commit
66461d6304
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Filebox
|
* Filebox
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -69,11 +69,10 @@ namespace nana
|
|||||||
|
|
||||||
|
|
||||||
const ::std::string& path() const;
|
const ::std::string& path() const;
|
||||||
const ::std::string& file() const;
|
::std::string file() const;
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
const ::std::vector<::std::string>& files() const;
|
const ::std::vector<::std::string>& files() const;
|
||||||
void allow_multi_select(bool allow);
|
void allow_multi_select(bool allow);
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Display the filebox dialog
|
/// Display the filebox dialog
|
||||||
bool show() const;
|
bool show() const;
|
||||||
|
|||||||
@ -104,6 +104,7 @@ namespace drawerbase
|
|||||||
struct element_tag
|
struct element_tag
|
||||||
{
|
{
|
||||||
checkbox * uiobj;
|
checkbox * uiobj;
|
||||||
|
event_handle eh_clicked;
|
||||||
event_handle eh_checked;
|
event_handle eh_checked;
|
||||||
event_handle eh_destroy;
|
event_handle eh_destroy;
|
||||||
event_handle eh_keyboard;
|
event_handle eh_keyboard;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Concept of Component Set
|
* Concept of Component Set
|
||||||
* Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -60,17 +60,19 @@ namespace nana{ namespace widgets{ namespace detail
|
|||||||
/// Widget scheme.
|
/// Widget scheme.
|
||||||
typedef WidgetScheme widget_scheme_t;
|
typedef WidgetScheme widget_scheme_t;
|
||||||
|
|
||||||
widget_scheme_t * wdg_scheme_ptr_{ nullptr };
|
//widget_scheme_t * wdg_scheme_ptr_{ nullptr }; //deprecated
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// The destructor.
|
/// The destructor.
|
||||||
virtual ~compset_placer(){}
|
virtual ~compset_placer(){}
|
||||||
|
|
||||||
|
/*
|
||||||
/// Init the scheme pointer
|
/// Init the scheme pointer
|
||||||
void init_scheme(widget_scheme_t* wdg_scheme_ptr)
|
void init_scheme(widget_scheme_t* wdg_scheme_ptr) //deprecated
|
||||||
{
|
{
|
||||||
wdg_scheme_ptr_ = wdg_scheme_ptr;
|
wdg_scheme_ptr_ = wdg_scheme_ptr;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/// Enable/Disable the specified component.
|
/// Enable/Disable the specified component.
|
||||||
virtual void enable(component_t, bool) = 0;
|
virtual void enable(component_t, bool) = 0;
|
||||||
|
|||||||
@ -92,6 +92,9 @@ namespace nana{
|
|||||||
/// Determines whether a specified option is checked, it throws an out_of_range if !(pos < number of options)
|
/// Determines whether a specified option is checked, it throws an out_of_range if !(pos < number of options)
|
||||||
bool option_checked(std::size_t pos) const;
|
bool option_checked(std::size_t pos) const;
|
||||||
|
|
||||||
|
/// Change typeface of caption label ( does not effect child widgets )
|
||||||
|
void typeface( const nana::paint::font& font );
|
||||||
|
|
||||||
group& enable_format_caption(bool format);
|
group& enable_format_caption(bool format);
|
||||||
|
|
||||||
group& collocate() noexcept;
|
group& collocate() noexcept;
|
||||||
@ -101,7 +104,7 @@ namespace nana{
|
|||||||
void field_display(const char* field_name, bool display); ///<Displays/Discards an existing field.
|
void field_display(const char* field_name, bool display); ///<Displays/Discards an existing field.
|
||||||
bool field_display(const char* field_name) const; ///<Determines whether the specified field is displayed.
|
bool field_display(const char* field_name) const; ///<Determines whether the specified field is displayed.
|
||||||
void erase(window handle); ///< Erases a window from field.
|
void erase(window handle); ///< Erases a window from field.
|
||||||
|
|
||||||
template<typename Widget, typename ...Args>
|
template<typename Widget, typename ...Args>
|
||||||
Widget* create_child(const char* field, Args && ... args)
|
Widget* create_child(const char* field, Args && ... args)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* A List Box Implementation
|
* A List Box Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -1461,7 +1461,19 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
/// Returns the number of columns
|
/// Returns the number of columns
|
||||||
size_type column_size() const;
|
size_type column_size() const;
|
||||||
|
|
||||||
void column_resizable(bool resizable);
|
/// Move column to view_position
|
||||||
|
void move_column(size_type abs_pos, size_type view_pos);
|
||||||
|
|
||||||
|
/// Sort columns in range first_col to last_col inclusive using the values from a row
|
||||||
|
void reorder_columns(size_type first_col,
|
||||||
|
size_type last_col,
|
||||||
|
index_pair row, bool reverse,
|
||||||
|
std::function<bool(const std::string &cell1, size_type col1,
|
||||||
|
const std::string &cell2, size_type col2,
|
||||||
|
const nana::any *rowval,
|
||||||
|
bool reverse)> comp);
|
||||||
|
|
||||||
|
void column_resizable(bool resizable);
|
||||||
bool column_resizable() const;
|
bool column_resizable() const;
|
||||||
void column_movable(bool);
|
void column_movable(bool);
|
||||||
bool column_movable() const;
|
bool column_movable() const;
|
||||||
@ -1517,7 +1529,8 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
|
|
||||||
///Sets a strict weak ordering comparer for a column
|
///Sets a strict weak ordering comparer for a column
|
||||||
void set_sort_compare( size_type col,
|
void set_sort_compare( size_type col,
|
||||||
std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> strick_ordering);
|
std::function<bool(const std::string&, nana::any*,
|
||||||
|
const std::string&, nana::any*, bool reverse)> strick_ordering);
|
||||||
|
|
||||||
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
/// sort() and ivalidate any existing reference from display position to absolute item, that is: after sort() display offset point to different items
|
||||||
void sort_col(size_type col, bool reverse = false);
|
void sort_col(size_type col, bool reverse = false);
|
||||||
@ -1538,6 +1551,7 @@ the nana::detail::basic_window member pointer scheme
|
|||||||
|
|
||||||
void enable_single(bool for_selection, bool category_limited);
|
void enable_single(bool for_selection, bool category_limited);
|
||||||
void disable_single(bool for_selection);
|
void disable_single(bool for_selection);
|
||||||
|
bool is_single_enabled(bool for_selection) const noexcept; ///< Determines whether the single selection/check is enabled.
|
||||||
export_options& def_export_options();
|
export_options& def_export_options();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -151,7 +151,13 @@ namespace nana
|
|||||||
bool vertical() const;
|
bool vertical() const;
|
||||||
void maximum(unsigned);
|
void maximum(unsigned);
|
||||||
unsigned maximum() const;
|
unsigned maximum() const;
|
||||||
void value(unsigned);
|
|
||||||
|
/** Set slider value
|
||||||
|
@param[in] v new value for slider.
|
||||||
|
v will be clipped to the range 0 to maximum
|
||||||
|
*/
|
||||||
|
void value(int );
|
||||||
|
|
||||||
unsigned value() const;
|
unsigned value() const;
|
||||||
unsigned move_step(bool forward); ///< Increase or decrease the value of slider.
|
unsigned move_step(bool forward); ///< Increase or decrease the value of slider.
|
||||||
unsigned adorn() const;
|
unsigned adorn() const;
|
||||||
|
|||||||
@ -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-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Platform Implementation
|
* Platform Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "../../paint/image_accessor.hpp"
|
#include "../../paint/image_accessor.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace nana{
|
namespace nana{
|
||||||
namespace detail{
|
namespace detail{
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ namespace nana{
|
|||||||
namespace x11_wait
|
namespace x11_wait
|
||||||
{
|
{
|
||||||
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
|
return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,15 +1020,11 @@ namespace nana{
|
|||||||
auto const owner = restrict::spec.get_owner(wd);
|
auto const owner = restrict::spec.get_owner(wd);
|
||||||
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
||||||
{
|
{
|
||||||
auto origin = window_position(owner);
|
int origin_x, origin_y;
|
||||||
#if 0
|
Window child_useless_for_API;
|
||||||
x += origin.x;
|
::XTranslateCoordinates(disp, reinterpret_cast<Window>(owner), restrict::spec.root_window(), 0, 0, &origin_x, &origin_y, &child_useless_for_API);
|
||||||
y += origin.y;
|
x += origin_x;
|
||||||
#else
|
y += origin_y;
|
||||||
auto owner_extents = window_frame_extents(owner);
|
|
||||||
x += origin.x + owner_extents.left;
|
|
||||||
y += origin.y + owner_extents.top;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
||||||
@ -1074,7 +1071,6 @@ namespace nana{
|
|||||||
XSizeHints hints;
|
XSizeHints hints;
|
||||||
nana::detail::platform_scope_guard psg;
|
nana::detail::platform_scope_guard psg;
|
||||||
|
|
||||||
|
|
||||||
//Returns if the requested rectangle is same with the current rectangle.
|
//Returns if the requested rectangle is same with the current rectangle.
|
||||||
//In some X-Server versions/implementations, XMapWindow() doesn't generate
|
//In some X-Server versions/implementations, XMapWindow() doesn't generate
|
||||||
//a ConfigureNotify if the requested rectangle is same with the current rectangle.
|
//a ConfigureNotify if the requested rectangle is same with the current rectangle.
|
||||||
@ -1114,11 +1110,11 @@ namespace nana{
|
|||||||
auto const owner = restrict::spec.get_owner(wd);
|
auto const owner = restrict::spec.get_owner(wd);
|
||||||
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
if(owner && (owner != reinterpret_cast<native_window_type>(restrict::spec.root_window())))
|
||||||
{
|
{
|
||||||
auto origin = window_position(owner);
|
int origin_x, origin_y;
|
||||||
|
Window child_useless_for_API;
|
||||||
auto owner_extents = window_frame_extents(owner);
|
::XTranslateCoordinates(disp, reinterpret_cast<Window>(owner), restrict::spec.root_window(), 0, 0, &origin_x, &origin_y, &child_useless_for_API);
|
||||||
x += origin.x + owner_extents.left;
|
x += origin_x;
|
||||||
y += origin.y + owner_extents.top;
|
y += origin_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Filebox
|
* Filebox
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -38,6 +38,8 @@
|
|||||||
# include "../detail/posix/theme.hpp"
|
# include "../detail/posix/theme.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
namespace fs_ext = nana::filesystem_ext;
|
namespace fs_ext = nana::filesystem_ext;
|
||||||
|
|
||||||
@ -153,7 +155,7 @@ namespace nana
|
|||||||
typedef treebox::item_proxy item_proxy;
|
typedef treebox::item_proxy item_proxy;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
filebox_implement(window owner, mode dialog_mode, const std::string& title, bool pick_directory = false):
|
filebox_implement(window owner, mode dialog_mode, const std::string& title, bool pick_directory, bool allow_multi_select):
|
||||||
form(owner, API::make_center(owner, 630, 440)),
|
form(owner, API::make_center(owner, 630, 440)),
|
||||||
pick_directory_(pick_directory),
|
pick_directory_(pick_directory),
|
||||||
mode_(dialog_mode)
|
mode_(dialog_mode)
|
||||||
@ -239,11 +241,42 @@ namespace nana
|
|||||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_TYPE"), 80);
|
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_TYPE"), 80);
|
||||||
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70);
|
ls_file_.append_header(i18n("NANA_FILEBOX_HEADER_SIZE"), 70);
|
||||||
|
|
||||||
auto fn_sel_file = [this](const arg_mouse& arg){
|
|
||||||
_m_select_file(arg);
|
auto fn_list_handler = [this](const arg_mouse& arg){
|
||||||
|
if(event_code::mouse_down == arg.evt_code)
|
||||||
|
{
|
||||||
|
selection_.is_deselect_delayed = true;
|
||||||
|
}
|
||||||
|
else if(event_code::mouse_up == arg.evt_code)
|
||||||
|
{
|
||||||
|
selection_.is_deselect_delayed = false;
|
||||||
|
#if 0
|
||||||
|
this->_m_delay_deselect(true);
|
||||||
|
#endif
|
||||||
|
if(_m_sync_with_selection())
|
||||||
|
_m_display_target_filenames();
|
||||||
|
}
|
||||||
|
else if(event_code::mouse_move == arg.evt_code)
|
||||||
|
{
|
||||||
|
if(arg.left_button)
|
||||||
|
{
|
||||||
|
selection_.is_deselect_delayed = false;
|
||||||
|
std::cout<<"MouseMove set is_deselect_delayed = true"<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event_code::dbl_click == arg.evt_code)
|
||||||
|
_m_click_select_file(arg);
|
||||||
};
|
};
|
||||||
ls_file_.events().dbl_click.connect_unignorable(fn_sel_file);
|
|
||||||
ls_file_.events().mouse_down.connect_unignorable(fn_sel_file);
|
ls_file_.events().dbl_click.connect_unignorable(fn_list_handler);
|
||||||
|
ls_file_.events().mouse_down.connect_unignorable(fn_list_handler);
|
||||||
|
ls_file_.events().mouse_up.connect_unignorable(fn_list_handler);
|
||||||
|
ls_file_.events().mouse_move.connect_unignorable(fn_list_handler);
|
||||||
|
|
||||||
|
ls_file_.events().selected.connect_unignorable([this](const arg_listbox& arg){
|
||||||
|
_m_select_file(arg.item);
|
||||||
|
});
|
||||||
|
|
||||||
ls_file_.set_sort_compare(0, [](const std::string& a, nana::any* fs_a, const std::string& b, nana::any* fs_b, bool reverse) -> bool
|
ls_file_.set_sort_compare(0, [](const std::string& a, nana::any* fs_a, const std::string& b, nana::any* fs_b, bool reverse) -> bool
|
||||||
{
|
{
|
||||||
int dira = any_cast<item_fs>(fs_a)->directory ? 1 : 0;
|
int dira = any_cast<item_fs>(fs_a)->directory ? 1 : 0;
|
||||||
@ -327,7 +360,7 @@ namespace nana
|
|||||||
tb_file_.events().key_char.connect_unignorable([this](const arg_keyboard& arg)
|
tb_file_.events().key_char.connect_unignorable([this](const arg_keyboard& arg)
|
||||||
{
|
{
|
||||||
if(arg.key == nana::keyboard::enter)
|
if(arg.key == nana::keyboard::enter)
|
||||||
_m_ok();
|
_m_try_select(tb_file_.caption());
|
||||||
});
|
});
|
||||||
|
|
||||||
//Don't create the combox for choose a file extension if the dialog is used for picking a directory.
|
//Don't create the combox for choose a file extension if the dialog is used for picking a directory.
|
||||||
@ -341,11 +374,11 @@ namespace nana
|
|||||||
btn_ok_.create(*this);
|
btn_ok_.create(*this);
|
||||||
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY"));
|
btn_ok_.i18n(i18n_eval("NANA_BUTTON_OK_SHORTKEY"));
|
||||||
|
|
||||||
|
|
||||||
btn_ok_.events().click.connect_unignorable([this](const arg_click&)
|
btn_ok_.events().click.connect_unignorable([this](const arg_click&)
|
||||||
{
|
{
|
||||||
_m_ok();
|
_m_try_select(tb_file_.caption());
|
||||||
});
|
});
|
||||||
|
|
||||||
btn_cancel_.create(*this);
|
btn_cancel_.create(*this);
|
||||||
btn_cancel_.i18n(i18n_eval("NANA_BUTTON_CANCEL_SHORTKEY"));
|
btn_cancel_.i18n(i18n_eval("NANA_BUTTON_CANCEL_SHORTKEY"));
|
||||||
|
|
||||||
@ -377,6 +410,10 @@ namespace nana
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
caption(title);
|
caption(title);
|
||||||
|
|
||||||
|
|
||||||
|
if(!allow_multi_select)
|
||||||
|
ls_file_.enable_single(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void def_extension(const std::string& ext)
|
void def_extension(const std::string& ext)
|
||||||
@ -392,7 +429,7 @@ namespace nana
|
|||||||
std::string dir;
|
std::string dir;
|
||||||
|
|
||||||
auto pos = init_file.find_last_of("\\/");
|
auto pos = init_file.find_last_of("\\/");
|
||||||
auto file_with_path_removed = (pos != init_file.npos ? init_file.substr(pos + 1) : init_file);
|
auto filename = (pos != init_file.npos ? init_file.substr(pos + 1) : init_file);
|
||||||
|
|
||||||
if(saved_init_path != init_path)
|
if(saved_init_path != init_path)
|
||||||
{
|
{
|
||||||
@ -400,7 +437,7 @@ namespace nana
|
|||||||
saved_init_path = init_path;
|
saved_init_path = init_path;
|
||||||
|
|
||||||
//Phase 2: Check whether init_file contains a path
|
//Phase 2: Check whether init_file contains a path
|
||||||
if(file_with_path_removed == init_file)
|
if(filename == init_file)
|
||||||
{
|
{
|
||||||
//Phase 3: Check whether init_path is empty
|
//Phase 3: Check whether init_path is empty
|
||||||
if(init_path.size())
|
if(init_path.size())
|
||||||
@ -414,7 +451,7 @@ namespace nana
|
|||||||
|
|
||||||
_m_load_cat_path(dir.size() ? dir : fs_ext::path_user().native());
|
_m_load_cat_path(dir.size() ? dir : fs_ext::path_user().native());
|
||||||
|
|
||||||
tb_file_.caption(file_with_path_removed);
|
tb_file_.caption(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_filter(const std::string& desc, const std::string& type)
|
void add_filter(const std::string& desc, const std::string& type)
|
||||||
@ -450,6 +487,7 @@ namespace nana
|
|||||||
cb_types_.anyobj(i, v);
|
cb_types_.anyobj(i, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool file(std::string& fs) const
|
bool file(std::string& fs) const
|
||||||
{
|
{
|
||||||
if(selection_.type == kind::none)
|
if(selection_.type == kind::none)
|
||||||
@ -464,6 +502,20 @@ namespace nana
|
|||||||
fs = selection_.target;
|
fs = selection_.target;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
std::vector<std::string> files() const
|
||||||
|
{
|
||||||
|
if(kind::none == selection_.type)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto pos = selection_.targets.front().find_last_of("\\/");
|
||||||
|
if(pos != selection_.targets.front().npos)
|
||||||
|
saved_selected_path = selection_.targets.front().substr(0, pos);
|
||||||
|
else
|
||||||
|
saved_selected_path.clear();
|
||||||
|
|
||||||
|
return selection_.targets;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
void _m_layout()
|
void _m_layout()
|
||||||
{
|
{
|
||||||
@ -704,7 +756,7 @@ namespace nana
|
|||||||
if(pick_directory_)
|
if(pick_directory_)
|
||||||
return is_dir;
|
return is_dir;
|
||||||
|
|
||||||
if((is_dir || 0 == extension) || (0 == extension->size())) return true;
|
if(is_dir || (nullptr == extension) || extension->empty()) return true;
|
||||||
|
|
||||||
for(auto & extstr : *extension)
|
for(auto & extstr : *extension)
|
||||||
{
|
{
|
||||||
@ -799,9 +851,8 @@ namespace nana
|
|||||||
ls_file_.auto_draw(true);
|
ls_file_.auto_draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _m_finish(kind::t type, const std::string& tar)
|
void _m_finish(kind::t type)
|
||||||
{
|
{
|
||||||
selection_.target = tar;
|
|
||||||
selection_.type = type;
|
selection_.type = type;
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -881,40 +932,346 @@ namespace nana
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void _m_select_file(const arg_mouse& arg)
|
void _m_insert_filename(const std::string& name)
|
||||||
{
|
{
|
||||||
auto sel = ls_file_.selected();
|
if(selection_.targets.cend() == std::find(selection_.targets.cbegin(), selection_.targets.cend(), name))
|
||||||
if(sel.empty())
|
selection_.targets.push_back(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _m_hovered_good() const
|
||||||
|
{
|
||||||
|
auto pos = ls_file_.hovered(false);
|
||||||
|
if(!pos.empty())
|
||||||
|
{
|
||||||
|
item_fs mfs;
|
||||||
|
ls_file_.at(pos).resolve_to(mfs);
|
||||||
|
return !mfs.directory;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _m_has_good_select() const
|
||||||
|
{
|
||||||
|
auto selected_items = ls_file_.selected();
|
||||||
|
if(selected_items.size())
|
||||||
|
{
|
||||||
|
for(auto & pos : selected_items)
|
||||||
|
{
|
||||||
|
item_fs mfs;
|
||||||
|
ls_file_.at(pos).resolve_to(mfs);
|
||||||
|
|
||||||
|
if((mode::open_directory == mode_) || (false == mfs.directory))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _m_sync_with_selection()
|
||||||
|
{
|
||||||
|
if(_m_has_good_select())
|
||||||
|
{
|
||||||
|
auto selected_items = ls_file_.selected();
|
||||||
|
if(selected_items.size() && (selected_items.size() < selection_.targets.size()))
|
||||||
|
{
|
||||||
|
selection_.targets.clear();
|
||||||
|
for(auto & pos : selected_items)
|
||||||
|
{
|
||||||
|
item_fs mfs;
|
||||||
|
ls_file_.at(pos).resolve_to(mfs);
|
||||||
|
|
||||||
|
if((mode::open_directory == mode_) || (false == mfs.directory))
|
||||||
|
selection_.targets.push_back(mfs.name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_click_select_file(const arg_mouse& arg)
|
||||||
|
{
|
||||||
|
auto selected_item = ls_file_.hovered(false);
|
||||||
|
if(selected_item.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto index = sel[0];
|
|
||||||
item_fs m;
|
item_fs m;
|
||||||
ls_file_.at(index).resolve_to(m);
|
ls_file_.at(selected_item).resolve_to(m);
|
||||||
|
|
||||||
if(event_code::dbl_click == arg.evt_code)
|
if(event_code::dbl_click == arg.evt_code)
|
||||||
{
|
{
|
||||||
if(m.directory)
|
if(!m.directory)
|
||||||
_m_load_cat_path(addr_.filesystem + m.name + "/");
|
_m_try_select(m.name);
|
||||||
else
|
else
|
||||||
_m_finish(kind::filesystem, addr_.filesystem + m.name);
|
_m_load_cat_path(addr_.filesystem + m.name + "/");
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((mode::open_directory == mode_) || (false == m.directory))
|
if((mode::open_directory == mode_) || (false == m.directory))
|
||||||
{
|
{
|
||||||
selection_.target = addr_.filesystem + m.name;
|
if(ls_file_.is_single_enabled(true) || !arg.ctrl)
|
||||||
tb_file_.caption(m.name);
|
{
|
||||||
|
std::cout<<"assign by click select "<<m.name<<std::endl;
|
||||||
|
selection_.targets = {m.name};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout<<"insert by click select "<<m.name<<std::endl;
|
||||||
|
_m_insert_filename(m.name);
|
||||||
|
}
|
||||||
|
_m_display_target_filenames();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void _m_delay_deselect(bool only_clear_register)
|
||||||
|
{
|
||||||
|
if(!only_clear_register)
|
||||||
|
{
|
||||||
|
std::string filename_string;
|
||||||
|
for(auto i = selection_.targets.cbegin(); i != selection_.targets.cend();)
|
||||||
|
{
|
||||||
|
std::filesystem::path p{*i};
|
||||||
|
|
||||||
|
auto u = std::find(selection_.delay_deselect.cbegin(), selection_.delay_deselect.cend(), p.filename().u8string());
|
||||||
|
if(u == selection_.delay_deselect.cend())
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i = selection_.targets.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
_m_display_target_filenames();
|
||||||
|
}
|
||||||
|
|
||||||
|
selection_.delay_deselect.clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _m_select_file(const listbox::item_proxy& item)
|
||||||
|
{
|
||||||
|
item_fs mfs;
|
||||||
|
ls_file_.at(item.pos()).resolve_to(mfs);
|
||||||
|
|
||||||
|
if(item.selected())
|
||||||
|
{
|
||||||
|
if((mode::open_directory == mode_) || (false == mfs.directory))
|
||||||
|
{
|
||||||
|
if(ls_file_.selected().size() < 2)
|
||||||
|
selection_.targets.clear();
|
||||||
|
|
||||||
|
std::cout<<"insert by select file:"<<mfs.name<<std::endl;
|
||||||
|
_m_insert_filename(mfs.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(_m_hovered_good() || _m_has_good_select())
|
||||||
|
{
|
||||||
|
for(auto i = selection_.targets.cbegin(); i != selection_.targets.cend();)
|
||||||
|
{
|
||||||
|
std::filesystem::path p{*i};
|
||||||
|
if(p.filename().u8string() == mfs.name)
|
||||||
|
{
|
||||||
|
std::cout<<"_m_select_file delay deselect = "<<selection_.is_deselect_delayed<<std::endl;
|
||||||
|
if(!selection_.is_deselect_delayed)
|
||||||
|
{
|
||||||
|
i = selection_.targets.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
selection_.delay_deselect.push_back(mfs.name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_m_display_target_filenames();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_display_target_filenames()
|
||||||
|
{
|
||||||
|
std::string filename_string;
|
||||||
|
if(selection_.targets.size() == 1)
|
||||||
|
{
|
||||||
|
filename_string = selection_.targets.front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(auto i = selection_.targets.crbegin(); i != selection_.targets.crend(); ++i)
|
||||||
|
{
|
||||||
|
std::filesystem::path p{*i};
|
||||||
|
if(!filename_string.empty())
|
||||||
|
filename_string += ' ';
|
||||||
|
|
||||||
|
filename_string += "\"" + p.filename().u8string() + "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tb_file_.caption(filename_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> _m_strip_files(const std::string& text)
|
||||||
|
{
|
||||||
|
std::vector<std::string> files;
|
||||||
|
std::size_t start_pos = 0;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
auto pos = text.find_first_of(" \"", start_pos);
|
||||||
|
if(text.npos == pos)
|
||||||
|
{
|
||||||
|
if(text.length() == start_pos)
|
||||||
|
return files;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pos = pos + 1;
|
||||||
|
|
||||||
|
if(text[pos] == '"')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pos = text.find('"', start_pos);
|
||||||
|
if(text.npos == pos)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if(pos - start_pos > 0)
|
||||||
|
files.push_back(text.substr(start_pos, pos - start_pos));
|
||||||
|
|
||||||
|
start_pos = pos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _m_try_select(const std::string& files_text)
|
||||||
|
{
|
||||||
|
selection_.targets.clear();
|
||||||
|
//auto file = tb_file_.caption();
|
||||||
|
auto targets = _m_strip_files(files_text);
|
||||||
|
#if 1 //debug
|
||||||
|
std::cout<<"filebox OK: file="<<files_text<<std::endl;
|
||||||
|
for(auto t : targets)
|
||||||
|
std::cout<<"filebox OK stripped:"<<t<<std::endl;
|
||||||
|
#endif
|
||||||
|
if(targets.empty())
|
||||||
|
{
|
||||||
|
//No file is selected
|
||||||
|
if(files_text.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
targets.push_back(files_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
internationalization i18n;
|
||||||
|
|
||||||
|
//the position of tar in targets
|
||||||
|
int tar_idx = -1;
|
||||||
|
|
||||||
|
//Check whether the selected files are valid.
|
||||||
|
for(auto tar : targets)
|
||||||
|
{
|
||||||
|
++tar_idx;
|
||||||
|
if(tar[0] == '.')
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption());
|
||||||
|
mb.icon(msgbox::icon_warning);
|
||||||
|
mb<<tar<<std::endl<<i18n("NANA_FILEBOX_ERROR_INVALID_FILENAME");
|
||||||
|
mb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tar[0] != '/')
|
||||||
|
tar = addr_.filesystem + tar;
|
||||||
|
|
||||||
|
auto fattr = fs::status(tar);
|
||||||
|
auto ftype = static_cast<fs::file_type>(fattr.type());
|
||||||
|
|
||||||
|
//Check if the selected name is a directory
|
||||||
|
auto is_dir = fs::is_directory(fattr);
|
||||||
|
|
||||||
|
if(!is_dir && _m_append_def_extension(tar))
|
||||||
|
{
|
||||||
|
//Add the extension, then check if it is a directory again.
|
||||||
|
fattr = fs::status(tar);
|
||||||
|
ftype = static_cast<fs::file_type>(fattr.type());
|
||||||
|
is_dir = fs::is_directory(fattr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_dir)
|
||||||
|
{
|
||||||
|
//Enter the directory if this is the first tar.
|
||||||
|
if(0 == tar_idx)
|
||||||
|
{
|
||||||
|
_m_load_cat_path(tar);
|
||||||
|
tb_file_.caption(std::string{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Other folders are ignored
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode::write_file != mode_)
|
||||||
|
{
|
||||||
|
if(fs::file_type::not_found == ftype)
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption());
|
||||||
|
mb.icon(msgbox::icon_information);
|
||||||
|
if(mode::open_file == mode_)
|
||||||
|
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
||||||
|
else
|
||||||
|
mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar);
|
||||||
|
mb();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(fs::file_type::not_found != ftype)
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption(), msgbox::yes_no);
|
||||||
|
mb.icon(msgbox::icon_question);
|
||||||
|
mb<<i18n("NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING");
|
||||||
|
if(msgbox::pick_no == mb())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selection_.targets.push_back(tar);
|
||||||
|
}
|
||||||
|
|
||||||
|
_m_finish(kind::filesystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void _m_ok()
|
void _m_ok()
|
||||||
{
|
{
|
||||||
std::string tar = selection_.target;
|
selection_.targets.clear();
|
||||||
|
auto file = tb_file_.caption();
|
||||||
|
auto targets = _m_strip_files(file);
|
||||||
|
#if 1 //debug
|
||||||
|
std::cout<<"filebox OK: file="<<file<<std::endl;
|
||||||
|
for(auto t : targets)
|
||||||
|
std::cout<<"filebox OK stripped:"<<t<<std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(selection_.target.empty())
|
//No file is selected
|
||||||
|
if(targets.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
std::string tar;
|
||||||
|
if(selection_.targets.empty())
|
||||||
{
|
{
|
||||||
auto file = tb_file_.caption();
|
|
||||||
if(file.size())
|
if(file.size())
|
||||||
{
|
{
|
||||||
internationalization i18n;
|
internationalization i18n;
|
||||||
@ -959,7 +1316,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
msgbox mb(*this, caption());
|
msgbox mb(*this, caption());
|
||||||
mb.icon(msgbox::icon_information);
|
mb.icon(msgbox::icon_information);
|
||||||
if(mode::open_file != mode_)
|
if(mode::open_file == mode_)
|
||||||
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
||||||
else
|
else
|
||||||
mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar);
|
mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar);
|
||||||
@ -979,11 +1336,94 @@ namespace nana
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selection_.targets = {tar};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
internationalization i18n;
|
||||||
|
|
||||||
_m_finish(kind::filesystem, tar);
|
//the position of tar in targets
|
||||||
|
int tar_idx = -1;
|
||||||
|
|
||||||
|
//Check whether the selected files are valid.
|
||||||
|
for(auto tar : targets)
|
||||||
|
{
|
||||||
|
++tar_idx;
|
||||||
|
if(tar[0] == '.')
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption());
|
||||||
|
mb.icon(msgbox::icon_warning);
|
||||||
|
mb<<file<<std::endl<<i18n("NANA_FILEBOX_ERROR_INVALID_FILENAME");
|
||||||
|
mb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tar[0] != '/')
|
||||||
|
tar = addr_.filesystem + tar;
|
||||||
|
|
||||||
|
auto fattr = fs::status(tar);
|
||||||
|
auto ftype = static_cast<fs::file_type>(fattr.type());
|
||||||
|
|
||||||
|
//Check if the selected name is a directory
|
||||||
|
auto is_dir = fs::is_directory(fattr);
|
||||||
|
|
||||||
|
if(!is_dir && _m_append_def_extension(tar))
|
||||||
|
{
|
||||||
|
//Add the extension, then check if it is a directory again.
|
||||||
|
fattr = fs::status(tar);
|
||||||
|
ftype = static_cast<fs::file_type>(fattr.type());
|
||||||
|
is_dir = fs::is_directory(fattr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_dir)
|
||||||
|
{
|
||||||
|
//Enter the directory if this is the first tar.
|
||||||
|
if(0 == tar_idx)
|
||||||
|
{
|
||||||
|
_m_load_cat_path(tar);
|
||||||
|
tb_file_.caption(std::string{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Other folders are ignored
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mode::write_file != mode_)
|
||||||
|
{
|
||||||
|
if(fs::file_type::not_found == ftype)
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption());
|
||||||
|
mb.icon(msgbox::icon_information);
|
||||||
|
if(mode::open_file == mode_)
|
||||||
|
mb << i18n("NANA_FILEBOX_ERROR_NOT_EXISTING_AND_RETRY", tar);
|
||||||
|
else
|
||||||
|
mb << i18n("NANA_FILEBOX_ERROR_DIRECTORY_NOT_EXISTING_AND_RETRY", tar);
|
||||||
|
mb();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(fs::file_type::not_found != ftype)
|
||||||
|
{
|
||||||
|
msgbox mb(*this, caption(), msgbox::yes_no);
|
||||||
|
mb.icon(msgbox::icon_question);
|
||||||
|
mb<<i18n("NANA_FILEBOX_ERROR_QUERY_REWRITE_BECAUSE_OF_EXISTING");
|
||||||
|
if(msgbox::pick_no == mb())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selection_.targets.push_back(tar);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_m_finish(kind::filesystem);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void _m_tr_expand(item_proxy node, bool exp)
|
void _m_tr_expand(item_proxy node, bool exp)
|
||||||
{
|
{
|
||||||
@ -1064,7 +1504,11 @@ namespace nana
|
|||||||
struct selection_rep
|
struct selection_rep
|
||||||
{
|
{
|
||||||
kind::t type;
|
kind::t type;
|
||||||
std::string target;
|
std::vector<std::string> targets;
|
||||||
|
#if 0
|
||||||
|
std::vector<std::string> delay_deselect;
|
||||||
|
#endif
|
||||||
|
bool is_deselect_delayed{ false };
|
||||||
}selection_;
|
}selection_;
|
||||||
|
|
||||||
static std::string saved_init_path;
|
static std::string saved_init_path;
|
||||||
@ -1099,12 +1543,9 @@ namespace nana
|
|||||||
window owner;
|
window owner;
|
||||||
bool open_or_save;
|
bool open_or_save;
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
bool allow_multi_select;
|
bool allow_multi_select;
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
#else
|
|
||||||
std::string file;
|
|
||||||
#endif
|
|
||||||
std::string title;
|
std::string title;
|
||||||
std::string path;
|
std::string path;
|
||||||
std::vector<filter> filters;
|
std::vector<filter> filters;
|
||||||
@ -1120,8 +1561,8 @@ namespace nana
|
|||||||
{
|
{
|
||||||
impl_->owner = owner;
|
impl_->owner = owner;
|
||||||
impl_->open_or_save = open;
|
impl_->open_or_save = open;
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
impl_->allow_multi_select = false;
|
impl_->allow_multi_select = false;
|
||||||
|
#if defined(NANA_WINDOWS)
|
||||||
auto len = ::GetCurrentDirectory(0, nullptr);
|
auto len = ::GetCurrentDirectory(0, nullptr);
|
||||||
if(len)
|
if(len)
|
||||||
{
|
{
|
||||||
@ -1178,11 +1619,7 @@ namespace nana
|
|||||||
|
|
||||||
filebox& filebox::init_file(const std::string& ifstr)
|
filebox& filebox::init_file(const std::string& ifstr)
|
||||||
{
|
{
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
impl_->files = {ifstr};
|
impl_->files = {ifstr};
|
||||||
#else
|
|
||||||
impl_->file = ifstr;
|
|
||||||
#endif
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,30 +1635,18 @@ namespace nana
|
|||||||
return impl_->path;
|
return impl_->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
std::string filebox::file() const
|
||||||
const std::string& filebox::file() const
|
|
||||||
{
|
{
|
||||||
if(impl_->files.empty())
|
if(impl_->files.empty())
|
||||||
{
|
return {};
|
||||||
static const std::string empty = "";
|
|
||||||
return empty;
|
return impl_->files.front();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return impl_->files.front();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& filebox::files() const
|
const std::vector<std::string>& filebox::files() const
|
||||||
{
|
{
|
||||||
return impl_->files;
|
return impl_->files;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
const std::string& filebox::file() const
|
|
||||||
{
|
|
||||||
return impl_->file;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool filebox::show() const
|
bool filebox::show() const
|
||||||
{
|
{
|
||||||
@ -1332,7 +1757,7 @@ namespace nana
|
|||||||
|
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
using mode = filebox_implement::mode;
|
using mode = filebox_implement::mode;
|
||||||
filebox_implement fb(impl_->owner, (impl_->open_or_save ? mode::open_file : mode::write_file), impl_->title);
|
filebox_implement fb(impl_->owner, (impl_->open_or_save ? mode::open_file : mode::write_file), impl_->title, false, impl_->allow_multi_select);
|
||||||
|
|
||||||
if(impl_->filters.size())
|
if(impl_->filters.size())
|
||||||
{
|
{
|
||||||
@ -1353,27 +1778,28 @@ namespace nana
|
|||||||
else
|
else
|
||||||
fb.add_filter("All Files", "*.*");
|
fb.add_filter("All Files", "*.*");
|
||||||
|
|
||||||
fb.load_fs(impl_->path, impl_->file);
|
fb.load_fs(impl_->path, this->file());
|
||||||
|
|
||||||
API::modal_window(fb);
|
API::modal_window(fb);
|
||||||
if(false == fb.file(impl_->file))
|
|
||||||
|
fb.files().swap(impl_->files);
|
||||||
|
if(impl_->files.empty())
|
||||||
return false;
|
return false;
|
||||||
auto tpos = impl_->file.find_last_of("\\/");
|
|
||||||
if(tpos != impl_->file.npos)
|
auto tpos = impl_->files.front().find_last_of("\\/");
|
||||||
impl_->path = impl_->file.substr(0, tpos);
|
if(tpos != impl_->files.front().npos)
|
||||||
|
impl_->path = impl_->files.front().substr(0, tpos);
|
||||||
else
|
else
|
||||||
impl_->path.clear();
|
impl_->path.clear();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(NANA_WINDOWS)
|
|
||||||
void filebox::allow_multi_select(bool allow)
|
void filebox::allow_multi_select(bool allow)
|
||||||
{
|
{
|
||||||
impl_->allow_multi_select = allow;
|
impl_->allow_multi_select = allow;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
//end class filebox
|
//end class filebox
|
||||||
|
|
||||||
//class directory picker
|
//class directory picker
|
||||||
@ -1484,17 +1910,18 @@ namespace nana
|
|||||||
|
|
||||||
#elif defined(NANA_POSIX)
|
#elif defined(NANA_POSIX)
|
||||||
using mode = filebox_implement::mode;
|
using mode = filebox_implement::mode;
|
||||||
filebox_implement fb(impl_->owner, mode::open_directory, {}, true);
|
filebox_implement fb(impl_->owner, mode::open_directory, {}, true, false/*single select*/);
|
||||||
|
|
||||||
fb.load_fs(impl_->init_path, "");
|
fb.load_fs(impl_->init_path, "");
|
||||||
|
|
||||||
API::modal_window(fb);
|
API::modal_window(fb);
|
||||||
|
|
||||||
std::string path_directory;
|
std::string path_directory;
|
||||||
if(false == fb.file(path_directory))
|
auto path_dir = fb.files();
|
||||||
|
if(path_dir.empty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return path_type{path_directory};
|
return path_type{path_dir.front()};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A CheckBox Implementation
|
* A CheckBox Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -216,6 +216,7 @@ namespace nana{ namespace drawerbase
|
|||||||
{
|
{
|
||||||
e.uiobj->radio(false);
|
e.uiobj->radio(false);
|
||||||
e.uiobj->react(true);
|
e.uiobj->react(true);
|
||||||
|
API::umake_event(e.eh_clicked);
|
||||||
API::umake_event(e.eh_checked);
|
API::umake_event(e.eh_checked);
|
||||||
API::umake_event(e.eh_destroy);
|
API::umake_event(e.eh_destroy);
|
||||||
API::umake_event(e.eh_keyboard);
|
API::umake_event(e.eh_keyboard);
|
||||||
@ -232,7 +233,7 @@ namespace nana{ namespace drawerbase
|
|||||||
|
|
||||||
el.uiobj = &uiobj;
|
el.uiobj = &uiobj;
|
||||||
|
|
||||||
uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg)
|
el.eh_checked = uiobj.events().checked.connect_unignorable([this](const arg_checkbox& arg)
|
||||||
{
|
{
|
||||||
if (arg.widget->checked())
|
if (arg.widget->checked())
|
||||||
{
|
{
|
||||||
@ -244,7 +245,7 @@ namespace nana{ namespace drawerbase
|
|||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
el.eh_checked = uiobj.events().click.connect_unignorable([this](const arg_click& arg)
|
el.eh_clicked = uiobj.events().click.connect_unignorable([this](const arg_click& arg)
|
||||||
{
|
{
|
||||||
for (auto & i : ui_container_)
|
for (auto & i : ui_container_)
|
||||||
i.uiobj->check(arg.window_handle == i.uiobj->handle());
|
i.uiobj->check(arg.window_handle == i.uiobj->handle());
|
||||||
|
|||||||
@ -27,10 +27,11 @@
|
|||||||
if(empty()) \
|
if(empty()) \
|
||||||
throw std::logic_error("the group is invalid");
|
throw std::logic_error("the group is invalid");
|
||||||
|
|
||||||
namespace nana{
|
namespace nana
|
||||||
|
{
|
||||||
|
|
||||||
static const char* field_title = "__nana_group_title__";
|
static const char* field_title = "__nana_group_title__";
|
||||||
static const char* field_options = "__nana_group_options__";
|
static const char* field_options = "__nana_group_options__";
|
||||||
|
|
||||||
struct group::implement
|
struct group::implement
|
||||||
{
|
{
|
||||||
@ -41,108 +42,109 @@ namespace nana{
|
|||||||
unsigned gap{2};
|
unsigned gap{2};
|
||||||
std::string usr_div_str;
|
std::string usr_div_str;
|
||||||
|
|
||||||
nana::size caption_dimension;
|
nana::size caption_dimension;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<checkbox>> options;
|
std::vector<std::unique_ptr<checkbox>> options;
|
||||||
radio_group * radio_logic{nullptr};
|
radio_group * radio_logic{nullptr};
|
||||||
|
|
||||||
implement() = default;
|
implement() = default;
|
||||||
|
|
||||||
implement(window grp_panel, ::std::string titel, bool vsb, unsigned gap=2)
|
implement(window grp_panel, ::std::string titel, bool vsb, unsigned gap=2)
|
||||||
: caption (grp_panel, std::move(titel), vsb),
|
: caption (grp_panel, std::move(titel), vsb),
|
||||||
place_content{grp_panel},
|
place_content{grp_panel},
|
||||||
gap{gap}
|
gap{gap}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void create(window pnl)
|
void create(window pnl)
|
||||||
{
|
{
|
||||||
caption.create(pnl);
|
caption.create(pnl);
|
||||||
caption.caption("");
|
caption.caption("");
|
||||||
place_content.bind(pnl);
|
place_content.bind(pnl);
|
||||||
|
|
||||||
if (!radio_logic)
|
if (!radio_logic)
|
||||||
radio_logic = new radio_group;
|
radio_logic = new radio_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_div()
|
void update_div()
|
||||||
{
|
{
|
||||||
const std::size_t padding = 10;
|
const std::size_t padding = 10;
|
||||||
caption_dimension = caption.measure(1000);
|
caption_dimension = caption.measure(1000);
|
||||||
caption_dimension.width += 1;
|
caption_dimension.width += 1;
|
||||||
|
|
||||||
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
std::string div = "vert margin=[0," + std::to_string(gap) + "," + std::to_string(gap + 5) + "," + std::to_string(gap) + "]";
|
||||||
|
|
||||||
div += "<weight=" + std::to_string(caption_dimension.height) + " ";
|
div += "<weight=" + std::to_string(caption_dimension.height) + " ";
|
||||||
|
|
||||||
if (align::left == caption_align)
|
if (align::left == caption_align)
|
||||||
div += "<weight=" + std::to_string(padding) + ">";
|
div += "<weight=" + std::to_string(padding) + ">";
|
||||||
else
|
else
|
||||||
div += "<>"; //right or center
|
div += "<>"; //right or center
|
||||||
|
|
||||||
div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">";
|
div += "<" + std::string{ field_title } + " weight=" + std::to_string(caption_dimension.width) + ">";
|
||||||
|
|
||||||
if (align::right == caption_align)
|
if (align::right == caption_align)
|
||||||
div += "<weight=" + std::to_string(padding) + ">";
|
div += "<weight=" + std::to_string(padding) + ">";
|
||||||
else if (align::center == caption_align)
|
else if (align::center == caption_align)
|
||||||
div += "<>";
|
div += "<>";
|
||||||
|
|
||||||
div += "><<vert margin=5 " + std::string(field_options) + ">";
|
div += "><<vert margin=5 " + std::string(field_options) + ">";
|
||||||
|
|
||||||
if (!usr_div_str.empty())
|
if (!usr_div_str.empty())
|
||||||
div += "<" + usr_div_str + ">>";
|
div += "<" + usr_div_str + ">>";
|
||||||
else
|
else
|
||||||
div += ">";
|
div += ">";
|
||||||
|
|
||||||
place_content.div(div.c_str());
|
place_content.div(div.c_str());
|
||||||
|
|
||||||
if (options.empty())
|
if (options.empty())
|
||||||
place_content.field_display(field_options, false);
|
place_content.field_display(field_options, false);
|
||||||
|
|
||||||
if (caption.caption().empty())
|
if (caption.caption().empty())
|
||||||
place_content.field_display(field_title, false);
|
place_content.field_display(field_title, false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
group::group()
|
group::group()
|
||||||
: impl_(new implement)
|
: impl_(new implement)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
group::group(window parent, const rectangle& r, bool vsb)
|
group::group(window parent, const rectangle& r, bool vsb)
|
||||||
: group()
|
: group()
|
||||||
{
|
{
|
||||||
create(parent, r, vsb);
|
create(parent, r, vsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
|
using groupbase_type = widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>;
|
||||||
|
|
||||||
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
group::group(window parent, ::std::string titel, bool formatted, unsigned gap, const rectangle& r, bool vsb)
|
||||||
: group(parent, r, vsb)
|
: group(parent, r, vsb)
|
||||||
{
|
{
|
||||||
this->bgcolor(API::bgcolor(parent));
|
this->bgcolor(API::bgcolor(parent));
|
||||||
|
|
||||||
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
impl_.reset(new implement(*this, std::move(titel), vsb, gap));
|
||||||
|
|
||||||
impl_->caption.format(formatted);
|
impl_->caption.format(formatted);
|
||||||
_m_init();
|
_m_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
group::~group()
|
group::~group()
|
||||||
{
|
{
|
||||||
delete impl_->radio_logic;
|
delete impl_->radio_logic;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox& group::add_option(std::string text)
|
checkbox& group::add_option(std::string text)
|
||||||
{
|
{
|
||||||
_THROW_IF_EMPTY()
|
_THROW_IF_EMPTY()
|
||||||
|
|
||||||
#ifdef _nana_std_has_emplace_return_type
|
#ifdef _nana_std_has_emplace_return_type
|
||||||
auto & opt = impl_->options.emplace_back(new checkbox{ handle() });
|
auto & opt = impl_->options.emplace_back(new checkbox { handle() });
|
||||||
#else
|
#else
|
||||||
impl_->options.emplace_back(new checkbox(handle()));
|
impl_->options.emplace_back(new checkbox(handle()));
|
||||||
auto & opt = impl_->options.back();
|
auto & opt = impl_->options.back();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
opt->transparent(true);
|
opt->transparent(true);
|
||||||
opt->caption(std::move(text));
|
opt->caption(std::move(text));
|
||||||
impl_->place_content[field_options] << *opt;
|
impl_->place_content[field_options] << *opt;
|
||||||
@ -358,5 +360,6 @@ namespace nana{
|
|||||||
impl_->update_div();
|
impl_->update_div();
|
||||||
impl_->place_content.collocate();
|
impl_->place_content.collocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A List Box Implementation
|
* A List Box Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -17,6 +17,12 @@
|
|||||||
* dankan1890(pr#158)
|
* dankan1890(pr#158)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <algorithm>
|
||||||
|
#include <list>
|
||||||
|
#include <deque>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <map>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <nana/gui/widgets/listbox.hpp>
|
#include <nana/gui/widgets/listbox.hpp>
|
||||||
#include <nana/gui/widgets/panel.hpp> //for inline widget
|
#include <nana/gui/widgets/panel.hpp> //for inline widget
|
||||||
@ -28,12 +34,6 @@
|
|||||||
#include <nana/system/platform.hpp>
|
#include <nana/system/platform.hpp>
|
||||||
#include "skeletons/content_view.hpp"
|
#include "skeletons/content_view.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <list>
|
|
||||||
#include <deque>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
static void check_range(std::size_t pos, std::size_t size)
|
static void check_range(std::size_t pos, std::size_t size)
|
||||||
@ -130,17 +130,18 @@ namespace nana
|
|||||||
struct column
|
struct column
|
||||||
: public column_interface
|
: public column_interface
|
||||||
{
|
{
|
||||||
native_string_type caption;
|
native_string_type caption; //< header title
|
||||||
unsigned width_px;
|
unsigned width_px; //< column width in pixels
|
||||||
std::pair<unsigned, unsigned> range_width_px;
|
std::pair<unsigned, unsigned> range_width_px; //< allowed width
|
||||||
bool visible_state{ true };
|
bool visible_state{ true };
|
||||||
|
|
||||||
/// Absolute position of column when it was creating
|
|
||||||
size_type index;
|
size_type index; //< Absolute position of column when it was created
|
||||||
|
|
||||||
nana::align alignment{ nana::align::left };
|
nana::align alignment{ nana::align::left };
|
||||||
|
|
||||||
std::function<bool(const std::string&, nana::any*, const std::string&, nana::any*, bool reverse)> weak_ordering;
|
std::function<bool(const std::string&, nana::any*,
|
||||||
|
const std::string&, nana::any*, bool reverse)> weak_ordering;
|
||||||
|
|
||||||
std::shared_ptr<paint::font> font; ///< The exclusive column font
|
std::shared_ptr<paint::font> font; ///< The exclusive column font
|
||||||
|
|
||||||
@ -186,18 +187,18 @@ namespace nana
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
//The definition is provided after essence
|
/// The definition is provided after essence
|
||||||
void _m_refresh() noexcept;
|
void _m_refresh() noexcept;
|
||||||
private:
|
private:
|
||||||
essence* const ess_;
|
essence* const ess_;
|
||||||
public:
|
public:
|
||||||
//Implementation of column_interface
|
/// Implementation of column_interface
|
||||||
unsigned width() const noexcept override
|
unsigned width() const noexcept override
|
||||||
{
|
{
|
||||||
return width_px;
|
return width_px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the width and overrides the ranged width
|
/// Sets the width and overrides the ranged width
|
||||||
void width(unsigned pixels) noexcept override
|
void width(unsigned pixels) noexcept override
|
||||||
{
|
{
|
||||||
width_px = pixels;
|
width_px = pixels;
|
||||||
@ -223,7 +224,7 @@ namespace nana
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type position(bool disp_order) const noexcept override; //The definition is provided after essence
|
size_type position(bool disp_order) const noexcept override; //< The definition is provided after essence
|
||||||
|
|
||||||
std::string text() const noexcept override
|
std::string text() const noexcept override
|
||||||
{
|
{
|
||||||
@ -440,7 +441,7 @@ namespace nana
|
|||||||
throw std::invalid_argument("listbox: invalid header index");
|
throw std::invalid_argument("listbox: invalid header index");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find and return a ref to the column that originaly was at position "pos" previous to any list reorganization.
|
/// find and return a ref to the column that originally was at position "pos" previous to any list reorganization.
|
||||||
column& at(size_type pos, bool disp_order = false)
|
column& at(size_type pos, bool disp_order = false)
|
||||||
{
|
{
|
||||||
check_range(pos, cont_.size());
|
check_range(pos, cont_.size());
|
||||||
@ -507,7 +508,7 @@ namespace nana
|
|||||||
return{ left, 0 };
|
return{ left, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// return the original index of the visible col currently before(in front of) or after the col originaly at index "index"
|
/// return the original index of the visible col currently before(in front of) or after the col originally at index "index"
|
||||||
size_type next(size_type index) const noexcept
|
size_type next(size_type index) const noexcept
|
||||||
{
|
{
|
||||||
bool found_me = false;
|
bool found_me = false;
|
||||||
@ -542,7 +543,25 @@ namespace nana
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// move the col originaly at "from" to the position currently in front (or after) the col originaly at index "to" invalidating some current index
|
|
||||||
|
/// move col to view pos
|
||||||
|
void move_to_view_pos (size_type col, size_type view, bool front) noexcept
|
||||||
|
{
|
||||||
|
if (!front) view++;
|
||||||
|
if (view >= cont_.size() ) return;
|
||||||
|
|
||||||
|
auto i = std::find_if( cont_.begin(),
|
||||||
|
cont_.end(),
|
||||||
|
[&](const column& c){return col==c.index;});
|
||||||
|
|
||||||
|
if (i==cont_.end()) return;
|
||||||
|
|
||||||
|
auto col_from = *i;
|
||||||
|
cont_.erase(i);
|
||||||
|
cont_.insert(cont_.begin()+ view, col_from);
|
||||||
|
|
||||||
|
}
|
||||||
|
/// move the col originally at "from" to the position currently in front (or after) the col originally at index "to" invalidating some current index
|
||||||
void move(size_type from, size_type to, bool front) noexcept
|
void move(size_type from, size_type to, bool front) noexcept
|
||||||
{
|
{
|
||||||
if ((from == to) || (from >= cont_.size()) || (to >= cont_.size()))
|
if ((from == to) || (from >= cont_.size()) || (to >= cont_.size()))
|
||||||
@ -1850,6 +1869,11 @@ namespace nana
|
|||||||
(for_selection ? single_selection_ : single_check_) = false;
|
(for_selection ? single_selection_ : single_check_) = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_single_enabled(bool for_selection) const noexcept
|
||||||
|
{
|
||||||
|
return (for_selection ? single_selection_ : single_check_);
|
||||||
|
}
|
||||||
|
|
||||||
size_type size_item(size_type cat) const
|
size_type size_item(size_type cat) const
|
||||||
{
|
{
|
||||||
return get(cat)->items.size();
|
return get(cat)->items.size();
|
||||||
@ -2006,6 +2030,8 @@ namespace nana
|
|||||||
{
|
{
|
||||||
bool started{ false };
|
bool started{ false };
|
||||||
bool reverse_selection{ false };
|
bool reverse_selection{ false };
|
||||||
|
bool scroll_direction;
|
||||||
|
bool deselect_when_start_to_move;
|
||||||
|
|
||||||
point screen_pos;
|
point screen_pos;
|
||||||
point begin_position; ///< Logical position to the
|
point begin_position; ///< Logical position to the
|
||||||
@ -2013,9 +2039,18 @@ namespace nana
|
|||||||
index_pairs already_selected;
|
index_pairs already_selected;
|
||||||
index_pairs selections;
|
index_pairs selections;
|
||||||
|
|
||||||
bool scroll_direction;
|
|
||||||
unsigned scroll_step{ 1 };
|
unsigned scroll_step{ 1 };
|
||||||
unsigned mouse_move_timestamp{ 0 };
|
unsigned mouse_move_timestamp{ 0 };
|
||||||
|
|
||||||
|
bool is_already_selected(const index_pair& abs_pos) const noexcept
|
||||||
|
{
|
||||||
|
return (already_selected.cend() != std::find(already_selected.cbegin(), already_selected.cend(), abs_pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_selected(const index_pair& abs_pos) const noexcept
|
||||||
|
{
|
||||||
|
return (selections.cend() != std::find(selections.cbegin(), selections.cend(), abs_pos));
|
||||||
|
}
|
||||||
}mouse_selection;
|
}mouse_selection;
|
||||||
|
|
||||||
|
|
||||||
@ -2113,6 +2148,7 @@ namespace nana
|
|||||||
mouse_selection.started = true;
|
mouse_selection.started = true;
|
||||||
mouse_selection.begin_position = logic_pos;
|
mouse_selection.begin_position = logic_pos;
|
||||||
mouse_selection.end_position = logic_pos;
|
mouse_selection.end_position = logic_pos;
|
||||||
|
mouse_selection.deselect_when_start_to_move = true;
|
||||||
|
|
||||||
if (arg.ctrl || arg.shift)
|
if (arg.ctrl || arg.shift)
|
||||||
{
|
{
|
||||||
@ -2128,6 +2164,17 @@ namespace nana
|
|||||||
if (!mouse_selection.started)
|
if (!mouse_selection.started)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// When the button is pressed and start to move the mouse, the listbox should deselect all items.
|
||||||
|
// But when ctrl is clicked
|
||||||
|
if (mouse_selection.deselect_when_start_to_move)
|
||||||
|
{
|
||||||
|
mouse_selection.deselect_when_start_to_move = false;
|
||||||
|
if (mouse_selection.already_selected.empty())
|
||||||
|
lister.select_for_all(false);
|
||||||
|
|
||||||
|
mouse_selection.selections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -2143,7 +2190,7 @@ namespace nana
|
|||||||
|
|
||||||
mouse_selection.end_position = logic_pos;
|
mouse_selection.end_position = logic_pos;
|
||||||
|
|
||||||
bool cancel_selections = true;
|
std::vector<std::pair<index_pair, bool>> selections;
|
||||||
|
|
||||||
auto content_x = coordinate_cast({ columns_range().first, 0 }, true).x;
|
auto content_x = coordinate_cast({ columns_range().first, 0 }, true).x;
|
||||||
if ((std::max)(mouse_selection.end_position.x, mouse_selection.begin_position.x) >= content_x &&
|
if ((std::max)(mouse_selection.end_position.x, mouse_selection.begin_position.x) >= content_x &&
|
||||||
@ -2154,18 +2201,18 @@ namespace nana
|
|||||||
auto begin = lister.advance(lister.first(), begin_off);
|
auto begin = lister.advance(lister.first(), begin_off);
|
||||||
if (!begin.empty())
|
if (!begin.empty())
|
||||||
{
|
{
|
||||||
std::vector<std::pair<index_pair, bool>> selections;
|
|
||||||
|
|
||||||
if ((mouse_selection.end_position.y < 0) || (lister.distance(lister.first(), begin) == begin_off))
|
if ((mouse_selection.end_position.y < 0) || (lister.distance(lister.first(), begin) == begin_off))
|
||||||
{
|
{
|
||||||
//The range [begin_off, last_off] is a range of box selection
|
//The range [begin_off, last_off] is a range of box selection
|
||||||
auto last_off = (std::max)(mouse_selection.begin_position.y, mouse_selection.end_position.y) / item_height();
|
auto last_off = (std::max)(mouse_selection.begin_position.y, mouse_selection.end_position.y) / item_height();
|
||||||
auto last = lister.advance(lister.first(), last_off);
|
auto last = lister.advance(lister.first(), last_off);
|
||||||
|
|
||||||
|
//Tries to select the items in the box, then returns the items with their previous selected states
|
||||||
selections = lister.select_display_range_if(begin, last, false, [this](const index_pair& abs_pos) {
|
selections = lister.select_display_range_if(begin, last, false, [this](const index_pair& abs_pos) {
|
||||||
if (this->mouse_selection.reverse_selection)
|
if (mouse_selection.reverse_selection)
|
||||||
{
|
{
|
||||||
if (mouse_selection.already_selected.cend() != std::find(mouse_selection.already_selected.cbegin(), mouse_selection.already_selected.cend(), abs_pos))
|
//Deselects the items in the box which has been already selected
|
||||||
|
if(mouse_selection.is_already_selected(abs_pos))
|
||||||
{
|
{
|
||||||
item_proxy{ this, abs_pos }.select(false);
|
item_proxy{ this, abs_pos }.select(false);
|
||||||
return false;
|
return false;
|
||||||
@ -2176,21 +2223,21 @@ namespace nana
|
|||||||
|
|
||||||
for (auto & pair : selections)
|
for (auto & pair : selections)
|
||||||
{
|
{
|
||||||
|
//Continue if the previous state is selected. It indicates the item now is not selected.
|
||||||
if (pair.second)
|
if (pair.second)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mouse_selection.selections.cend() ==
|
//Add the item to selections container.
|
||||||
std::find(mouse_selection.selections.cbegin(), mouse_selection.selections.cend(), pair.first))
|
if(!mouse_selection.is_selected(pair.first))
|
||||||
{
|
|
||||||
mouse_selection.selections.push_back(pair.first);
|
mouse_selection.selections.push_back(pair.first);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Deselects the items which are in mouse_selection.selections but not in selections.
|
||||||
|
//Eq to mouse_selection.selections = selections
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
for (auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
for (auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
||||||
#else
|
#else
|
||||||
for(auto i = mouse_selection.selections.begin(); i != mouse_selection.selections.end();)
|
for(auto i = mouse_selection.selections.begin(); i != mouse_selection.selections.end();)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
auto & selpos = *i;
|
auto & selpos = *i;
|
||||||
@ -2204,30 +2251,45 @@ namespace nana
|
|||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel_selections = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancel_selections)
|
//Restores an already selected item if it is not in selections.
|
||||||
|
for (auto& abs_pos : mouse_selection.already_selected)
|
||||||
{
|
{
|
||||||
if (!mouse_selection.already_selected.empty())
|
if (selections.cend() == std::find_if(selections.cbegin(), selections.cend(), [abs_pos](const std::pair<index_pair, bool>& rhs) {
|
||||||
|
return (abs_pos == rhs.first);
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
for (auto & pos : mouse_selection.selections)
|
item_proxy m{ this, abs_pos };
|
||||||
item_proxy(this, pos).select(false);
|
if (!m.selected())
|
||||||
|
|
||||||
//Don't restore the already selections if it is reverse selection(pressing shift). Behaves like Windows Explorer.
|
|
||||||
if (!mouse_selection.reverse_selection)
|
|
||||||
{
|
{
|
||||||
for (auto & abs_pos : mouse_selection.already_selected)
|
m.select(true);
|
||||||
item_proxy(this, abs_pos).select(true);
|
//Add the item to selections container.
|
||||||
|
if(!mouse_selection.is_selected(abs_pos))
|
||||||
|
mouse_selection.selections.push_back(abs_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
lister.select_for_all(false);
|
|
||||||
|
|
||||||
mouse_selection.selections.clear();
|
//Deselects the item which is not in already_selected and selections but in mouse_selection.selections
|
||||||
|
for(auto i = mouse_selection.selections.cbegin(); i != mouse_selection.selections.cend();)
|
||||||
|
{
|
||||||
|
auto abs_pos = *i;
|
||||||
|
|
||||||
|
bool is_box_selected = (selections.cend() != std::find_if(selections.cbegin(), selections.cend(), [abs_pos](const std::pair<index_pair, bool>& rhs) {
|
||||||
|
return (abs_pos == rhs.first);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (is_box_selected || mouse_selection.is_already_selected(abs_pos))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_proxy{ this, abs_pos }.select(false);
|
||||||
|
i = mouse_selection.selections.erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4110,11 +4172,13 @@ namespace nana
|
|||||||
essence_->draw_peripheral();
|
essence_->draw_peripheral();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In mouse move event, it cancels the msup_deselect if the listbox is draggable or it started the mouse selection.
|
||||||
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
using item_state = essence::item_state;
|
using item_state = essence::item_state;
|
||||||
using parts = essence::parts;
|
using parts = essence::parts;
|
||||||
|
|
||||||
|
//Don't deselect the items if the listbox is draggable
|
||||||
if ((operation_states::msup_deselect == essence_->operation.state) && API::dev::window_draggable(arg.window_handle))
|
if ((operation_states::msup_deselect == essence_->operation.state) && API::dev::window_draggable(arg.window_handle))
|
||||||
essence_->operation.state = operation_states::none;
|
essence_->operation.state = operation_states::none;
|
||||||
|
|
||||||
@ -4168,6 +4232,9 @@ namespace nana
|
|||||||
if (essence_->mouse_selection.started)
|
if (essence_->mouse_selection.started)
|
||||||
{
|
{
|
||||||
essence_->update_mouse_selection(arg.pos);
|
essence_->update_mouse_selection(arg.pos);
|
||||||
|
|
||||||
|
//Don't deselect items if the mouse selection is started
|
||||||
|
essence_->operation.state = operation_states::none;
|
||||||
need_refresh = true;
|
need_refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4364,7 +4431,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);
|
essence_->start_mouse_selection(arg);
|
||||||
|
|
||||||
//Deselection of all items is deferred to the mouse up event when ctrl or shift is not pressed
|
//Deselecting all items is deferred to the mouse up event when ctrl or shift is not pressed
|
||||||
//Pressing ctrl or shift is to selects other items without deselecting current selections.
|
//Pressing ctrl or shift is to selects other items without deselecting current selections.
|
||||||
if (!(arg.ctrl || arg.shift))
|
if (!(arg.ctrl || arg.shift))
|
||||||
{
|
{
|
||||||
@ -4411,7 +4478,7 @@ namespace nana
|
|||||||
essence_->stop_mouse_selection();
|
essence_->stop_mouse_selection();
|
||||||
need_refresh = true;
|
need_refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation_states::msup_deselect == essence_->operation.state)
|
if (operation_states::msup_deselect == essence_->operation.state)
|
||||||
{
|
{
|
||||||
essence_->operation.state = operation_states::none;
|
essence_->operation.state = operation_states::none;
|
||||||
@ -5954,9 +6021,16 @@ namespace nana
|
|||||||
|
|
||||||
void listbox::disable_single(bool for_selection)
|
void listbox::disable_single(bool for_selection)
|
||||||
{
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
_m_ess().lister.disable_single(for_selection);
|
_m_ess().lister.disable_single(for_selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool listbox::is_single_enabled(bool for_selection) const noexcept
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
return _m_ess().lister.is_single_enabled(for_selection);
|
||||||
|
}
|
||||||
|
|
||||||
listbox::export_options& listbox::def_export_options()
|
listbox::export_options& listbox::def_export_options()
|
||||||
{
|
{
|
||||||
return _m_ess().def_exp_options;
|
return _m_ess().def_exp_options;
|
||||||
@ -6097,5 +6171,49 @@ namespace nana
|
|||||||
internal_scope_guard lock;
|
internal_scope_guard lock;
|
||||||
return _m_ess().content_view->scroll_operation();
|
return _m_ess().content_view->scroll_operation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Move column to view_position
|
||||||
|
void listbox::move_column(size_type abs_pos, size_type view_pos)
|
||||||
|
{
|
||||||
|
internal_scope_guard lock;
|
||||||
|
return _m_ess().header.move_to_view_pos(abs_pos, view_pos, true);
|
||||||
|
_m_ess().update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sort columns in range first_col to last_col inclusive using a row
|
||||||
|
void listbox::reorder_columns(size_type first_col,
|
||||||
|
size_type last_col,
|
||||||
|
index_pair row, bool reverse,
|
||||||
|
std::function<bool(const std::string &cell1, size_type col1,
|
||||||
|
const std::string &cell2, size_type col2,
|
||||||
|
const nana::any *rowval,
|
||||||
|
bool reverse)> comp)
|
||||||
|
{
|
||||||
|
if (first_col<0 || last_col<=first_col)
|
||||||
|
return;
|
||||||
|
if (last_col >= column_size())
|
||||||
|
return;
|
||||||
|
std::vector<size_type> new_idx;
|
||||||
|
for(size_type i=first_col; i<=last_col; ++i) new_idx.push_back(i);
|
||||||
|
|
||||||
|
internal_scope_guard lock;
|
||||||
|
auto ip_row = this->at(row);
|
||||||
|
auto pnany=_m_ess().lister.anyobj(row,false);
|
||||||
|
std::sort(new_idx.begin(), new_idx.end(), [&](size_type col1,
|
||||||
|
size_type col2)
|
||||||
|
{
|
||||||
|
return comp(ip_row.text(col1), col1,
|
||||||
|
ip_row.text(col2), col2,
|
||||||
|
pnany, reverse);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Only change the view position of columns
|
||||||
|
for(size_t i=0; i<new_idx.size(); ++i)
|
||||||
|
{
|
||||||
|
move_column(new_idx[i],i+first_col);
|
||||||
|
}
|
||||||
|
_m_ess().update();
|
||||||
|
}
|
||||||
|
|
||||||
//end class listbox
|
//end class listbox
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|||||||
@ -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-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -1728,7 +1728,7 @@ namespace nana {
|
|||||||
str = impl_->textbase.getline(0);
|
str = impl_->textbase.getline(0);
|
||||||
for (std::size_t i = 1; i < lines; ++i)
|
for (std::size_t i = 1; i < lines; ++i)
|
||||||
{
|
{
|
||||||
str += L"\n\r";
|
str += L"\r\n";
|
||||||
str += impl_->textbase.getline(i);
|
str += impl_->textbase.getline(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -245,7 +245,7 @@ namespace nana
|
|||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
enum class parts{none, bar, slider};
|
enum class parts{none, bar, slider};
|
||||||
|
|
||||||
using graph_reference = drawer_trigger::graph_reference;
|
using graph_reference = drawer_trigger::graph_reference;
|
||||||
|
|
||||||
model()
|
model()
|
||||||
@ -256,7 +256,7 @@ namespace nana
|
|||||||
proto_.renderer = pat::cloneable<renderer_interface>{interior_renderer{}};
|
proto_.renderer = pat::cloneable<renderer_interface>{interior_renderer{}};
|
||||||
|
|
||||||
attr_.seek_dir = seekdir::bilateral;
|
attr_.seek_dir = seekdir::bilateral;
|
||||||
|
|
||||||
attr_.is_draw_adorn = false;
|
attr_.is_draw_adorn = false;
|
||||||
attr_.vcur = 0;
|
attr_.vcur = 0;
|
||||||
attr_.vmax = 10;
|
attr_.vmax = 10;
|
||||||
@ -361,7 +361,7 @@ namespace nana
|
|||||||
parts seek_where(::nana::point pos) const
|
parts seek_where(::nana::point pos) const
|
||||||
{
|
{
|
||||||
nana::rectangle r = _m_bar_area();
|
nana::rectangle r = _m_bar_area();
|
||||||
|
|
||||||
if (attr_.slider.vert)
|
if (attr_.slider.vert)
|
||||||
{
|
{
|
||||||
std::swap(pos.x, pos.y);
|
std::swap(pos.x, pos.y);
|
||||||
@ -373,7 +373,7 @@ namespace nana
|
|||||||
return parts::slider;
|
return parts::slider;
|
||||||
|
|
||||||
sdpos = static_cast<int>(attr_.slider.weight) / 2;
|
sdpos = static_cast<int>(attr_.slider.weight) / 2;
|
||||||
|
|
||||||
if (sdpos <= pos.x && pos.x < sdpos + static_cast<int>(r.width))
|
if (sdpos <= pos.x && pos.x < sdpos + static_cast<int>(r.width))
|
||||||
{
|
{
|
||||||
if(pos.y < r.bottom())
|
if(pos.y < r.bottom())
|
||||||
@ -446,7 +446,7 @@ namespace nana
|
|||||||
bool move_slider(const ::nana::point& pos)
|
bool move_slider(const ::nana::point& pos)
|
||||||
{
|
{
|
||||||
int adorn_pos = slider_state_.snap_pos + (attr_.slider.vert ? pos.y : pos.x) - slider_state_.refpos.x;
|
int adorn_pos = slider_state_.snap_pos + (attr_.slider.vert ? pos.y : pos.x) - slider_state_.refpos.x;
|
||||||
|
|
||||||
if (adorn_pos > 0)
|
if (adorn_pos > 0)
|
||||||
{
|
{
|
||||||
int range = static_cast<int>(_m_range());
|
int range = static_cast<int>(_m_range());
|
||||||
@ -691,7 +691,7 @@ namespace nana
|
|||||||
window wd;
|
window wd;
|
||||||
nana::slider * widget;
|
nana::slider * widget;
|
||||||
}other_;
|
}other_;
|
||||||
|
|
||||||
struct prototype_tag
|
struct prototype_tag
|
||||||
{
|
{
|
||||||
pat::cloneable<slider::renderer_interface> renderer;
|
pat::cloneable<slider::renderer_interface> renderer;
|
||||||
@ -759,9 +759,9 @@ namespace nana
|
|||||||
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
void trigger::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||||
{
|
{
|
||||||
// check if slider is disabled
|
// check if slider is disabled
|
||||||
if(!API::get_widget(arg.window_handle)->enabled())
|
if(!API::get_widget(arg.window_handle)->enabled())
|
||||||
return; // do nothing
|
return; // do nothing
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
if (model_ptr_->if_trace_slider())
|
if (model_ptr_->if_trace_slider())
|
||||||
{
|
{
|
||||||
@ -804,7 +804,7 @@ namespace nana
|
|||||||
|
|
||||||
//class slider
|
//class slider
|
||||||
slider::slider(){}
|
slider::slider(){}
|
||||||
|
|
||||||
slider::slider(window wd, bool visible)
|
slider::slider(window wd, bool visible)
|
||||||
{
|
{
|
||||||
create(wd, rectangle(), visible);
|
create(wd, rectangle(), visible);
|
||||||
@ -844,10 +844,14 @@ namespace nana
|
|||||||
return get_drawer_trigger().get_model()->attribute().vmax;
|
return get_drawer_trigger().get_model()->attribute().vmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slider::value(unsigned v)
|
void slider::value(int v)
|
||||||
{
|
{
|
||||||
if(handle())
|
if(handle())
|
||||||
{
|
{
|
||||||
|
// limit to positive values, vcur expects unsigned
|
||||||
|
if( v < 0 )
|
||||||
|
v = 0;
|
||||||
|
|
||||||
if(get_drawer_trigger().get_model()->vcur(v))
|
if(get_drawer_trigger().get_model()->vcur(v))
|
||||||
API::refresh_window(handle());
|
API::refresh_window(handle());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A Spin box widget
|
* A Spin box widget
|
||||||
* 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-2019 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
|
||||||
@ -467,7 +467,7 @@ namespace nana
|
|||||||
|
|
||||||
std::wstring text;
|
std::wstring text;
|
||||||
|
|
||||||
if (API::is_focus_ready(editor_->window_handle()))
|
if (API::is_focus_ready(editor_->window_handle()) && editor_->attr().editable)
|
||||||
text = to_wstring(range_->value());
|
text = to_wstring(range_->value());
|
||||||
else
|
else
|
||||||
text = to_wstring(modifier_.prefix + range_->value() + modifier_.suffix);
|
text = to_wstring(modifier_.prefix + range_->value() + modifier_.suffix);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* A Treebox Implementation
|
* A Treebox Implementation
|
||||||
* Nana C++ Library(http://www.nanapro.org)
|
* Nana C++ Library(http://www.nanapro.org)
|
||||||
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
|
* Copyright(C) 2003-2019 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
|
||||||
@ -1330,6 +1330,10 @@ namespace nana
|
|||||||
class internal_placer
|
class internal_placer
|
||||||
: public compset_placer_interface
|
: public compset_placer_interface
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
internal_placer(const scheme& schm):
|
||||||
|
scheme_(schm)
|
||||||
|
{}
|
||||||
private:
|
private:
|
||||||
//Implement the compset_locator_interface
|
//Implement the compset_locator_interface
|
||||||
|
|
||||||
@ -1364,17 +1368,24 @@ namespace nana
|
|||||||
|
|
||||||
virtual unsigned item_height(graph_reference graph) const override
|
virtual unsigned item_height(graph_reference graph) const override
|
||||||
{
|
{
|
||||||
auto m = std::max((enable_crook_ ? wdg_scheme_ptr_->crook_size : 0), (enable_icon_ ? wdg_scheme_ptr_->icon_size : 0));
|
auto m = std::max((enable_crook_ ? scheme_.crook_size : 0), (enable_icon_ ? scheme_.icon_size : 0));
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
unsigned as = 0, ds = 0, il;
|
||||||
|
graph.text_metrics(as, ds, il);
|
||||||
|
return std::max(as + ds + 8, m);
|
||||||
|
#else
|
||||||
#ifdef _nana_std_has_string_view
|
#ifdef _nana_std_has_string_view
|
||||||
return std::max(m, graph.text_extent_size(std::wstring_view{ L"jH{", 3 }).height + 8);
|
return std::max(m, graph.text_extent_size(std::wstring_view{ L"jH{", 3 }).height + 8);
|
||||||
#else
|
#else
|
||||||
return std::max(m, graph.text_extent_size(L"jH{", 3).height + 8);
|
return std::max(m, graph.text_extent_size(L"jH{", 3).height + 8);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override
|
virtual unsigned item_width(graph_reference graph, const item_attribute_t& attr) const override
|
||||||
{
|
{
|
||||||
return graph.text_extent_size(attr.text).width + (enable_crook_ ? wdg_scheme_ptr_->crook_size : 0) + (enable_icon_ ? wdg_scheme_ptr_ ->icon_size: 0) + (wdg_scheme_ptr_->text_offset << 1) + wdg_scheme_ptr_->item_offset;
|
return graph.text_extent_size(attr.text).width + (enable_crook_ ? scheme_.crook_size : 0) + (enable_icon_ ? scheme_.icon_size : 0) + (scheme_.text_offset << 1) + scheme_.item_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Locate a component through the specified coordinate.
|
// Locate a component through the specified coordinate.
|
||||||
@ -1389,7 +1400,7 @@ namespace nana
|
|||||||
case component_t::expander:
|
case component_t::expander:
|
||||||
if(attr.has_children)
|
if(attr.has_children)
|
||||||
{
|
{
|
||||||
r->width = wdg_scheme_ptr_->item_offset;
|
r->width = scheme_.item_offset;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1398,26 +1409,26 @@ namespace nana
|
|||||||
case component_t::crook:
|
case component_t::crook:
|
||||||
if(enable_crook_)
|
if(enable_crook_)
|
||||||
{
|
{
|
||||||
r->x += wdg_scheme_ptr_->item_offset;
|
r->x += scheme_.item_offset;
|
||||||
r->width = wdg_scheme_ptr_->crook_size;
|
r->width = scheme_.crook_size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case component_t::icon:
|
case component_t::icon:
|
||||||
if(enable_icon_)
|
if(enable_icon_)
|
||||||
{
|
{
|
||||||
r->x += wdg_scheme_ptr_->item_offset + (enable_crook_ ? wdg_scheme_ptr_->crook_size : 0);
|
r->x += scheme_.item_offset + (enable_crook_ ? scheme_.crook_size : 0);
|
||||||
r->y = 2;
|
r->y = 2;
|
||||||
r->width = wdg_scheme_ptr_->icon_size;
|
r->width = scheme_.icon_size;
|
||||||
r->height -= 2;
|
r->height -= 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case component_t::text:
|
case component_t::text:
|
||||||
{
|
{
|
||||||
auto text_pos = wdg_scheme_ptr_->item_offset + (enable_crook_ ? wdg_scheme_ptr_->crook_size : 0) + (enable_icon_ ? wdg_scheme_ptr_->icon_size : 0) + wdg_scheme_ptr_->text_offset;
|
auto text_pos = scheme_.item_offset + (enable_crook_ ? scheme_.crook_size : 0) + (enable_icon_ ? scheme_.icon_size : 0) + scheme_.text_offset;
|
||||||
r->x += text_pos;
|
r->x += text_pos;
|
||||||
r->width -= (text_pos + wdg_scheme_ptr_->text_offset);
|
r->width -= (text_pos + scheme_.text_offset);
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -1426,6 +1437,7 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
const scheme& scheme_;
|
||||||
bool enable_crook_{ false };
|
bool enable_crook_{ false };
|
||||||
bool enable_icon_{ false };
|
bool enable_icon_{ false };
|
||||||
};
|
};
|
||||||
@ -1680,7 +1692,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
impl_->data.trigger_ptr = this;
|
impl_->data.trigger_ptr = this;
|
||||||
impl_->data.renderer = nana::pat::cloneable<renderer_interface>(internal_renderer());
|
impl_->data.renderer = nana::pat::cloneable<renderer_interface>(internal_renderer());
|
||||||
impl_->data.comp_placer = nana::pat::cloneable<compset_placer_interface>(internal_placer());
|
//impl_->data.comp_placer = nana::pat::cloneable<compset_placer_interface>(internal_placer()); //deprecated
|
||||||
|
|
||||||
impl_->adjust.timer.elapse([this]
|
impl_->adjust.timer.elapse([this]
|
||||||
{
|
{
|
||||||
@ -1946,13 +1958,16 @@ namespace nana
|
|||||||
widget.bgcolor(colors::white);
|
widget.bgcolor(colors::white);
|
||||||
impl_->data.widget_ptr = static_cast<::nana::treebox*>(&widget);
|
impl_->data.widget_ptr = static_cast<::nana::treebox*>(&widget);
|
||||||
impl_->data.scheme_ptr = static_cast<::nana::treebox::scheme_type*>(API::dev::get_scheme(widget));
|
impl_->data.scheme_ptr = static_cast<::nana::treebox::scheme_type*>(API::dev::get_scheme(widget));
|
||||||
impl_->data.comp_placer->init_scheme(impl_->data.scheme_ptr);
|
//impl_->data.comp_placer->init_scheme(impl_->data.scheme_ptr); //deprecated
|
||||||
|
impl_->data.comp_placer = nana::pat::cloneable<compset_placer_interface>(internal_placer{ *impl_->data.scheme_ptr });
|
||||||
|
|
||||||
widget.caption("nana treebox");
|
widget.caption("nana treebox");
|
||||||
}
|
}
|
||||||
|
|
||||||
void trigger::detached()
|
void trigger::detached()
|
||||||
{
|
{
|
||||||
|
//Reset the comp_placer, because after deteching, the scheme refered by comp_placer will be released
|
||||||
|
impl_->data.comp_placer.reset();
|
||||||
impl_->data.graph = nullptr;
|
impl_->data.graph = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user