fix some listbox bugs
This commit is contained in:
parent
2988d3e16c
commit
b890f2fad7
@ -96,6 +96,7 @@
|
|||||||
<Unit filename="../../source/gui/widgets/picture.cpp" />
|
<Unit filename="../../source/gui/widgets/picture.cpp" />
|
||||||
<Unit filename="../../source/gui/widgets/progress.cpp" />
|
<Unit filename="../../source/gui/widgets/progress.cpp" />
|
||||||
<Unit filename="../../source/gui/widgets/scroll.cpp" />
|
<Unit filename="../../source/gui/widgets/scroll.cpp" />
|
||||||
|
<Unit filename="../../source/gui/widgets/skeletons/content_view.cpp" />
|
||||||
<Unit filename="../../source/gui/widgets/skeletons/text_editor.cpp" />
|
<Unit filename="../../source/gui/widgets/skeletons/text_editor.cpp" />
|
||||||
<Unit filename="../../source/gui/widgets/slider.cpp" />
|
<Unit filename="../../source/gui/widgets/slider.cpp" />
|
||||||
<Unit filename="../../source/gui/widgets/spinbox.cpp" />
|
<Unit filename="../../source/gui/widgets/spinbox.cpp" />
|
||||||
|
|||||||
@ -232,6 +232,7 @@
|
|||||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
||||||
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
||||||
|
|||||||
@ -327,6 +327,9 @@
|
|||||||
<ClCompile Include="..\..\source\stdc++.cpp">
|
<ClCompile Include="..\..\source\stdc++.cpp">
|
||||||
<Filter>Source Files\nana</Filter>
|
<Filter>Source Files\nana</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
|
||||||
|
<Filter>Source Files\nana\gui\widgets\skeletons</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
<ClCompile Include="..\..\source\gui\widgets\group.cpp">
|
||||||
|
|||||||
@ -226,6 +226,7 @@
|
|||||||
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\picture.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\progress.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\scroll.cpp" />
|
||||||
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\text_editor.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\slider.cpp" />
|
||||||
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
<ClCompile Include="..\..\source\gui\widgets\spinbox.cpp" />
|
||||||
|
|||||||
@ -285,5 +285,8 @@
|
|||||||
<ClCompile Include="..\..\source\stdc++.cpp">
|
<ClCompile Include="..\..\source\stdc++.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\source\gui\widgets\skeletons\content_view.cpp">
|
||||||
|
<Filter>Source Files\gui\widgets\skeletons</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@ -805,7 +805,7 @@ namespace nana
|
|||||||
: public std::iterator<std::input_iterator_tag, item_proxy>
|
: public std::iterator<std::input_iterator_tag, item_proxy>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
item_proxy(essence*, const index_pair& = index_pair{});
|
item_proxy(essence*, const index_pair& = index_pair{npos, npos});
|
||||||
|
|
||||||
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
/// the main porpose of this it to make obvious that item_proxy operate with absolute positions, and dont get moved during sort()
|
||||||
static item_proxy from_display(essence *, const index_pair &relative) ;
|
static item_proxy from_display(essence *, const index_pair &relative) ;
|
||||||
|
|||||||
@ -125,6 +125,7 @@ namespace std {
|
|||||||
|
|
||||||
#ifdef _enable_std_put_time
|
#ifdef _enable_std_put_time
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <string>
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
//Workaround for no implemenation of std::put_time in gcc < 5.
|
//Workaround for no implemenation of std::put_time in gcc < 5.
|
||||||
|
|||||||
@ -19,7 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nana/gui/widgets/listbox.hpp>
|
#include <nana/gui/widgets/listbox.hpp>
|
||||||
#include <nana/gui/widgets/scroll.hpp>
|
|
||||||
#include <nana/gui/widgets/panel.hpp> //for inline widget
|
#include <nana/gui/widgets/panel.hpp> //for inline widget
|
||||||
|
|
||||||
#include <nana/gui/layout_utility.hpp>
|
#include <nana/gui/layout_utility.hpp>
|
||||||
@ -27,11 +26,12 @@
|
|||||||
#include <nana/paint/text_renderer.hpp>
|
#include <nana/paint/text_renderer.hpp>
|
||||||
#include <nana/system/dataexch.hpp>
|
#include <nana/system/dataexch.hpp>
|
||||||
#include <nana/system/platform.hpp>
|
#include <nana/system/platform.hpp>
|
||||||
|
#include "skeletons/content_view.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
@ -42,406 +42,6 @@ namespace nana
|
|||||||
throw std::out_of_range("listbox: invalid element position");
|
throw std::out_of_range("listbox: invalid element position");
|
||||||
}
|
}
|
||||||
|
|
||||||
class intermediary
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct events_type
|
|
||||||
{
|
|
||||||
std::function<void(const point&)> hover_outside;
|
|
||||||
};
|
|
||||||
|
|
||||||
intermediary(window handle)
|
|
||||||
: window_handle_(handle)
|
|
||||||
{
|
|
||||||
API::events(handle).mouse_wheel([this](const arg_wheel& arg){
|
|
||||||
scroll_interface * scroll = nullptr;
|
|
||||||
switch (arg.which)
|
|
||||||
{
|
|
||||||
case arg_wheel::wheel::vertical:
|
|
||||||
scroll = &vert_;
|
|
||||||
break;
|
|
||||||
case arg_wheel::wheel::horizontal:
|
|
||||||
scroll = &horz_;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//Other button is not unsupported.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!API::empty_window(arg.window_handle))
|
|
||||||
{
|
|
||||||
auto align_px = (scroll->value() % scroll->step());
|
|
||||||
if (align_px)
|
|
||||||
{
|
|
||||||
auto new_value = scroll->value() - align_px;
|
|
||||||
if (!arg.upwards)
|
|
||||||
new_value += scroll->step();
|
|
||||||
|
|
||||||
scroll->value(new_value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
scroll->make_step(!arg.upwards, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
API::events(handle).mouse_move([this](const arg_mouse& arg)
|
|
||||||
{
|
|
||||||
if (!arg.is_left_button())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this->_m_drive(arg.pos))
|
|
||||||
{
|
|
||||||
tmr_.interval(16);
|
|
||||||
tmr_.start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tmr_.elapse([this](const arg_elapse&)
|
|
||||||
{
|
|
||||||
auto curs = ::nana::API::cursor_position();
|
|
||||||
::nana::API::calc_window_point(window_handle_, curs);
|
|
||||||
|
|
||||||
if (this->_m_drive(curs))
|
|
||||||
{
|
|
||||||
if (events_.hover_outside)
|
|
||||||
events_.hover_outside(curs);
|
|
||||||
|
|
||||||
API::refresh_window(window_handle_);
|
|
||||||
this->sync(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tmr_.stop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
events_type& events()
|
|
||||||
{
|
|
||||||
return events_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void step(unsigned step_value, bool horz)
|
|
||||||
{
|
|
||||||
if (horz)
|
|
||||||
horz_.step(step_value);
|
|
||||||
else
|
|
||||||
vert_.step(step_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool turn_page(bool forwards, bool horz)
|
|
||||||
{
|
|
||||||
if (horz)
|
|
||||||
return horz_.make_page_scroll(forwards);
|
|
||||||
else
|
|
||||||
return vert_.make_page_scroll(forwards);
|
|
||||||
}
|
|
||||||
|
|
||||||
void disp_area(const rectangle& da, const point& skew_horz, const point& skew_vert, const size& extra_px, bool try_update = true)
|
|
||||||
{
|
|
||||||
if (disp_area_ != da)
|
|
||||||
{
|
|
||||||
disp_area_ = da;
|
|
||||||
skew_horz_ = skew_horz;
|
|
||||||
skew_vert_ = skew_vert;
|
|
||||||
extra_px_ = extra_px;
|
|
||||||
|
|
||||||
auto imd_area = this->intermediary_area();
|
|
||||||
if (static_cast<int>(content_size_.width) - origin_.x < static_cast<int>(imd_area.width))
|
|
||||||
{
|
|
||||||
origin_.x = static_cast<int>(content_size_.width) - static_cast<int>(imd_area.width);
|
|
||||||
if (origin_.x < 0)
|
|
||||||
origin_.x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static_cast<int>(content_size_.height) - origin_.y < static_cast<int>(imd_area.height))
|
|
||||||
{
|
|
||||||
origin_.y = static_cast<int>(content_size_.height) - static_cast<int>(imd_area.height);
|
|
||||||
if (origin_.y < 0)
|
|
||||||
origin_.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_m_size_changed(try_update);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void content_size(const size& sz, bool try_update = true)
|
|
||||||
{
|
|
||||||
content_size_ = sz;
|
|
||||||
_m_size_changed(try_update);
|
|
||||||
}
|
|
||||||
|
|
||||||
const point& origin() const
|
|
||||||
{
|
|
||||||
return origin_;
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle corner() const
|
|
||||||
{
|
|
||||||
rectangle r;
|
|
||||||
|
|
||||||
auto imd_area = this->intermediary_area();
|
|
||||||
|
|
||||||
r.x = disp_area_.x + static_cast<int>(imd_area.width) + skew_vert_.x;
|
|
||||||
r.y = disp_area_.y + static_cast<int>(imd_area.height) + skew_horz_.y;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned extra_horz = (disp_area_.width < content_size_.width ? _m_extra_px() : 0);
|
|
||||||
unsigned extra_vert = (disp_area_.height < content_size_.height + extra_horz ? _m_extra_px() : 0);
|
|
||||||
|
|
||||||
if ((0 == extra_horz) && extra_vert)
|
|
||||||
extra_horz = (disp_area_.width < content_size_.width + extra_vert ? _m_extra_px() : 0);
|
|
||||||
|
|
||||||
r.width = extra_horz;
|
|
||||||
r.height = extra_vert;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
rectangle intermediary_area() const
|
|
||||||
{
|
|
||||||
unsigned extra_horz = (disp_area_.width < content_size_.width ? _m_extra_px() : 0);
|
|
||||||
unsigned extra_vert = (disp_area_.height < content_size_.height + extra_horz ? _m_extra_px() : 0);
|
|
||||||
|
|
||||||
if ((0 == extra_horz) && extra_vert)
|
|
||||||
extra_horz = (disp_area_.width < content_size_.width + extra_vert ? _m_extra_px() : 0);
|
|
||||||
|
|
||||||
return rectangle{
|
|
||||||
disp_area_.position(),
|
|
||||||
size{
|
|
||||||
disp_area_.width > extra_vert ? disp_area_.width - extra_vert : 0,
|
|
||||||
disp_area_.height > extra_horz ? disp_area_.height - extra_horz : 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned extra_space(bool horz) const
|
|
||||||
{
|
|
||||||
return ((horz ? horz_.empty() : vert_.empty()) ? 0 : _m_extra_px());
|
|
||||||
}
|
|
||||||
|
|
||||||
void change_position(int pos, bool aligned, bool horz)
|
|
||||||
{
|
|
||||||
if (aligned)
|
|
||||||
pos -= (pos % static_cast<int>(horz ? horz_.step() : vert_.step()));
|
|
||||||
|
|
||||||
auto imd_size = this->intermediary_area();
|
|
||||||
|
|
||||||
if (horz)
|
|
||||||
{
|
|
||||||
if (pos + imd_size.width > content_size_.width)
|
|
||||||
pos = static_cast<int>(content_size_.width) - static_cast<int>(imd_size.width);
|
|
||||||
|
|
||||||
if (pos < 0) pos = 0;
|
|
||||||
|
|
||||||
origin_.x = pos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pos + imd_size.height > content_size_.height)
|
|
||||||
pos = static_cast<int>(content_size_.height) - static_cast<int>(imd_size.height);
|
|
||||||
|
|
||||||
if (pos < 0) pos = 0;
|
|
||||||
|
|
||||||
origin_.y = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void move_origin(const point& skew)
|
|
||||||
{
|
|
||||||
auto imd_area = this->intermediary_area();
|
|
||||||
|
|
||||||
origin_.x += skew.x;
|
|
||||||
if (origin_.x + imd_area.width > content_size_.width)
|
|
||||||
origin_.x = static_cast<int>(content_size_.width) - static_cast<int>(imd_area.width);
|
|
||||||
|
|
||||||
if (origin_.x < 0) origin_.x = 0;
|
|
||||||
|
|
||||||
|
|
||||||
origin_.y += skew.y;
|
|
||||||
if (origin_.y + imd_area.height > content_size_.height)
|
|
||||||
origin_.y = static_cast<int>(content_size_.height) - static_cast<int>(imd_area.height);
|
|
||||||
|
|
||||||
if (origin_.y < 0) origin_.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sync(bool try_update)
|
|
||||||
{
|
|
||||||
this->enable_update_ = try_update;
|
|
||||||
horz_.value(origin_.x);
|
|
||||||
vert_.value(origin_.y);
|
|
||||||
this->enable_update_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pursue(const point& cursor)
|
|
||||||
{
|
|
||||||
if (disp_area_.is_hit(cursor))
|
|
||||||
return;
|
|
||||||
|
|
||||||
int delta = 0;
|
|
||||||
if (cursor.x < disp_area_.x)
|
|
||||||
delta = cursor.x - disp_area_.x;
|
|
||||||
else if (cursor.x > disp_area_.right())
|
|
||||||
delta = cursor.x - disp_area_.right();
|
|
||||||
|
|
||||||
origin_.x += delta;
|
|
||||||
if (origin_.x < 0)
|
|
||||||
origin_.x = 0;
|
|
||||||
|
|
||||||
if (cursor.y < disp_area_.y)
|
|
||||||
delta = cursor.y - disp_area_.y;
|
|
||||||
else if (cursor.y > disp_area_.bottom())
|
|
||||||
delta = cursor.y - disp_area_.bottom();
|
|
||||||
|
|
||||||
origin_.y += delta;
|
|
||||||
if (origin_.y < 0)
|
|
||||||
origin_.y = 0;
|
|
||||||
|
|
||||||
bool changed = false;
|
|
||||||
if (!horz_.empty() && (static_cast<long long>(horz_.value()) != origin_.x))
|
|
||||||
{
|
|
||||||
horz_.value(origin_.x);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!vert_.empty()) && (static_cast<long long>(vert_.value()) != origin_.y))
|
|
||||||
{
|
|
||||||
vert_.value(origin_.y);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
API::refresh_window(window_handle_);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
static constexpr unsigned _m_extra_px()
|
|
||||||
{
|
|
||||||
return 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _m_drive(const point& cursor_pos)
|
|
||||||
{
|
|
||||||
auto const imd_area = this->intermediary_area();
|
|
||||||
|
|
||||||
point skew;
|
|
||||||
|
|
||||||
if (disp_area_.x > cursor_pos.x)
|
|
||||||
skew.x = cursor_pos.x - disp_area_.x;
|
|
||||||
else if (cursor_pos.x > disp_area_.x + static_cast<int>(imd_area.width))
|
|
||||||
skew.x = cursor_pos.x - (disp_area_.x + static_cast<int>(imd_area.width));
|
|
||||||
|
|
||||||
if (disp_area_.y > cursor_pos.y)
|
|
||||||
skew.y = cursor_pos.y - disp_area_.y;
|
|
||||||
else if (cursor_pos.y > disp_area_.y + static_cast<int>(imd_area.height))
|
|
||||||
skew.y = cursor_pos.y - (disp_area_.y + static_cast<int>(imd_area.height));
|
|
||||||
|
|
||||||
if (skew.x == 0 && skew.y == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
auto speed_horz = 0;
|
|
||||||
if (skew.x)
|
|
||||||
speed_horz = skew.x / (std::max)(1, static_cast<int>(horz_.step())) + (skew.x < 0 ? -1 : 1);
|
|
||||||
|
|
||||||
auto speed_vert = 0;
|
|
||||||
if(skew.y)
|
|
||||||
speed_vert = skew.y / (std::max)(1, static_cast<int>(vert_.step())) + (skew.y < 0 ? -1 : 1);
|
|
||||||
|
|
||||||
speed_horz = (std::min)(5, (std::max)(speed_horz, -5));
|
|
||||||
speed_vert = (std::min)(5, (std::max)(speed_vert, -5));
|
|
||||||
|
|
||||||
move_origin({
|
|
||||||
speed_horz, speed_vert
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _m_size_changed(bool try_update)
|
|
||||||
{
|
|
||||||
auto imd_area = intermediary_area();
|
|
||||||
|
|
||||||
//event hander for scrollbars
|
|
||||||
auto event_fn = [this](const arg_scroll& arg)
|
|
||||||
{
|
|
||||||
if (arg.window_handle == this->vert_.handle())
|
|
||||||
origin_.y = static_cast<int>(this->vert_.value());
|
|
||||||
else
|
|
||||||
origin_.x = static_cast<int>(this->horz_.value());
|
|
||||||
|
|
||||||
if (this->enable_update_)
|
|
||||||
{
|
|
||||||
API::refresh_window(this->window_handle_);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this->enable_update_ = try_update;
|
|
||||||
|
|
||||||
if (imd_area.width != disp_area_.width)
|
|
||||||
{
|
|
||||||
if (vert_.empty())
|
|
||||||
{
|
|
||||||
vert_.create(window_handle_);
|
|
||||||
vert_.events().value_changed.connect_unignorable(event_fn);
|
|
||||||
this->enable_update_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
vert_.move({
|
|
||||||
disp_area_.x + static_cast<int>(imd_area.width) + skew_vert_.x,
|
|
||||||
disp_area_.y + skew_vert_.y,
|
|
||||||
_m_extra_px(),
|
|
||||||
imd_area.height + extra_px_.height
|
|
||||||
});
|
|
||||||
|
|
||||||
vert_.amount(content_size_.height);
|
|
||||||
vert_.range(imd_area.height);
|
|
||||||
vert_.value(origin_.y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vert_.close();
|
|
||||||
|
|
||||||
if (imd_area.height != disp_area_.height)
|
|
||||||
{
|
|
||||||
if (horz_.empty())
|
|
||||||
{
|
|
||||||
horz_.create(window_handle_);
|
|
||||||
horz_.events().value_changed.connect_unignorable(event_fn);
|
|
||||||
this->enable_update_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
horz_.move({
|
|
||||||
disp_area_.x + skew_horz_.x,
|
|
||||||
disp_area_.y + static_cast<int>(imd_area.height) + skew_horz_.y,
|
|
||||||
imd_area.width + extra_px_.width,
|
|
||||||
_m_extra_px()
|
|
||||||
});
|
|
||||||
|
|
||||||
horz_.amount(content_size_.width);
|
|
||||||
horz_.range(imd_area.width);
|
|
||||||
horz_.value(origin_.x);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
horz_.close();
|
|
||||||
|
|
||||||
this->enable_update_ = true;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
window const window_handle_;
|
|
||||||
nana::rectangle disp_area_;
|
|
||||||
nana::size content_size_;
|
|
||||||
|
|
||||||
point skew_horz_;
|
|
||||||
point skew_vert_;
|
|
||||||
nana::size extra_px_;
|
|
||||||
|
|
||||||
bool enable_update_{ true };
|
|
||||||
point origin_;
|
|
||||||
|
|
||||||
nana::scroll<false> horz_;
|
|
||||||
nana::scroll<true> vert_;
|
|
||||||
|
|
||||||
timer tmr_;
|
|
||||||
|
|
||||||
events_type events_;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace drawerbase
|
namespace drawerbase
|
||||||
{
|
{
|
||||||
namespace listbox
|
namespace listbox
|
||||||
@ -1632,56 +1232,35 @@ namespace nana
|
|||||||
index_pair advance(const index_pair& from, size_type offset) const
|
index_pair advance(const index_pair& from, size_type offset) const
|
||||||
{
|
{
|
||||||
const auto cat_size = categories_.size();
|
const auto cat_size = categories_.size();
|
||||||
index_pair dpos{npos, npos};
|
index_pair dpos{ npos, npos };
|
||||||
if (from.cat >= cat_size || (from.item != npos && from.item >= size_item(from.cat)))
|
if (from.cat >= cat_size || (from.item != npos && from.item >= size_item(from.cat)))
|
||||||
return dpos;
|
return dpos;
|
||||||
|
|
||||||
dpos = from;
|
if ((0 == from.cat && npos == from.item) || (!expand(from.cat) && (npos != from.item)))
|
||||||
|
|
||||||
while(offset)
|
|
||||||
{
|
|
||||||
if(dpos.item == npos)
|
|
||||||
{
|
|
||||||
if(expand(dpos.cat) == false)
|
|
||||||
{
|
|
||||||
if (dpos.cat + 1 == cat_size)
|
|
||||||
break;
|
|
||||||
++dpos.cat;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
dpos.item = 0;
|
|
||||||
--offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size_type rest = size_item(dpos.cat) - dpos.item - 1;
|
|
||||||
if(rest == 0)
|
|
||||||
{
|
|
||||||
if (dpos.cat + 1 == cat_size)
|
|
||||||
break;
|
|
||||||
++dpos.cat;
|
|
||||||
dpos.item = npos;
|
|
||||||
--offset;
|
|
||||||
}
|
|
||||||
else if(rest < offset)
|
|
||||||
{
|
|
||||||
offset -= rest;
|
|
||||||
if (dpos.cat + 1 >= cat_size)
|
|
||||||
{
|
|
||||||
dpos.item += rest;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dpos.item = npos;
|
|
||||||
++dpos.cat;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dpos.item += offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dpos;
|
return dpos;
|
||||||
|
|
||||||
|
if (0 == offset)
|
||||||
|
return from;
|
||||||
|
|
||||||
|
dpos = from;
|
||||||
|
std::size_t pos = (npos == from.item ? 0 : 1);
|
||||||
|
|
||||||
|
while (offset)
|
||||||
|
{
|
||||||
|
std::size_t end = 1;
|
||||||
|
if (expand(dpos.cat))
|
||||||
|
end += size_item(dpos.cat);
|
||||||
|
|
||||||
|
if (offset < end - pos)
|
||||||
|
{
|
||||||
|
return index_pair{ dpos.cat, pos + offset - 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
offset -= (end - pos);
|
||||||
|
pos = 0;
|
||||||
|
++dpos.cat;
|
||||||
|
}
|
||||||
|
return index_pair{ dpos.cat, npos };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// change to index arg
|
/// change to index arg
|
||||||
@ -1699,32 +1278,24 @@ namespace nana
|
|||||||
else if(to.cat < from.cat)
|
else if(to.cat < from.cat)
|
||||||
std::swap(from, to);
|
std::swap(from, to);
|
||||||
|
|
||||||
size_type n = 0;
|
std::size_t count = 1;
|
||||||
auto i = get(from.cat);
|
for (auto i = get(from.cat); i != get(to.cat); ++i)
|
||||||
if(from.item == npos)
|
|
||||||
{
|
{
|
||||||
if(i->expand)
|
if (i->expand)
|
||||||
n = i->items.size();
|
count += i->items.size() + 1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
n = i->items.size() - (from.item + 1);
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
for(++i, ++from.cat; i != categories_.cend(); ++i, ++from.cat)
|
if (npos != to.item)
|
||||||
{
|
count += (1 + to.item);
|
||||||
++n; //this is a category
|
|
||||||
if(from.cat != to.cat)
|
if (npos != from.item)
|
||||||
{
|
count -= (1 + from.item);
|
||||||
if(i->expand)
|
else if (0 == from.cat)
|
||||||
n += i->items.size();
|
--count;
|
||||||
}
|
|
||||||
else
|
return count - 1;
|
||||||
{
|
|
||||||
if(to.item != npos)
|
|
||||||
n += (to.item + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void text(category_t* cat, size_type pos, size_type abs_col, cell&& cl, size_type columns)
|
void text(category_t* cat, size_type pos, size_type abs_col, cell&& cl, size_type columns)
|
||||||
@ -1835,7 +1406,7 @@ namespace nana
|
|||||||
|
|
||||||
bool expand(size_type cat, bool exp) noexcept
|
bool expand(size_type cat, bool exp) noexcept
|
||||||
{
|
{
|
||||||
if(good(cat))
|
if(good(cat) && cat)
|
||||||
{
|
{
|
||||||
auto & expanded = get(cat)->expand;
|
auto & expanded = get(cat)->expand;
|
||||||
if(expanded != exp)
|
if(expanded != exp)
|
||||||
@ -2411,7 +1982,7 @@ namespace nana
|
|||||||
//if where == lister || where == checker, 'second' indicates the offset to the scroll offset_y which stands for the first item displayed in lister.
|
//if where == lister || where == checker, 'second' indicates the offset to the scroll offset_y which stands for the first item displayed in lister.
|
||||||
//if where == unknown, 'second' ignored.
|
//if where == unknown, 'second' ignored.
|
||||||
|
|
||||||
std::unique_ptr<intermediary> intermed;
|
std::unique_ptr<widgets::skeletons::content_view> content_view;
|
||||||
|
|
||||||
struct mouse_selection_part
|
struct mouse_selection_part
|
||||||
{
|
{
|
||||||
@ -2455,12 +2026,12 @@ namespace nana
|
|||||||
else
|
else
|
||||||
r.height -= head_px;
|
r.height -= head_px;
|
||||||
|
|
||||||
this->intermed->disp_area(r, { -1, 0 }, { 1, -static_cast<int>(head_px) }, { 2, head_px });
|
this->content_view->disp_area(r, { -1, 0 }, { 1, -static_cast<int>(head_px) }, { 2, head_px });
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type column_from_pos(int screen_x) const
|
size_type column_from_pos(int screen_x) const
|
||||||
{
|
{
|
||||||
return header.column_from_point(screen_x - content_area().x + intermed->origin().x);
|
return header.column_from_point(screen_x - content_area().x + content_view->origin().x);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string to_string(const export_options& exp_opt) const
|
std::string to_string(const export_options& exp_opt) const
|
||||||
@ -2475,14 +2046,14 @@ namespace nana
|
|||||||
|
|
||||||
index_pair first_display() const noexcept
|
index_pair first_display() const noexcept
|
||||||
{
|
{
|
||||||
auto offset_display = intermed->origin().y / item_height();
|
auto offset_display = content_view->origin().y / item_height();
|
||||||
return lister.advance(lister.first(), offset_display);
|
return lister.advance(lister.first(), offset_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned item_height() const noexcept
|
unsigned item_height() const noexcept
|
||||||
{
|
{
|
||||||
auto px = (std::max)(scheme_ptr->item_height_ex + text_height, unsigned(1));
|
auto px = (std::max)(scheme_ptr->item_height_ex + text_height, unsigned(1));
|
||||||
intermed->step(px, false);
|
content_view->step(px, false);
|
||||||
return px;
|
return px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2492,7 +2063,7 @@ namespace nana
|
|||||||
if (!rect_lister(orignal))
|
if (!rect_lister(orignal))
|
||||||
return{};
|
return{};
|
||||||
|
|
||||||
const auto origin = this->intermed->origin();
|
const auto origin = this->content_view->origin();
|
||||||
|
|
||||||
if (from_screen)
|
if (from_screen)
|
||||||
return from - orignal.position() + origin;
|
return from - orignal.position() + origin;
|
||||||
@ -2519,7 +2090,7 @@ namespace nana
|
|||||||
if (!rect_header(r))
|
if (!rect_header(r))
|
||||||
return{};
|
return{};
|
||||||
|
|
||||||
auto origin = intermed->origin();
|
auto origin = content_view->origin();
|
||||||
return{ r.x - origin.x, r.x - origin.x + static_cast<int>(header.pixels()) };
|
return{ r.x - origin.x, r.x - origin.x + static_cast<int>(header.pixels()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2541,7 +2112,7 @@ namespace nana
|
|||||||
mouse_selection.screen_pos = screen_pos;
|
mouse_selection.screen_pos = screen_pos;
|
||||||
|
|
||||||
auto logic_pos = coordinate_cast(screen_pos, true);
|
auto logic_pos = coordinate_cast(screen_pos, true);
|
||||||
auto imd_area = intermed->intermediary_area();
|
auto imd_area = content_view->view_area();
|
||||||
|
|
||||||
if (logic_pos.y > mouse_selection.begin_position.y)
|
if (logic_pos.y > mouse_selection.begin_position.y)
|
||||||
{
|
{
|
||||||
@ -2659,7 +2230,7 @@ namespace nana
|
|||||||
*/
|
*/
|
||||||
size_type count_of_exposed(bool with_rest) const
|
size_type count_of_exposed(bool with_rest) const
|
||||||
{
|
{
|
||||||
auto lister_s = this->intermed->intermediary_area().height;
|
auto lister_s = this->content_view->view_area().height;
|
||||||
return (lister_s / item_height()) + (with_rest && (lister_s % item_height()) ? 1 : 0);
|
return (lister_s / item_height()) + (with_rest && (lister_s % item_height()) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2681,7 +2252,7 @@ namespace nana
|
|||||||
|
|
||||||
ctt_size.height *= this->item_height();
|
ctt_size.height *= this->item_height();
|
||||||
|
|
||||||
this->intermed->content_size(ctt_size, try_update);
|
this->content_view->content_size(ctt_size, try_update);
|
||||||
|
|
||||||
return ctt_size;
|
return ctt_size;
|
||||||
}
|
}
|
||||||
@ -2698,7 +2269,19 @@ namespace nana
|
|||||||
if (seq.empty())
|
if (seq.empty())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (header.position(seq[0], nullptr) - this->intermed->origin().x + r.x);
|
return (header.position(seq[0], nullptr) - this->content_view->origin().x + r.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns the absolute coordinate of the specified item in the window
|
||||||
|
point item_coordinate(const index_pair& pos) const
|
||||||
|
{
|
||||||
|
auto top = static_cast<int>(this->lister.distance(index_pair{}, pos) * item_height()) - content_view->origin().y;
|
||||||
|
|
||||||
|
rectangle r;
|
||||||
|
if (rect_lister(r))
|
||||||
|
top += r.y;
|
||||||
|
|
||||||
|
return{ top, top + static_cast<int>(item_height()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<parts, size_t> where(const nana::point& pos) const noexcept
|
std::pair<parts, size_t> where(const nana::point& pos) const noexcept
|
||||||
@ -2709,7 +2292,7 @@ namespace nana
|
|||||||
|
|
||||||
if(area.is_hit(pos))
|
if(area.is_hit(pos))
|
||||||
{ /// we are inside
|
{ /// we are inside
|
||||||
auto const origin = intermed->origin();
|
auto const origin = content_view->origin();
|
||||||
|
|
||||||
if(header.visible() && (pos.y < static_cast<int>(scheme_ptr->header_height) + area.y))
|
if(header.visible() && (pos.y < static_cast<int>(scheme_ptr->header_height) + area.y))
|
||||||
{ /// we are in the header
|
{ /// we are in the header
|
||||||
@ -2719,14 +2302,17 @@ namespace nana
|
|||||||
else if (area.x <= pos.x + origin.x && pos.x + origin.x < area.x + static_cast<int>(header.pixels()))
|
else if (area.x <= pos.x + origin.x && pos.x + origin.x < area.x + static_cast<int>(header.pixels()))
|
||||||
{
|
{
|
||||||
new_where.first = parts::list;
|
new_where.first = parts::list;
|
||||||
new_where.second = (pos.y - area.y - header_visible_px()) / item_height();
|
|
||||||
|
auto const item_h = item_height();
|
||||||
|
//don't combine the following formula into the (pos.y - area.y - header_visible_px()) / item_h
|
||||||
|
new_where.second = ((pos.y - area.y - header_visible_px() + origin.y) / item_h) - (origin.y / item_h);
|
||||||
|
|
||||||
if (checkable)
|
if (checkable)
|
||||||
{
|
{
|
||||||
nana::rectangle r;
|
nana::rectangle r;
|
||||||
if (rect_lister(r))
|
if (rect_lister(r))
|
||||||
{
|
{
|
||||||
auto top = new_where.second * item_height() + header_visible_px();
|
auto top = new_where.second * item_h + header_visible_px();
|
||||||
if (checkarea(item_xpos(r), static_cast<int>(top)).is_hit(pos))
|
if (checkarea(item_xpos(r), static_cast<int>(top)).is_hit(pos))
|
||||||
new_where.first = parts::checker;
|
new_where.first = parts::checker;
|
||||||
}
|
}
|
||||||
@ -2752,7 +2338,7 @@ namespace nana
|
|||||||
void widget_to_header(nana::point& pos) noexcept
|
void widget_to_header(nana::point& pos) noexcept
|
||||||
{
|
{
|
||||||
--pos.y;
|
--pos.y;
|
||||||
pos.x += this->intermed->origin().x - 2;
|
pos.x += this->content_view->origin().x - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_peripheral()
|
void draw_peripheral()
|
||||||
@ -2768,7 +2354,7 @@ namespace nana
|
|||||||
graph->line({ ctt_area.right(), ctt_area.y }, { ctt_area.right(), ctt_area.bottom() - 1 });
|
graph->line({ ctt_area.right(), ctt_area.y }, { ctt_area.right(), ctt_area.bottom() - 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r = this->intermed->corner();
|
auto r = this->content_view->corner();
|
||||||
if (!r.empty())
|
if (!r.empty())
|
||||||
graph->rectangle(r, true, colors::button_face);
|
graph->rectangle(r, true, colors::button_face);
|
||||||
}
|
}
|
||||||
@ -2804,7 +2390,7 @@ namespace nana
|
|||||||
if (lister.wd_ptr()->borderless())
|
if (lister.wd_ptr()->borderless())
|
||||||
return !r.empty();
|
return !r.empty();
|
||||||
|
|
||||||
auto exs = this->intermed->extra_space(false);
|
auto exs = this->content_view->extra_space(false);
|
||||||
const unsigned ex_width = (exs ? exs - 1 : 0);
|
const unsigned ex_width = (exs ? exs - 1 : 0);
|
||||||
|
|
||||||
if(r.width > ex_width)
|
if(r.width > ex_width)
|
||||||
@ -2820,8 +2406,8 @@ namespace nana
|
|||||||
{
|
{
|
||||||
auto head_pixels = header_visible_px();
|
auto head_pixels = header_visible_px();
|
||||||
|
|
||||||
auto exs_vert = this->intermed->extra_space(false);
|
auto exs_vert = this->content_view->extra_space(false);
|
||||||
auto exs_horz = this->intermed->extra_space(true);
|
auto exs_horz = this->content_view->extra_space(true);
|
||||||
|
|
||||||
unsigned extr_w = (exs_vert ? exs_vert - 1 : 0);
|
unsigned extr_w = (exs_vert ? exs_vert - 1 : 0);
|
||||||
unsigned extr_h = exs_horz + head_pixels;
|
unsigned extr_h = exs_horz + head_pixels;
|
||||||
@ -2842,7 +2428,7 @@ namespace nana
|
|||||||
std::vector<size_type> header_seq(unsigned lister_w) const
|
std::vector<size_type> header_seq(unsigned lister_w) const
|
||||||
{
|
{
|
||||||
std::vector<size_type> seqs;
|
std::vector<size_type> seqs;
|
||||||
int x = -intermed->origin().x;
|
int x = -content_view->origin().x;
|
||||||
|
|
||||||
for (const auto& col : header.cont())
|
for (const auto& col : header.cont())
|
||||||
{
|
{
|
||||||
@ -3282,7 +2868,7 @@ namespace nana
|
|||||||
|
|
||||||
void hovered(index_type /*pos*/) override
|
void hovered(index_type /*pos*/) override
|
||||||
{
|
{
|
||||||
auto offset = ess_->intermed->origin().y / ess_->item_height();
|
auto offset = ess_->content_view->origin().y / ess_->item_height();
|
||||||
|
|
||||||
if (ess_->pointer_where.first != parts::list || ess_->pointer_where.second != offset)
|
if (ess_->pointer_where.first != parts::list || ess_->pointer_where.second != offset)
|
||||||
{
|
{
|
||||||
@ -3310,7 +2896,7 @@ namespace nana
|
|||||||
ess_->calc_content_size();
|
ess_->calc_content_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
ess_->intermed->turn_page(to_bottom, false);
|
ess_->content_view->turn_page(to_bottom, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void es_lister::erase(const index_pair& pos)
|
void es_lister::erase(const index_pair& pos)
|
||||||
@ -3501,7 +3087,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
if(essence_->ptr_state == item_state::highlighted)
|
if(essence_->ptr_state == item_state::highlighted)
|
||||||
{
|
{
|
||||||
x -= r.x - essence_->intermed->origin().x;
|
x -= r.x - essence_->content_view->origin().x;
|
||||||
|
|
||||||
for(auto & col : essence_->header.cont()) // in current order
|
for(auto & col : essence_->header.cont()) // in current order
|
||||||
{
|
{
|
||||||
@ -3594,7 +3180,7 @@ namespace nana
|
|||||||
state = essence_->ptr_state;
|
state = essence_->ptr_state;
|
||||||
|
|
||||||
rectangle column_r{
|
rectangle column_r{
|
||||||
r.x - essence_->intermed->origin().x, r.y,
|
r.x - essence_->content_view->origin().x, r.y,
|
||||||
0, r.height - 1
|
0, r.height - 1
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3643,7 +3229,7 @@ namespace nana
|
|||||||
size_type _m_target_strip(int x, const nana::rectangle& rect, size_type grab, bool& place_front)
|
size_type _m_target_strip(int x, const nana::rectangle& rect, size_type grab, bool& place_front)
|
||||||
{
|
{
|
||||||
//convert x to header logic coordinate.
|
//convert x to header logic coordinate.
|
||||||
auto const x_offset = essence_->intermed->origin().x;
|
auto const x_offset = essence_->content_view->origin().x;
|
||||||
if (x < x_offset)
|
if (x < x_offset)
|
||||||
x = x_offset;
|
x = x_offset;
|
||||||
else if (x > x_offset + static_cast<int>(rect.width))
|
else if (x > x_offset + static_cast<int>(rect.width))
|
||||||
@ -3727,7 +3313,7 @@ namespace nana
|
|||||||
|
|
||||||
auto xpos = essence_->header.position(col.index, nullptr) + pos.x - grabs_.start_pos;
|
auto xpos = essence_->header.position(col.index, nullptr) + pos.x - grabs_.start_pos;
|
||||||
|
|
||||||
fl_graph.blend(rectangle{ fl_graph.size() }, *(essence_->graph), point{ xpos - essence_->intermed->origin().x + rect.x, rect.y }, 0.5);
|
fl_graph.blend(rectangle{ fl_graph.size() }, *(essence_->graph), point{ xpos - essence_->content_view->origin().x + rect.x, rect.y }, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -3785,7 +3371,7 @@ namespace nana
|
|||||||
|
|
||||||
auto const header_w = essence_->header.pixels();
|
auto const header_w = essence_->header.pixels();
|
||||||
|
|
||||||
auto origin = essence_->intermed->origin();
|
auto origin = essence_->content_view->origin();
|
||||||
if (header_w < origin.x + rect.width)
|
if (header_w < origin.x + rect.width)
|
||||||
essence_->graph->rectangle(rectangle{ point{ rect.x + static_cast<int>(header_w) - origin.x, rect.y },
|
essence_->graph->rectangle(rectangle{ point{ rect.x + static_cast<int>(header_w) - origin.x, rect.y },
|
||||||
size{ rect.width + origin.x - header_w, rect.height } }, true);
|
size{ rect.width + origin.x - header_w, rect.height } }, true);
|
||||||
@ -3960,7 +3546,7 @@ namespace nana
|
|||||||
|
|
||||||
//Draw selecting inner rectangle
|
//Draw selecting inner rectangle
|
||||||
if (sel && (categ.expand == false))
|
if (sel && (categ.expand == false))
|
||||||
_m_draw_item_border(r.x, y, (std::min)(r.width, width - essence_->intermed->origin().x));
|
_m_draw_item_border(r.x, y, (std::min)(r.width, width - essence_->content_view->origin().x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws an item
|
/// Draws an item
|
||||||
@ -4003,7 +3589,7 @@ namespace nana
|
|||||||
bgcolor = bgcolor.blend(essence_->scheme_ptr->item_highlighted, 0.7);/// \todo create a parametre for amount of blend
|
bgcolor = bgcolor.blend(essence_->scheme_ptr->item_highlighted, 0.7);/// \todo create a parametre for amount of blend
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned show_w = (std::min)(content_r.width, width - essence_->intermed->origin().x);
|
const unsigned show_w = (std::min)(content_r.width, width - essence_->content_view->origin().x);
|
||||||
|
|
||||||
auto graph = essence_->graph;
|
auto graph = essence_->graph;
|
||||||
|
|
||||||
@ -4260,10 +3846,10 @@ namespace nana
|
|||||||
essence_->lister.bind(essence_, widget);
|
essence_->lister.bind(essence_, widget);
|
||||||
widget.bgcolor(colors::white);
|
widget.bgcolor(colors::white);
|
||||||
|
|
||||||
essence_->intermed.reset(new intermediary(widget));
|
essence_->content_view.reset(new widgets::skeletons::content_view{ widget.handle() });
|
||||||
essence_->resize_disp_area();
|
essence_->resize_disp_area();
|
||||||
|
|
||||||
essence_->intermed->events().hover_outside = [this](const point& cur_pos) {
|
essence_->content_view->events().hover_outside = [this](const point& cur_pos) {
|
||||||
essence_->update_mouse_selection(cur_pos);
|
essence_->update_mouse_selection(cur_pos);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -4403,14 +3989,17 @@ namespace nana
|
|||||||
|
|
||||||
auto & lister = essence_->lister;
|
auto & lister = essence_->lister;
|
||||||
|
|
||||||
|
rectangle head_r, list_r;
|
||||||
|
auto const good_head_r = essence_->rect_header(head_r);
|
||||||
|
auto const good_list_r = essence_->rect_lister(list_r);
|
||||||
|
|
||||||
auto & ptr_where = essence_->pointer_where;
|
auto & ptr_where = essence_->pointer_where;
|
||||||
if((ptr_where.first == parts::header) && (ptr_where.second != npos || (drawer_header_->splitter() != npos)))
|
if((ptr_where.first == parts::header) && (ptr_where.second != npos || (drawer_header_->splitter() != npos)))
|
||||||
{
|
{
|
||||||
essence_->ptr_state = item_state::pressed;
|
essence_->ptr_state = item_state::pressed;
|
||||||
nana::rectangle r;
|
if(good_head_r)
|
||||||
if(essence_->rect_header(r))
|
|
||||||
{
|
{
|
||||||
drawer_header_->draw(graph, r);
|
drawer_header_->draw(graph, head_r);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4426,6 +4015,18 @@ namespace nana
|
|||||||
|
|
||||||
if(ptr_where.first == parts::list)
|
if(ptr_where.first == parts::list)
|
||||||
{
|
{
|
||||||
|
//adjust the display of selected into the list rectangle if the part of the item is beyond the top/bottom edge
|
||||||
|
if (good_list_r)
|
||||||
|
{
|
||||||
|
auto item_coord = this->essence_->item_coordinate(abs_item_pos); //item_coord.x = top, item_coord.y = bottom
|
||||||
|
if (item_coord.x < list_r.y && list_r.y < item_coord.y)
|
||||||
|
essence_->content_view->move_origin({ 0, item_coord.x - list_r.y });
|
||||||
|
else if (item_coord.x < list_r.bottom() && list_r.bottom() < item_coord.y)
|
||||||
|
essence_->content_view->move_origin({ 0, item_coord.y - list_r.bottom() });
|
||||||
|
|
||||||
|
essence_->content_view->sync(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool sel = true;
|
bool sel = true;
|
||||||
|
|
||||||
//no single selected
|
//no single selected
|
||||||
@ -4532,10 +4133,14 @@ namespace nana
|
|||||||
|
|
||||||
if(update)
|
if(update)
|
||||||
{
|
{
|
||||||
nana::rectangle r;
|
if (good_list_r)
|
||||||
update = essence_->rect_lister(r);
|
{
|
||||||
if(update)
|
drawer_lister_->draw(list_r);
|
||||||
drawer_lister_->draw(r);
|
if (good_head_r)
|
||||||
|
drawer_header_->draw(graph, head_r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
update = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ptr_where.first == parts::list_blank) //not selected
|
else if (ptr_where.first == parts::list_blank) //not selected
|
||||||
@ -4543,14 +4148,7 @@ namespace nana
|
|||||||
if (arg.is_left_button() && (!lister.single_status(true)))
|
if (arg.is_left_button() && (!lister.single_status(true)))
|
||||||
essence_->start_mouse_selection(arg.pos);
|
essence_->start_mouse_selection(arg.pos);
|
||||||
|
|
||||||
|
lister.select_for_all(false);
|
||||||
if (lister.select_for_all(false))
|
|
||||||
{
|
|
||||||
nana::rectangle r;
|
|
||||||
update = essence_->rect_lister(r);
|
|
||||||
if (update)
|
|
||||||
drawer_lister_->draw(r);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(update)
|
if(update)
|
||||||
@ -4646,12 +4244,12 @@ namespace nana
|
|||||||
if (lister.backward(last, n, last))
|
if (lister.backward(last, n, last))
|
||||||
{
|
{
|
||||||
auto px = lister.distance(lister.first(), last) * essence_->item_height();
|
auto px = lister.distance(lister.first(), last) * essence_->item_height();
|
||||||
essence_->intermed->change_position(static_cast<int>(px), true, false);
|
essence_->content_view->change_position(static_cast<int>(px), true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
essence_->calc_content_size(false);
|
essence_->calc_content_size(false);
|
||||||
essence_->intermed->sync(false);
|
essence_->content_view->sync(false);
|
||||||
refresh(graph);
|
refresh(graph);
|
||||||
API::dev::lazy_refresh();
|
API::dev::lazy_refresh();
|
||||||
}
|
}
|
||||||
@ -4693,7 +4291,7 @@ namespace nana
|
|||||||
case keyboard::os_pagedown:
|
case keyboard::os_pagedown:
|
||||||
{
|
{
|
||||||
//Turns page, then returns if no change occurs
|
//Turns page, then returns if no change occurs
|
||||||
if (!essence_->intermed->turn_page(!up, false))
|
if (!essence_->content_view->turn_page(!up, false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
essence_->lister.select_for_all(false);
|
essence_->lister.select_for_all(false);
|
||||||
@ -5698,7 +5296,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
auto & ess = _m_ess();
|
auto & ess = _m_ess();
|
||||||
|
|
||||||
auto origin = ess.intermed->origin();
|
auto origin = ess.content_view->origin();
|
||||||
|
|
||||||
int new_pos = origin.y;
|
int new_pos = origin.y;
|
||||||
|
|
||||||
@ -5712,8 +5310,8 @@ namespace nana
|
|||||||
ess.lister.clear(cat);
|
ess.lister.clear(cat);
|
||||||
|
|
||||||
ess.calc_content_size(false);
|
ess.calc_content_size(false);
|
||||||
ess.intermed->change_position(new_pos, false, false);
|
ess.content_view->change_position(new_pos, false, false);
|
||||||
ess.intermed->sync(false);
|
ess.content_view->sync(false);
|
||||||
ess.update();
|
ess.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5725,8 +5323,8 @@ namespace nana
|
|||||||
unsort(); // apperar to be espected
|
unsort(); // apperar to be espected
|
||||||
|
|
||||||
ess.calc_content_size(false);
|
ess.calc_content_size(false);
|
||||||
ess.intermed->change_position(0, false, false);
|
ess.content_view->change_position(0, false, false);
|
||||||
ess.intermed->sync(false);
|
ess.content_view->sync(false);
|
||||||
|
|
||||||
ess.update();
|
ess.update();
|
||||||
}
|
}
|
||||||
@ -5735,7 +5333,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
auto & ess = _m_ess();
|
auto & ess = _m_ess();
|
||||||
|
|
||||||
auto origin = ess.intermed->origin();
|
auto origin = ess.content_view->origin();
|
||||||
|
|
||||||
auto start_pos = ess.content_position(index_pair{ cat, npos });
|
auto start_pos = ess.content_position(index_pair{ cat, npos });
|
||||||
|
|
||||||
@ -5749,8 +5347,8 @@ namespace nana
|
|||||||
ess.lister.erase(cat);
|
ess.lister.erase(cat);
|
||||||
|
|
||||||
ess.calc_content_size(false);
|
ess.calc_content_size(false);
|
||||||
ess.intermed->change_position(new_pos, false, false);
|
ess.content_view->change_position(new_pos, false, false);
|
||||||
ess.intermed->sync(false);
|
ess.content_view->sync(false);
|
||||||
|
|
||||||
ess.update();
|
ess.update();
|
||||||
}
|
}
|
||||||
@ -5773,7 +5371,7 @@ namespace nana
|
|||||||
|
|
||||||
auto & ess = _m_ess();
|
auto & ess = _m_ess();
|
||||||
|
|
||||||
auto const origin = ess.intermed->origin();
|
auto const origin = ess.content_view->origin();
|
||||||
|
|
||||||
for (auto & pos : indexes)
|
for (auto & pos : indexes)
|
||||||
{
|
{
|
||||||
@ -5802,8 +5400,8 @@ namespace nana
|
|||||||
}
|
}
|
||||||
|
|
||||||
ess.calc_content_size(false);
|
ess.calc_content_size(false);
|
||||||
ess.intermed->change_position(origin.y, false, false);
|
ess.content_view->change_position(origin.y, false, false);
|
||||||
ess.intermed->sync(false);
|
ess.content_view->sync(false);
|
||||||
|
|
||||||
ess.lister.sort();
|
ess.lister.sort();
|
||||||
|
|
||||||
@ -5818,14 +5416,14 @@ namespace nana
|
|||||||
auto * ess = ip._m_ess();
|
auto * ess = ip._m_ess();
|
||||||
auto _where = ip.pos();
|
auto _where = ip.pos();
|
||||||
|
|
||||||
auto origin = ess->intermed->origin();
|
auto origin = ess->content_view->origin();
|
||||||
auto start_pos = ess->content_position(_where);
|
auto start_pos = ess->content_position(_where);
|
||||||
if (start_pos < origin.y)
|
if (start_pos < origin.y)
|
||||||
origin.y -= ess->item_height();
|
origin.y -= ess->item_height();
|
||||||
|
|
||||||
ess->calc_content_size(false);
|
ess->calc_content_size(false);
|
||||||
ess->intermed->change_position(origin.y, false, false);
|
ess->content_view->change_position(origin.y, false, false);
|
||||||
ess->intermed->sync(false);
|
ess->content_view->sync(false);
|
||||||
|
|
||||||
ess->update();
|
ess->update();
|
||||||
if(_where.item < ess->lister.size_item(_where.cat))
|
if(_where.item < ess->lister.size_item(_where.cat))
|
||||||
|
|||||||
451
source/gui/widgets/skeletons/content_view.cpp
Normal file
451
source/gui/widgets/skeletons/content_view.cpp
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
/*
|
||||||
|
* A Content View Implementation
|
||||||
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
|
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* @file: nana/gui/widgets/skeletons/content_view.hpp
|
||||||
|
* @author: Jinhao
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "content_view.hpp"
|
||||||
|
#include <nana/gui/widgets/scroll.hpp>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace nana {
|
||||||
|
namespace widgets {
|
||||||
|
namespace skeletons
|
||||||
|
{
|
||||||
|
struct content_view::implementation
|
||||||
|
{
|
||||||
|
content_view& view;
|
||||||
|
window const window_handle;
|
||||||
|
nana::rectangle disp_area;
|
||||||
|
nana::size content_size;
|
||||||
|
|
||||||
|
point skew_horz;
|
||||||
|
point skew_vert;
|
||||||
|
nana::size extra_px;
|
||||||
|
|
||||||
|
bool enable_update{ true };
|
||||||
|
point origin;
|
||||||
|
|
||||||
|
nana::scroll<false> horz;
|
||||||
|
nana::scroll<true> vert;
|
||||||
|
|
||||||
|
timer tmr;
|
||||||
|
|
||||||
|
events_type events;
|
||||||
|
|
||||||
|
struct conf_provider
|
||||||
|
{
|
||||||
|
std::function<unsigned()> wheel_speed;
|
||||||
|
}provider;
|
||||||
|
|
||||||
|
implementation(content_view& v, window handle) :
|
||||||
|
view(v),
|
||||||
|
window_handle(handle)
|
||||||
|
{
|
||||||
|
API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) {
|
||||||
|
scroll_interface * scroll = nullptr;
|
||||||
|
switch (arg.which)
|
||||||
|
{
|
||||||
|
case arg_wheel::wheel::vertical:
|
||||||
|
scroll = |
|
||||||
|
break;
|
||||||
|
case arg_wheel::wheel::horizontal:
|
||||||
|
scroll = &horz;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//Other button is not unsupported.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!API::empty_window(arg.window_handle))
|
||||||
|
{
|
||||||
|
auto align_px = (scroll->value() % scroll->step());
|
||||||
|
if (align_px)
|
||||||
|
{
|
||||||
|
auto new_value = scroll->value() - align_px;
|
||||||
|
if (!arg.upwards)
|
||||||
|
new_value += scroll->step();
|
||||||
|
|
||||||
|
scroll->value(new_value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned speed = 1;
|
||||||
|
if (provider.wheel_speed)
|
||||||
|
{
|
||||||
|
speed = provider.wheel_speed();
|
||||||
|
if (0 == speed)
|
||||||
|
speed = 1;
|
||||||
|
}
|
||||||
|
scroll->make_step(!arg.upwards, speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
API::events(handle).mouse_move.connect_unignorable([this](const arg_mouse& arg)
|
||||||
|
{
|
||||||
|
if (!arg.is_left_button())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->drive(arg.pos))
|
||||||
|
{
|
||||||
|
tmr.interval(16);
|
||||||
|
tmr.start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tmr.elapse([this](const arg_elapse&)
|
||||||
|
{
|
||||||
|
auto curs = ::nana::API::cursor_position();
|
||||||
|
::nana::API::calc_window_point(window_handle, curs);
|
||||||
|
|
||||||
|
if (this->drive(curs))
|
||||||
|
{
|
||||||
|
if (events.hover_outside)
|
||||||
|
events.hover_outside(curs);
|
||||||
|
|
||||||
|
API::refresh_window(window_handle);
|
||||||
|
view.sync(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmr.stop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool drive(const point& cursor_pos)
|
||||||
|
{
|
||||||
|
auto const area = view.view_area();
|
||||||
|
|
||||||
|
point skew;
|
||||||
|
|
||||||
|
if (disp_area.x > cursor_pos.x)
|
||||||
|
skew.x = cursor_pos.x - disp_area.x;
|
||||||
|
else if (cursor_pos.x > disp_area.x + static_cast<int>(area.width))
|
||||||
|
skew.x = cursor_pos.x - (disp_area.x + static_cast<int>(area.width));
|
||||||
|
|
||||||
|
if (disp_area.y > cursor_pos.y)
|
||||||
|
skew.y = cursor_pos.y - disp_area.y;
|
||||||
|
else if (cursor_pos.y > disp_area.y + static_cast<int>(area.height))
|
||||||
|
skew.y = cursor_pos.y - (disp_area.y + static_cast<int>(area.height));
|
||||||
|
|
||||||
|
if (skew.x == 0 && skew.y == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto speed_horz = 0;
|
||||||
|
if (skew.x)
|
||||||
|
speed_horz = skew.x / (std::max)(1, static_cast<int>(horz.step())) + (skew.x < 0 ? -1 : 1);
|
||||||
|
|
||||||
|
auto speed_vert = 0;
|
||||||
|
if (skew.y)
|
||||||
|
speed_vert = skew.y / (std::max)(1, static_cast<int>(vert.step())) + (skew.y < 0 ? -1 : 1);
|
||||||
|
|
||||||
|
speed_horz = (std::min)(5, (std::max)(speed_horz, -5));
|
||||||
|
speed_vert = (std::min)(5, (std::max)(speed_vert, -5));
|
||||||
|
|
||||||
|
view.move_origin({
|
||||||
|
speed_horz, speed_vert
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void size_changed(bool try_update)
|
||||||
|
{
|
||||||
|
auto imd_area = view.view_area();
|
||||||
|
|
||||||
|
//event hander for scrollbars
|
||||||
|
auto event_fn = [this](const arg_scroll& arg)
|
||||||
|
{
|
||||||
|
if (arg.window_handle == this->vert.handle())
|
||||||
|
origin.y = static_cast<int>(this->vert.value());
|
||||||
|
else
|
||||||
|
origin.x = static_cast<int>(this->horz.value());
|
||||||
|
|
||||||
|
if (this->enable_update)
|
||||||
|
{
|
||||||
|
API::refresh_window(this->window_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this->enable_update = try_update;
|
||||||
|
|
||||||
|
if (imd_area.width != disp_area.width)
|
||||||
|
{
|
||||||
|
if (vert.empty())
|
||||||
|
{
|
||||||
|
vert.create(window_handle);
|
||||||
|
vert.events().value_changed.connect_unignorable(event_fn);
|
||||||
|
this->enable_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vert.move({
|
||||||
|
disp_area.x + static_cast<int>(imd_area.width) + skew_vert.x,
|
||||||
|
disp_area.y + skew_vert.y,
|
||||||
|
_m_extra_px(),
|
||||||
|
imd_area.height + extra_px.height
|
||||||
|
});
|
||||||
|
|
||||||
|
vert.amount(content_size.height);
|
||||||
|
vert.range(imd_area.height);
|
||||||
|
vert.value(origin.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vert.close();
|
||||||
|
|
||||||
|
if (imd_area.height != disp_area.height)
|
||||||
|
{
|
||||||
|
if (horz.empty())
|
||||||
|
{
|
||||||
|
horz.create(window_handle);
|
||||||
|
horz.events().value_changed.connect_unignorable(event_fn);
|
||||||
|
this->enable_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
horz.move({
|
||||||
|
disp_area.x + skew_horz.x,
|
||||||
|
disp_area.y + static_cast<int>(imd_area.height) + skew_horz.y,
|
||||||
|
imd_area.width + extra_px.width,
|
||||||
|
_m_extra_px()
|
||||||
|
});
|
||||||
|
|
||||||
|
horz.amount(content_size.width);
|
||||||
|
horz.range(imd_area.width);
|
||||||
|
horz.value(origin.x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
horz.close();
|
||||||
|
|
||||||
|
this->enable_update = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
content_view::content_view(window handle)
|
||||||
|
: impl_{ new implementation{*this, handle} }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
content_view::~content_view()
|
||||||
|
{
|
||||||
|
delete impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
content_view::events_type& content_view::events()
|
||||||
|
{
|
||||||
|
return impl_->events;
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::step(unsigned step_value, bool horz)
|
||||||
|
{
|
||||||
|
if (horz)
|
||||||
|
impl_->horz.step(step_value);
|
||||||
|
else
|
||||||
|
impl_->vert.step(step_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool content_view::scroll(bool forwards, bool horz)
|
||||||
|
{
|
||||||
|
unsigned speed = 1;
|
||||||
|
if (impl_->provider.wheel_speed)
|
||||||
|
{
|
||||||
|
speed = impl_->provider.wheel_speed();
|
||||||
|
if (0 == speed)
|
||||||
|
speed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (horz)
|
||||||
|
return impl_->horz.make_step(forwards, speed);
|
||||||
|
|
||||||
|
return impl_->vert.make_step(forwards, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool content_view::turn_page(bool forwards, bool horz)
|
||||||
|
{
|
||||||
|
if (horz)
|
||||||
|
return impl_->horz.make_page_scroll(forwards);
|
||||||
|
else
|
||||||
|
return impl_->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)
|
||||||
|
{
|
||||||
|
if (impl_->disp_area != da)
|
||||||
|
{
|
||||||
|
impl_->disp_area = da;
|
||||||
|
impl_->skew_horz = skew_horz;
|
||||||
|
impl_->skew_vert = skew_vert;
|
||||||
|
impl_->extra_px = extra_px;
|
||||||
|
|
||||||
|
auto imd_area = this->view_area();
|
||||||
|
if (static_cast<int>(impl_->content_size.width) - impl_->origin.x < static_cast<int>(imd_area.width))
|
||||||
|
impl_->origin.x = (std::max)(0, static_cast<int>(impl_->content_size.width) - static_cast<int>(imd_area.width));
|
||||||
|
|
||||||
|
if (static_cast<int>(impl_->content_size.height) - impl_->origin.y < static_cast<int>(imd_area.height))
|
||||||
|
impl_->origin.y = (std::max)(0, static_cast<int>(impl_->content_size.height) - static_cast<int>(imd_area.height));
|
||||||
|
|
||||||
|
impl_->size_changed(try_update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::content_size(const size& sz, bool try_update)
|
||||||
|
{
|
||||||
|
impl_->content_size = sz;
|
||||||
|
impl_->size_changed(try_update);
|
||||||
|
}
|
||||||
|
|
||||||
|
const point& content_view::origin() const
|
||||||
|
{
|
||||||
|
return impl_->origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
rectangle content_view::corner() const
|
||||||
|
{
|
||||||
|
rectangle r;
|
||||||
|
|
||||||
|
auto imd_area = this->view_area();
|
||||||
|
|
||||||
|
r.x = impl_->disp_area.x + static_cast<int>(imd_area.width) + impl_->skew_vert.x;
|
||||||
|
r.y = impl_->disp_area.y + static_cast<int>(imd_area.height) + impl_->skew_horz.y;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned extra_horz = (impl_->disp_area.width < impl_->content_size.width ? _m_extra_px() : 0);
|
||||||
|
unsigned extra_vert = (impl_->disp_area.height < impl_->content_size.height + extra_horz ? _m_extra_px() : 0);
|
||||||
|
|
||||||
|
if ((0 == extra_horz) && extra_vert)
|
||||||
|
extra_horz = (impl_->disp_area.width < impl_->content_size.width + extra_vert ? _m_extra_px() : 0);
|
||||||
|
|
||||||
|
r.width = extra_horz;
|
||||||
|
r.height = extra_vert;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
rectangle content_view::view_area() const
|
||||||
|
{
|
||||||
|
unsigned extra_horz = (impl_->disp_area.width < impl_->content_size.width ? _m_extra_px() : 0);
|
||||||
|
unsigned extra_vert = (impl_->disp_area.height < impl_->content_size.height + extra_horz ? _m_extra_px() : 0);
|
||||||
|
|
||||||
|
if ((0 == extra_horz) && extra_vert)
|
||||||
|
extra_horz = (impl_->disp_area.width < impl_->content_size.width + extra_vert ? _m_extra_px() : 0);
|
||||||
|
|
||||||
|
return rectangle{
|
||||||
|
impl_->disp_area.position(),
|
||||||
|
size{
|
||||||
|
impl_->disp_area.width > extra_vert ? impl_->disp_area.width - extra_vert : 0,
|
||||||
|
impl_->disp_area.height > extra_horz ? impl_->disp_area.height - extra_horz : 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned content_view::extra_space(bool horz) const
|
||||||
|
{
|
||||||
|
return ((horz ? impl_->horz.empty() : impl_->vert.empty()) ? 0 : _m_extra_px());
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::change_position(int pos, bool aligned, bool horz)
|
||||||
|
{
|
||||||
|
if (aligned)
|
||||||
|
pos -= (pos % static_cast<int>(horz ? impl_->horz.step() : impl_->vert.step()));
|
||||||
|
|
||||||
|
auto imd_size = this->view_area();
|
||||||
|
|
||||||
|
if (horz)
|
||||||
|
{
|
||||||
|
if (pos + imd_size.width > impl_->content_size.width)
|
||||||
|
pos = static_cast<int>(impl_->content_size.width) - static_cast<int>(imd_size.width);
|
||||||
|
|
||||||
|
if (pos < 0) pos = 0;
|
||||||
|
|
||||||
|
impl_->origin.x = pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pos + imd_size.height > impl_->content_size.height)
|
||||||
|
pos = static_cast<int>(impl_->content_size.height) - static_cast<int>(imd_size.height);
|
||||||
|
|
||||||
|
if (pos < 0) pos = 0;
|
||||||
|
|
||||||
|
impl_->origin.y = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::move_origin(const point& skew)
|
||||||
|
{
|
||||||
|
auto imd_area = this->view_area();
|
||||||
|
|
||||||
|
impl_->origin.x += skew.x;
|
||||||
|
if (impl_->origin.x + imd_area.width > impl_->content_size.width)
|
||||||
|
impl_->origin.x = static_cast<int>(impl_->content_size.width) - static_cast<int>(imd_area.width);
|
||||||
|
|
||||||
|
if (impl_->origin.x < 0) impl_->origin.x = 0;
|
||||||
|
|
||||||
|
|
||||||
|
impl_->origin.y += skew.y;
|
||||||
|
if (impl_->origin.y + imd_area.height > impl_->content_size.height)
|
||||||
|
impl_->origin.y = static_cast<int>(impl_->content_size.height) - static_cast<int>(imd_area.height);
|
||||||
|
|
||||||
|
if (impl_->origin.y < 0) impl_->origin.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::sync(bool try_update)
|
||||||
|
{
|
||||||
|
impl_->enable_update = try_update;
|
||||||
|
impl_->horz.value(impl_->origin.x);
|
||||||
|
impl_->vert.value(impl_->origin.y);
|
||||||
|
impl_->enable_update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::pursue(const point& cursor)
|
||||||
|
{
|
||||||
|
if (impl_->disp_area.is_hit(cursor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int delta = 0;
|
||||||
|
if (cursor.x < impl_->disp_area.x)
|
||||||
|
delta = cursor.x - impl_->disp_area.x;
|
||||||
|
else if (cursor.x > impl_->disp_area.right())
|
||||||
|
delta = cursor.x - impl_->disp_area.right();
|
||||||
|
|
||||||
|
impl_->origin.x += delta;
|
||||||
|
if (impl_->origin.x < 0)
|
||||||
|
impl_->origin.x = 0;
|
||||||
|
|
||||||
|
if (cursor.y < impl_->disp_area.y)
|
||||||
|
delta = cursor.y - impl_->disp_area.y;
|
||||||
|
else if (cursor.y > impl_->disp_area.bottom())
|
||||||
|
delta = cursor.y - impl_->disp_area.bottom();
|
||||||
|
|
||||||
|
impl_->origin.y += delta;
|
||||||
|
if (impl_->origin.y < 0)
|
||||||
|
impl_->origin.y = 0;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
if (!impl_->horz.empty() && (static_cast<long long>(impl_->horz.value()) != impl_->origin.x))
|
||||||
|
{
|
||||||
|
impl_->horz.value(impl_->origin.x);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!impl_->vert.empty()) && (static_cast<long long>(impl_->vert.value()) != impl_->origin.y))
|
||||||
|
{
|
||||||
|
impl_->vert.value(impl_->origin.y);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
API::refresh_window(impl_->window_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void content_view::set_wheel_speed(std::function<unsigned()> fn)
|
||||||
|
{
|
||||||
|
impl_->provider.wheel_speed = std::move(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
source/gui/widgets/skeletons/content_view.hpp
Normal file
78
source/gui/widgets/skeletons/content_view.hpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* A Content View Implementation
|
||||||
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
|
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com)
|
||||||
|
*
|
||||||
|
* Distributed under the Boost Software License, Version 1.0.
|
||||||
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*
|
||||||
|
* @file: nana/gui/widgets/skeletons/content_view.hpp
|
||||||
|
* @author: Jinhao
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NANA_WIDGETS_SKELETONS_CONTENT_VIEW_INCLUDED
|
||||||
|
#define NANA_WIDGETS_SKELETONS_CONTENT_VIEW_INCLUDED
|
||||||
|
|
||||||
|
#include <nana/gui/basis.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace nana { namespace widgets {
|
||||||
|
namespace skeletons
|
||||||
|
{
|
||||||
|
class content_view
|
||||||
|
{
|
||||||
|
struct implementation;
|
||||||
|
|
||||||
|
content_view(const content_view&) = delete;
|
||||||
|
content_view& operator=(const content_view&) = delete;
|
||||||
|
|
||||||
|
content_view(content_view&&) = delete;
|
||||||
|
content_view& operator=(content_view&&) = delete;
|
||||||
|
public:
|
||||||
|
struct events_type
|
||||||
|
{
|
||||||
|
std::function<void(const point&)> hover_outside;
|
||||||
|
};
|
||||||
|
|
||||||
|
content_view(window handle);
|
||||||
|
~content_view();
|
||||||
|
|
||||||
|
events_type& events();
|
||||||
|
|
||||||
|
void step(unsigned step_value, bool horz);
|
||||||
|
bool scroll(bool forwards, bool horz);
|
||||||
|
bool turn_page(bool forwards, bool horz);
|
||||||
|
|
||||||
|
void disp_area(const rectangle& da, const point& skew_horz, const point& skew_vert, const size& extra_px, bool try_update = true);
|
||||||
|
|
||||||
|
void content_size(const size& sz, bool try_update = true);
|
||||||
|
const point& origin() const;
|
||||||
|
rectangle corner() const;
|
||||||
|
|
||||||
|
rectangle view_area() const;
|
||||||
|
|
||||||
|
unsigned extra_space(bool horz) const;
|
||||||
|
|
||||||
|
void change_position(int pos, bool aligned, bool horz);
|
||||||
|
|
||||||
|
void move_origin(const point& skew);
|
||||||
|
|
||||||
|
void sync(bool try_update);
|
||||||
|
|
||||||
|
void pursue(const point& cursor);
|
||||||
|
|
||||||
|
void set_wheel_speed(std::function<unsigned()> fn);
|
||||||
|
private:
|
||||||
|
static constexpr unsigned _m_extra_px()
|
||||||
|
{
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
implementation * const impl_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -425,7 +425,6 @@ namespace std
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _enable_std_put_time
|
#ifdef _enable_std_put_time
|
||||||
#include <ctime>
|
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user