Merge branch 'qPCR4vir-test_error' into develop

This commit is contained in:
Jinhao
2019-05-07 00:25:46 +08:00
16 changed files with 547 additions and 409 deletions

View File

@@ -46,8 +46,6 @@ before_install:
- cd ..
- git clone --depth=1 --branch=hotfix https://github.com/qPCR4vir/nana-demo.git nana-demo
- export PATH="$HOME/bin:$PATH"
#- mkdir ~/bin #it seemd that a bin already exists from 20170901
- wget --no-check-certificate --no-clobber -O /tmp/tools/cmake https://cmake.org/files/v3.12/cmake-3.12.0-rc3-Linux-x86_64.sh || true
- chmod -R +x /tmp/tools
@@ -65,7 +63,7 @@ before_script :
- cd demo-build
script:
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=ON -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON
- cmake -G"Unix Makefiles" ../nana-demo -DCMAKE_INSTALL_PREFIX=.. -DNANA_CMAKE_ENABLE_JPEG=ON -DNANA_CMAKE_FIND_BOOST_FILESYSTEM=OFF -DNANA_CMAKE_AUTOMATIC_GUI_TESTING=ON
- make install
# todo: separate resources from sources (a directory for images)
- ls

View File

@@ -17,6 +17,9 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") # AN
target_compile_options(nana PRIVATE -Wall
PUBLIC -g )
# todo: set in target property of nana
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -DNDEBUG")
set(THREADS_PREFER_PTHREAD_FLAG ON) # todo - test this
find_package(Threads REQUIRED)
target_link_libraries(nana PRIVATE Threads::Threads)

View File

@@ -30,6 +30,8 @@ if (NANA_CMAKE_VERBOSE_PREPROCESSOR)
cmake_print_variables(CMAKE_BUILD_TYPE)
cmake_print_variables(CMAKE_CONFIGURATION_TYPES)
cmake_print_variables(CMAKE_CXX_FLAGS_RELEASE)
message ( "CMAKE_CXX_COMPILER_ID = " ${CMAKE_CXX_COMPILER_ID})
message ( "COMPILER_IS_CLANG = " ${COMPILER_IS_CLANG})
message ( "CMAKE_COMPILER_IS_GNUCXX = " ${CMAKE_COMPILER_IS_GNUCXX})

View File

@@ -102,6 +102,7 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -116,6 +117,7 @@
<PreprocessorDefinitions>_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -132,6 +134,7 @@
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -150,6 +153,7 @@
<PreprocessorDefinitions>NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -252,6 +256,7 @@
<ClInclude Include="..\..\include\nana\gui.hpp" />
<ClInclude Include="..\..\include\nana\gui\animation.hpp" />
<ClInclude Include="..\..\include\nana\gui\basis.hpp" />
<ClInclude Include="..\..\include\nana\gui\dragdrop.hpp" />
<ClInclude Include="..\..\include\nana\gui\dragger.hpp" />
<ClInclude Include="..\..\include\nana\gui\drawing.hpp" />
<ClInclude Include="..\..\include\nana\gui\effects.hpp" />

View File

@@ -474,6 +474,9 @@
<ClInclude Include="..\..\include\nana\verbose_preprocessor.hpp">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\..\include\nana\gui\dragdrop.hpp">
<Filter>Include\gui</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\include\nana\pop_ignore_diagnostic">

View File

@@ -40,7 +40,16 @@ namespace nana
simple_dragdrop(simple_dragdrop&&) = delete;
simple_dragdrop& operator=(simple_dragdrop&&) = delete;
public:
simple_dragdrop(window source);
explicit simple_dragdrop(window source);
simple_dragdrop(window drag_origin,
std::function<bool()> when,
window drop_target,
std::function<void()> how)
: simple_dragdrop{drag_origin}
{
condition(when);
make_drop(drop_target, how);
}
~simple_dragdrop();
/// Condition checker

View File

@@ -1,16 +1,16 @@
/*
/**
* An Implementation of Place for Layout
* 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.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/place.cpp
* @file nana/gui/place.cpp
*
* @contributions:
* min/max and splitter bar initial weight by Ariel Vina-Rodriguez.
* @contributions
* error, width/height, min/max and splitter bar initial weight by Ariel Vina-Rodriguez.
*/
#ifndef NANA_GUI_PLACE_HPP
@@ -79,6 +79,7 @@ namespace nana
{
struct implement;
class field_interface
{
field_interface(const field_interface&) = delete;
@@ -103,6 +104,19 @@ namespace nana
virtual void _m_add_agent(const detail::place_agent&) = 0;
};
public:
class error :public std::invalid_argument
{
public:
error( const std::string& what,
const place& plc,
std::string field = "unknown",
std::string::size_type pos = std::string::npos);
std::string base_what;
std::string owner_caption; ///< truncate caption (title) of the "placed" widget
std::string div_text; ///< involved div_text
std::string field; ///< posible field where the error ocurred.
std::string::size_type pos; ///< posible position in the div_text where the error ocurred. npos if unknown
};
/// reference to a field manipulator which refers to a field object created by place
using field_reference = field_interface &;
@@ -119,9 +133,13 @@ namespace nana
void splitter_renderer(std::function<void(window, paint::graphics&, mouse_action)> fn);
void div(std::string div_text); ///< Divides the attached widget into fields.
void div(std::string div_text); ///< Divides the attached widget into fields. May throw placa::error
const std::string& div() const noexcept; ///< Returns div-text that depends on fields status.
void modify(const char* field_name, const char* div_text); ///< Modifies a specified field.
static bool valid_field_name(const char* name) ///< must begin with _a-zA-Z
{
return name && (*name == '_' || (('a' <= *name && *name <= 'z') || ('A' <= *name && *name <= 'Z')));
}
void modify(const char* field_name, const char* div_text); ///< Modifies a specified field. May throw placa::error
field_reference field(const char* name);///< Returns a field with the specified name.
@@ -152,6 +170,8 @@ namespace nana
private:
implement * impl_;
};
}//end namespace nana
#include <nana/pop_ignore_diagnostic>

View File

@@ -35,7 +35,10 @@ namespace nana{
}//end namespace drawerbase
class group
: public widget_object<category::widget_tag, drawerbase::panel::drawer, general_events, drawerbase::group::scheme>
: public widget_object<category::widget_tag,
drawerbase::panel::drawer,
general_events,
drawerbase::group::scheme>
{
struct implement;
public:
@@ -56,7 +59,6 @@ namespace nana{
group(window parent, const rectangle& = {}, bool visible = true);
/// The construction that creates the widget and set the title or caption
group(window parent, ///< a handle to the parent
::std::string title, ///< caption of the group
bool formatted = false, ///< Enable/disable the formatted text for the title

View File

@@ -1292,7 +1292,10 @@ the nana::detail::basic_window member pointer scheme
\example listbox_Resolver.cpp
*/
class listbox
: public widget_object<category::widget_tag, drawerbase::listbox::trigger, drawerbase::listbox::listbox_events, drawerbase::listbox::scheme>,
: public widget_object<category::widget_tag,
drawerbase::listbox::trigger,
drawerbase::listbox::listbox_events,
drawerbase::listbox::scheme>,
public concepts::any_objective<drawerbase::listbox::size_type, 2>
{
public:

View File

@@ -77,7 +77,10 @@ namespace nana
/// Spinbox Widget
class spinbox
: public widget_object <category::widget_tag, drawerbase::spinbox::drawer, drawerbase::spinbox::spinbox_events, ::nana::widgets::skeletons::text_editor_scheme>
: public widget_object <category::widget_tag,
drawerbase::spinbox::drawer,
drawerbase::spinbox::spinbox_events,
::nana::widgets::skeletons::text_editor_scheme>
{
public:
/// Constructs a spinbox.

View File

@@ -350,7 +350,9 @@ namespace nana
/// \brief Displays a hierarchical list of items, such as the files and directories on a disk.
/// See also in [documentation](http://nanapro.org/en-us/documentation/widgets/treebox.htm)
class treebox
:public widget_object <category::widget_tag, drawerbase::treebox::trigger, drawerbase::treebox::treebox_events, drawerbase::treebox::scheme>
:public widget_object <category::widget_tag,
drawerbase::treebox::trigger,
drawerbase::treebox::treebox_events, drawerbase::treebox::scheme>
{
public:
/// A type refers to the item and is also used to iterate through the nodes.

View File

@@ -1,14 +1,14 @@
/*
/**
* An Implementation of Place for Layout
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/place.cpp
* @contributors: Ariel Vina-Rodriguez
* @file nana/gui/place.cpp
* @contributors Ariel Vina-Rodriguez
* dankan1890(PR#156)
*/
@@ -36,16 +36,16 @@
namespace nana
{
namespace place_parts
struct badname: place::error
{
//check the name
void check_field_name(const char* name)
{
if (*name && (*name != '_' && !(('a' <= *name && *name <= 'z') || ('A' <= *name && *name <= 'Z'))))
throw std::invalid_argument("nana.place: bad field name");
}
}//end namespace place_parts
explicit badname( ::std::string what,
const place& plc,
const char* name = "unknown",
std::string::size_type pos = std::string::npos)
:place::error(what + ": bad field name '" + (name ? name : "nullptr") + "'.",
plc, (name ? name : "nullptr"), pos)
{}
};
typedef place_parts::number_t number_t;
typedef place_parts::repeated_array repeated_array;
@@ -54,6 +54,20 @@ namespace nana
class tokenizer
{
public:
/// \todo add member full_what and overrider what() in internal exeptions
struct error : std::invalid_argument
{
error(std::string what,
const tokenizer& tok)
: std::invalid_argument{ what + " from tokenizer " },
pos{tok.pos()},
div_str(tok.divstr_)
{}
std::string::size_type pos;
std::string div_str;
};
enum class token
{
div_start, div_end, splitter,
@@ -73,7 +87,7 @@ namespace nana
return idstr_;
}
const number_t& number() const
const number_t& number() const noexcept
{
return number_;
}
@@ -93,9 +107,9 @@ namespace nana
return parameters_;
}
std::size_t pos() const noexcept
std::string::size_type pos() const noexcept
{
return (sp_ - divstr_);
return static_cast<std::string::size_type>(sp_ - divstr_);
}
token read()
@@ -137,9 +151,13 @@ namespace nana
while (true)
{
sp_ = _m_eat_whitespace(sp_);
auto tk = read();
if (token::number != tk && token::variable != tk && token::repeated != tk)
_m_throw_error("invalid array element");
auto tk = read(); // try ??
if ( token::number != tk
&& token::variable != tk
&& token::repeated != tk)
throw error("invalid array element. Expected a number, variable or repaet", *this);
if (!repeated)
{
@@ -165,7 +183,7 @@ namespace nana
return (repeated ? token::reparray : token::array);
if (ch != ',')
_m_throw_error("invalid array");
throw error("invalid array", *this);
}
}
break;
@@ -183,7 +201,7 @@ namespace nana
if (token::number == read())
parameters_.push_back(number_);
else
_m_throw_error("invalid parameter.");
throw error("invalid parameter. Expected a number", *this);
sp_ = _m_eat_whitespace(sp_);
char ch = *sp_++;
@@ -192,7 +210,7 @@ namespace nana
return token::parameters;
if (ch != ',')
_m_throw_error("invalid parameter.");
throw error("invalid parameter. Expected a ','", *this);
}
break;
case '.': case '-':
@@ -211,7 +229,7 @@ namespace nana
return token::number;
}
else
_m_throw_error("invalid character '" + std::string(1, *sp_) + "'");
throw error("invalid character '" + std::string(1, *sp_) + "'", *this);
break;
default:
if ('0' <= *sp_ && *sp_ <= '9')
@@ -269,14 +287,14 @@ namespace nana
{
auto idstr = idstr_;
if (token::equal != read())
_m_throw_error("an equal sign is required after '" + idstr + "'");
throw error("an equal sign is required after '" + idstr + "'", *this);
return ('g' == idstr[0] ? token::grid : token::margin);
}
else if ("collapse" == idstr_)
{
if (token::parameters != read())
_m_throw_error("a parameter list is required after 'collapse'");
throw error("a parameter list is required after 'collapse'", *this);
return token::collapse;
}
else if (!idstr_.empty())
@@ -333,22 +351,14 @@ namespace nana
return token::identifier;
}
std::string err = "an invalid character '";
err += *sp_;
err += "'";
_m_throw_error(err);
throw error("invalid character '" + std::string(1, *sp_) + "'", *this);
return token::error; //Useless, just for syntax correction.
}
private:
void _m_throw_error(const std::string& err)
{
throw std::runtime_error("nana::place: " + err + " at " + std::to_string(static_cast<unsigned>(sp_ - divstr_)));
}
void _m_attr_number_value()
{
if (token::equal != read())
_m_throw_error("an equal sign is required after '" + idstr_ + "'");
throw error("an equal sign is required after '" + idstr_ + "'", *this);
auto p = _m_eat_whitespace(sp_);
@@ -358,7 +368,7 @@ namespace nana
auto len = _m_number(p, neg_ptr != p);
if (0 == len)
_m_throw_error("the '" + idstr_ + "' requires a number(integer or real or percent)");
throw error("the '" + idstr_ + "' requires a number (integer, real or percent)", *this);
sp_ += len + (p - sp_);
}
@@ -367,7 +377,7 @@ namespace nana
{
auto idstr = idstr_;
if (token::equal != read())
_m_throw_error("an equal sign is required after '" + idstr + "'");
throw error("an equal sign is required after '" + idstr + "'", *this);
sp_ = _m_eat_whitespace(sp_);
@@ -385,19 +395,21 @@ namespace nana
case token::reparray:
break;
default:
_m_throw_error("a (repeated) array is required after '" + idstr + "'");
throw error("a (repeated) array is required after '" + idstr + "'", *this);
}
}
static const char* _m_eat_whitespace(const char* sp) noexcept
{
while (*sp && !std::isgraph(*sp))
while (*sp && !std::isgraph(int(*sp)))
++sp;
return sp;
}
std::size_t _m_number(const char* sp, bool negative) noexcept
{
/// \todo use std::from_char<int>() etc.
const char* allstart = sp;
sp = _m_eat_whitespace(sp);
@@ -462,8 +474,8 @@ namespace nana
return 0;
}
private:
const char* divstr_;
const char* sp_;
const char* divstr_{};
const char* sp_{};
std::string idstr_;
number_t number_;
std::vector<number_t> array_;
@@ -482,7 +494,6 @@ namespace nana
return (vert ? pos.y : pos.x);
}
static bool is_idchar(int ch) noexcept
{
return ('_' == ch || std::isalnum(ch));
@@ -490,6 +501,7 @@ namespace nana
static std::size_t find_idstr(const std::string& text, const char* idstr, std::size_t off = 0)
{
if (!idstr) return text.npos; /// ??
const auto len = std::strlen(idstr);
size_t pos;
@@ -596,6 +608,20 @@ namespace nana
//struct implement
struct place::implement
{
/// usefull ??
struct error : std::invalid_argument
{
error(std::string what,
std::string field = "unknown",
std::string::size_type pos = std::string::npos)
: std::invalid_argument{ what + " from place implementation " },
pos{ pos },
field { field.empty() ? "unnamed" : field }
{}
std::string::size_type pos;
std::string field;
};
class field_gather;
class field_dock;
@@ -643,6 +669,8 @@ namespace nana
: public place::field_interface
{
public:
/// \todo introduce a place::implement::field_gather::error ??
struct element_t
{
window handle;
@@ -692,13 +720,13 @@ namespace nana
return nullptr;
}
private:
void _m_insert_widget(window wd, bool to_fasten)
void _m_insert_widget(window wd, bool to_fasten) /// \todo better errors caption of failed windows, field
{
if (API::empty_window(wd))
throw std::invalid_argument("Place: An invalid window handle.");
throw place::error("Failed to insert an invalid window handle.", *place_ptr_);
if (API::get_parent_window(wd) != place_ptr_->window_handle())
throw std::invalid_argument("Place: the window is not a child of place bind window");
throw place::error("Failed to insert a window which is not a child of the place-binded window", *place_ptr_);
//Listen to destroy of a window
//It will delete the element and recollocate when the window destroyed.
@@ -1984,11 +2012,11 @@ namespace nana
return;
auto fieldstr = div.substr(bound.first, bound.second - bound.first);
_m_remove_attr(fieldstr, "weight");
_m_remove_attr(fieldstr, "weight"); /// \todo and higth, width ?
std::string::size_type tag_pos{ left ? div.find('<', bound.second + 2) : div.rfind('>', bound.first - 2) };
if (div.npos == tag_pos)
throw std::invalid_argument("please report an issue if it throws");
throw place::implement::error("please report an issue: the splitter was unable to update division " + div, name);
auto other_bound = get_field_boundary(div, tag_pos);
@@ -2704,7 +2732,7 @@ namespace nana
return static_cast<int>(arg.real());
const char* pos_strs[] = { "1st", "2nd", "3rd", "4th" };
throw std::invalid_argument("nana.place: the type of the " + std::string{pos_strs[pos]} +"th parameter for collapse should be integer.");
throw place_parts::tokenizer::error("the type of the " + std::string{pos_strs[pos]} +" parameter for collapse should be integer.", tknizer);
}
//implicitly_started indicates whether the field in div-text starts without < mark.
@@ -2732,13 +2760,14 @@ namespace nana
bool invisible = false;
token tk = token::eof;
try {
for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
{
switch (tk)
{
case token::dock:
if (token::eof != div_type && token::dock != div_type)
throw std::invalid_argument("nana.place: conflict of div type at " + std::to_string(tknizer.pos()));
throw std::invalid_argument("conflict of div type -expected dock type-");
div_type = token::dock;
break;
@@ -2807,7 +2836,7 @@ namespace nana
case token::collapse:
{
if (tknizer.parameters().size() != 4)
throw std::invalid_argument("nana.place: collapse requires 4 parameters.");
throw std::invalid_argument("collapse requires 4 parameters");
::nana::rectangle col{
get_parameter(tknizer, 0),
@@ -2822,7 +2851,7 @@ namespace nana
{
//Overwrite if a exist_col in collapses has same position as the col.
bool use_col = true;
for (auto & exist_col : collapses)
for (auto& exist_col : collapses)
{
if (exist_col.x == col.x && exist_col.y == col.y)
{
@@ -2847,7 +2876,7 @@ namespace nana
switch (tk)
{
case token::weight: weight = n; weight_type = token::weight; break; // we could detect errors here (redefinitions and duplicates)
case token::width : weight = n; weight_type = token::width ; break;
case token::width: weight = n; weight_type = token::width; break;
case token::height: weight = n; weight_type = token::height; break;
case token::min_px: min_px = n; break;
case token::max_px: max_px = n; break;
@@ -2903,7 +2932,7 @@ namespace nana
}
if (implicitly_started && (tk == token::div_end))
throw std::invalid_argument("nana.place: the div-text ends prematurely at " + std::to_string(tknizer.pos()));
throw std::invalid_argument("the div-text ends prematurely");
field_gather * attached_field = nullptr;
@@ -2918,7 +2947,7 @@ namespace nana
{
//The fields are allowed to have a same name. E.g.
//place.div("A <B><C>");
//place.modify("A", "<B>"); Here the same name B must be allowed, otherwise it throws runtime error.
//place.modify("A", "<B>"); Here the same name B must be allowed, otherwise it throws std::invalid_argument.
bool allow_same_name = false;
if (!ignore_duplicate.empty())
@@ -2937,7 +2966,7 @@ namespace nana
}
if (!allow_same_name)
throw std::runtime_error("place, the name '" + name + "' is redefined.");
throw std::invalid_argument("redefined field name");
}
}
@@ -2946,13 +2975,13 @@ namespace nana
{
case token::eof: // "horizontal" div
case token::vert: // "vertical" div
if(token::eof == div_type)
if (token::eof == div_type)
unmatch = token::height;
for (auto& ch : children)
if (ch->weigth_type == unmatch)
throw std::invalid_argument("nana.place: unmatch vertical-height/horizontal-width between division '"
+name+"' and children division '" + ch->name);
throw std::invalid_argument("unmatch vertical-height/horizontal-width between division '"
+ name + "' and children division '" + ch->name);
div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange)));
break;
@@ -2983,7 +3012,7 @@ namespace nana
div.reset(new div_switchable(std::move(name), this));
break;
default:
throw std::invalid_argument("nana.place: invalid division type.");
throw std::invalid_argument("invalid division type.");
}
div->weigth_type = weight_type;
@@ -3049,7 +3078,7 @@ namespace nana
{
//adjust these children for dock division
std::vector<std::unique_ptr<division>> adjusted_children;
for (auto & child : children)
for (auto& child : children)
{
auto dockpn = new div_dockpane(std::move(child->name), this, child->dir);
dockpn->div_owner = child->div_owner;
@@ -3057,7 +3086,7 @@ namespace nana
adjusted_children.emplace_back(std::unique_ptr<division>{ dockpn });
}
division * next = nullptr;
division* next = nullptr;
for (int i = static_cast<int>(adjusted_children.size()) - 1; i >= 0; --i)
{
adjusted_children[i]->div_next = next;
@@ -3076,7 +3105,25 @@ namespace nana
div->visible = !(undisplayed || invisible);
div->fit = fit;
div->fit_parameters = std::move(fit_parameters);
}
catch (place::error& ) { throw; }
catch ( error& ) { throw; }
catch (place_parts::tokenizer::error& e)
{
throw error(e.what(), name, e.pos);
}
catch (std::invalid_argument& e)
{
throw error(e.what(), name, tknizer.pos());
}
catch (std::exception& e)
{
throw error(std::string{"unexpected error: "}+e.what(), name, tknizer.pos());
}
catch (...)
{
throw error("unknow error", name, tknizer.pos());
}
return div;
}
@@ -3213,7 +3260,8 @@ namespace nana
void place::bind(window wd)
{
if (impl_->window_handle)
throw std::runtime_error("place.bind: it has already bound to a window.");
throw error(" bind('"+ API::window_caption(wd).substr(0, 80)
+ "'): it was already bound to another window.", *this);
impl_->window_handle = wd;
impl_->event_size_handle = API::events(wd).resized.connect_unignorable([this](const arg_resized& arg)
@@ -3241,21 +3289,37 @@ namespace nana
}
void place::div(std::string div_text)
{
try
{
place_parts::tokenizer tknizer(div_text.c_str());
impl_->disconnect();
auto div = impl_->scan_div(tknizer, true);
try
{
impl_->connect(div.get()); //throws if there is a redefined name of field.
impl_->root_division.reset(); //clear attachments div-fields
impl_->root_division.swap(div);
impl_->div_text.swap(div_text);
}
catch (place::error & ) { throw; }
catch (place::implement::error & e)
{
throw error("failed to set div('" + div_text + "'): " + e.what(), *this, e.field, e.pos);
}
catch (place_parts::tokenizer::error & e)
{
throw error("failed to set div('" + div_text + "'): " + e.what(), *this, "", e.pos);
}
catch (std::invalid_argument & e)
{
throw error("failed to set div('" + div_text + "'): " + e.what(), *this);
}
catch (std::exception & e)
{
throw error("failed to set div('"+div_text+"'): unexpected error: " +e.what(), *this );
}
catch (...)
{
//redefined a name of field
throw;
throw error("failed to set div('" + div_text + "'): unknonw error", *this);
}
}
@@ -3272,23 +3336,15 @@ namespace nana
void place::modify(const char* name, const char* div_text)
{
if (nullptr == div_text)
throw std::invalid_argument("nana.place: invalid div-text");
throw error("modify(): invalid div-text (=nullptr)", *this);
if (nullptr == name) name = "";
//check the name, it throws std::invalid_argument
//if name violate the naming convention.
place_parts::check_field_name(name);
if (! valid_field_name(name) )
throw badname("modify()", *this, name);
auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name);
if (!div_ptr)
{
std::string what = "nana::place: field '";
what += name;
what += "' is not found.";
throw error("modify(): field was not found", *this, name);
throw std::invalid_argument(what);
}
std::unique_ptr<implement::division>* replaced = nullptr;
@@ -3342,23 +3398,44 @@ namespace nana
}
}
}
catch (...)
catch (place::error & )
{
replaced->swap(impl_->tmp_replaced);
throw;
}
catch (place::implement::error & e)
{
replaced->swap(impl_->tmp_replaced);
throw error("failed to modify('"+std::string(name) +", "+ div_text + "'): " + e.what(), *this, e.field, e.pos);
}
catch (place_parts::tokenizer::error & e)
{
replaced->swap(impl_->tmp_replaced);
throw error("failed to modify('" + std::string(name) + ", " + div_text + "'): " + e.what(), *this, "", e.pos);
}
catch (std::invalid_argument & e)
{
replaced->swap(impl_->tmp_replaced);
throw error("failed to modify('" + std::string(name) + ", " + div_text + "'): " + e.what(), *this);
}
catch (std::exception & e)
{
replaced->swap(impl_->tmp_replaced);
throw error("failed to modify('" + std::string(name) + ", " + div_text + "'): unexpected error: " + e.what(), *this);
}
catch (...)
{
replaced->swap(impl_->tmp_replaced);
throw error("failed to modify('" + std::string(name) + ", " + div_text + "'): unknonw error", *this);
}
}
place::field_reference place::field(const char* name)
{
if (nullptr == name)
name = "";
if (!valid_field_name(name))
throw badname("field()", *this, name);
//check the name, it throws std::invalid_argument
//if name violate the naming convention.
place_parts::check_field_name(name);
//get the field with specified name, if no such field with specified name
//get the field with the specified name. If no such field with specified name
//then create one.
auto & p = impl_->fields[name];
if (nullptr == p)
@@ -3367,12 +3444,12 @@ namespace nana
if ((!p->attached) && impl_->root_division)
{
//search the division with the specified name,
//and attached the division to the field
//and attaches the division to the field
auto div = implement::search_div_name(impl_->root_division.get(), name);
if (div)
{
if (div->field && (div->field != p))
throw std::runtime_error("nana.place: unexpected error, the division attaches an unexpected field.");
throw error("field(): the division attaches an unexpected field", *this, name);
div->field = p;
p->attached = div;
@@ -3449,10 +3526,8 @@ namespace nana
void place::field_visible(const char* name, bool vsb)
{
if (!name) name = "";
//May throw std::invalid_argument
place_parts::check_field_name(name);
if (!valid_field_name(name))
throw badname("field_visible()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name);
if (div)
@@ -3464,10 +3539,8 @@ namespace nana
bool place::field_visible(const char* name) const
{
if (!name) name = "";
//May throw std::invalid_argument
place_parts::check_field_name(name);
if (!valid_field_name(name))
throw badname("field_visible()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name);
return (div && div->visible);
@@ -3475,10 +3548,8 @@ namespace nana
void place::field_display(const char* name, bool dsp)
{
if (!name) name = "";
//May throw std::invalid_argument
place_parts::check_field_name(name);
if (!valid_field_name(name))
throw badname("field_display()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name);
if (div)
@@ -3491,10 +3562,8 @@ namespace nana
bool place::field_display(const char* name) const
{
if (!name) name = "";
//May throw std::invalid_argument
place_parts::check_field_name(name);
if (!valid_field_name(name))
throw badname("field_display()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name);
return (div && div->display);
@@ -3531,9 +3600,8 @@ namespace nana
place& place::dock(const std::string& name, std::string factory_name, std::function<std::unique_ptr<widget>(window)> factory)
{
//check the name, it throws std::invalid_argument
//if name violate the naming convention.
place_parts::check_field_name(name.data());
if (!valid_field_name(name.data()))
throw badname("dock()", *this, name.data());
auto & dock_ptr = impl_->docks[name];
if (!dock_ptr)
@@ -3543,7 +3611,7 @@ namespace nana
if (!factory_name.empty())
{
if (impl_->dock_factoris.find(factory_name) != impl_->dock_factoris.end())
throw std::invalid_argument("nana::place - the specified factory name(" + factory_name + ") already exists");
throw error("dock() - the specified factory name(" + factory_name + ") already exists", *this, name);
impl_->dock_factoris[factory_name] = dock_ptr;
dock_ptr->factories[factory_name] = std::move(factory);
@@ -3579,7 +3647,7 @@ namespace nana
{
auto i = impl_->dock_factoris.find(factory);
if (i == impl_->dock_factoris.end())
throw std::invalid_argument("invalid factory name(" + factory + ") of dockpane");
throw std::invalid_argument("nana::place::dock_create - invalid factory name(" + factory + ") of dockpane");
auto dock_ptr = i->second;
if (dock_ptr->attached)
@@ -3600,7 +3668,27 @@ namespace nana
return nullptr;
}
place::error::error(const std::string& what,
const place& plc,
std::string field,
std::string::size_type pos)
: std::invalid_argument{ "from widget '"
+ API::window_caption(plc.window_handle()).substr(0,80)
+ "'; nana::place error "
+ what
+ "' in field '" + field
+ (pos == std::string::npos ? "' " : "' at position " + std::to_string(pos))
+ " in div_text:\n" + plc.div() },
base_what{ what },
owner_caption{ API::window_caption(plc.window_handle()).substr(0,80) },
div_text{ plc.div() },
field{ field },
pos{ pos }
{}
//end class place
}//end namespace nana
#include <nana/pop_ignore_diagnostic>

View File

@@ -1,13 +1,13 @@
/*
/**
* Parts of Class Place
* 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.
* (See accompanying file LICENSE_1_0.txt or copy at
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/place_parts.hpp
* @file nana/gui/place_parts.hpp
*/
#ifndef NANA_GUI_PLACE_PARTS_HPP
#define NANA_GUI_PLACE_PARTS_HPP

View File

@@ -1,4 +1,4 @@
/*
/**
* A Categorize Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
@@ -7,7 +7,7 @@
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/widgets/categorize.cpp
* @file nana/gui/widgets/categorize.cpp
*/
#include <nana/gui/wvl.hpp>

View File

@@ -1,19 +1,19 @@
/**
* A group widget implementation
* Nana C++ Library(http://www.nanaro.org)
* Copyright(C) 2015-2018 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2015-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/widgets/group.cpp
* @file nana/gui/widgets/group.cpp
*
* @Author: Stefan Pfeifer(st-321), Ariel Vina-Rodriguez (qPCR4vir)
* @author Stefan Pfeifer(st-321), Ariel Vina-Rodriguez (qPCR4vir)
*
* @brief group is a widget used to visually group and layout other widgets.
*
* @contributor:
* @contributor
* dankan1890(https://github.com/dankan1890)
*/