first "working" version of place::error - compiles and run when Ok

tested with some errors as espected
This commit is contained in:
qPCR4vir 2019-05-03 14:52:28 +02:00
parent 003ffee01a
commit 74b486e267
2 changed files with 359 additions and 328 deletions

View File

@ -110,19 +110,7 @@ namespace nana
error( const std::string& what, error( const std::string& what,
const place& plc, const place& plc,
std::string field = "unknown", std::string field = "unknown",
std::string::size_type pos = std::string::npos) std::string::size_type pos = std::string::npos);
: std::invalid_argument{ "Place error " + what
+ " from widget " + API::window_caption(plc.window_handle()).substr(0,80)
+ " in fleld " + field
+ ( pos == std::string::npos ? "" : "at 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) },
field { field },
div_text { plc.div() },
pos { pos }
{}
std::string base_what; std::string base_what;
std::string owner_caption; ///< truncate caption (title) of the "placed" widget std::string owner_caption; ///< truncate caption (title) of the "placed" widget
std::string div_text; ///< involved div_text std::string div_text; ///< involved div_text

View File

@ -61,9 +61,11 @@ namespace nana
const tokenizer& tok) const tokenizer& tok)
: std::invalid_argument{ what + " from tokenizer " }, : std::invalid_argument{ what + " from tokenizer " },
pos{static_cast<std::string::size_type>(tok.sp_ - tok.divstr_)} pos{tok.pos()},
div_str(tok.divstr_)
{} {}
std::string::size_type pos; std::string::size_type pos;
std::string div_str;
}; };
enum class token enum class token
@ -105,9 +107,9 @@ namespace nana
return parameters_; 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() token read()
@ -227,7 +229,7 @@ namespace nana
return token::number; return token::number;
} }
else else
throw("invalid character '" + std::string(1, *sp_) + "'", *this); throw error("invalid character '" + std::string(1, *sp_) + "'", *this);
break; break;
default: default:
if ('0' <= *sp_ && *sp_ <= '9') if ('0' <= *sp_ && *sp_ <= '9')
@ -349,7 +351,7 @@ namespace nana
return token::identifier; return token::identifier;
} }
throw("invalid character '" + std::string(1, *sp_) + "'", *this); throw error("invalid character '" + std::string(1, *sp_) + "'", *this);
return token::error; //Useless, just for syntax correction. return token::error; //Useless, just for syntax correction.
} }
private: private:
@ -610,12 +612,15 @@ namespace nana
struct error : std::invalid_argument struct error : std::invalid_argument
{ {
error(std::string what, error(std::string what,
const implement& impl) std::string field = "unknown",
std::string::size_type pos = std::string::npos)
: std::invalid_argument{ what + " from implementation " }/*, : std::invalid_argument{ what + " from place implementation " },
pos{ static_cast<std::string::size_type>(tok.sp_ - tok.divstr_) }*/ pos{ pos },
field { field.empty() ? "unnamed" : field }
{} {}
std::string::size_type pos; std::string::size_type pos;
std::string field;
}; };
class field_gather; class field_gather;
class field_dock; class field_dock;
@ -2007,11 +2012,11 @@ namespace nana
return; return;
auto fieldstr = div.substr(bound.first, bound.second - bound.first); 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) }; std::string::size_type tag_pos{ left ? div.find('<', bound.second + 2) : div.rfind('>', bound.first - 2) };
if (div.npos == tag_pos) if (div.npos == tag_pos)
throw place::error("please report an issue: unable to update division " + div, impl_-> ); 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); auto other_bound = get_field_boundary(div, tag_pos);
@ -2727,7 +2732,7 @@ namespace nana
return static_cast<int>(arg.real()); return static_cast<int>(arg.real());
const char* pos_strs[] = { "1st", "2nd", "3rd", "4th" }; 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. //implicitly_started indicates whether the field in div-text starts without < mark.
@ -2755,13 +2760,14 @@ namespace nana
bool invisible = false; bool invisible = false;
token tk = token::eof; token tk = token::eof;
try {
for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read()) for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
{ {
switch (tk) switch (tk)
{ {
case token::dock: case token::dock:
if (token::eof != div_type && token::dock != div_type) 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; div_type = token::dock;
break; break;
@ -2830,7 +2836,7 @@ namespace nana
case token::collapse: case token::collapse:
{ {
if (tknizer.parameters().size() != 4) 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{ ::nana::rectangle col{
get_parameter(tknizer, 0), get_parameter(tknizer, 0),
@ -2845,7 +2851,7 @@ namespace nana
{ {
//Overwrite if a exist_col in collapses has same position as the col. //Overwrite if a exist_col in collapses has same position as the col.
bool use_col = true; 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) if (exist_col.x == col.x && exist_col.y == col.y)
{ {
@ -2870,7 +2876,7 @@ namespace nana
switch (tk) switch (tk)
{ {
case token::weight: weight = n; weight_type = token::weight; break; // we could detect errors here (redefinitions and duplicates) 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::height: weight = n; weight_type = token::height; break;
case token::min_px: min_px = n; break; case token::min_px: min_px = n; break;
case token::max_px: max_px = n; break; case token::max_px: max_px = n; break;
@ -2926,7 +2932,7 @@ namespace nana
} }
if (implicitly_started && (tk == token::div_end)) 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; field_gather * attached_field = nullptr;
@ -2941,7 +2947,7 @@ namespace nana
{ {
//The fields are allowed to have a same name. E.g. //The fields are allowed to have a same name. E.g.
//place.div("A <B><C>"); //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; bool allow_same_name = false;
if (!ignore_duplicate.empty()) if (!ignore_duplicate.empty())
@ -2960,7 +2966,7 @@ namespace nana
} }
if (!allow_same_name) if (!allow_same_name)
throw std::runtime_error("place, the name '" + name + "' is redefined."); throw std::invalid_argument("redefined field name");
} }
} }
@ -2969,13 +2975,13 @@ namespace nana
{ {
case token::eof: // "horizontal" div case token::eof: // "horizontal" div
case token::vert: // "vertical" div case token::vert: // "vertical" div
if(token::eof == div_type) if (token::eof == div_type)
unmatch = token::height; unmatch = token::height;
for (auto& ch : children) for (auto& ch : children)
if (ch->weigth_type == unmatch) if (ch->weigth_type == unmatch)
throw std::invalid_argument("nana.place: unmatch vertical-height/horizontal-width between division '" throw std::invalid_argument("unmatch vertical-height/horizontal-width between division '"
+name+"' and children division '" + ch->name); + name + "' and children division '" + ch->name);
div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange))); div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange)));
break; break;
@ -3006,7 +3012,7 @@ namespace nana
div.reset(new div_switchable(std::move(name), this)); div.reset(new div_switchable(std::move(name), this));
break; break;
default: default:
throw std::invalid_argument("nana.place: invalid division type."); throw std::invalid_argument("invalid division type.");
} }
div->weigth_type = weight_type; div->weigth_type = weight_type;
@ -3072,7 +3078,7 @@ namespace nana
{ {
//adjust these children for dock division //adjust these children for dock division
std::vector<std::unique_ptr<division>> adjusted_children; 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); auto dockpn = new div_dockpane(std::move(child->name), this, child->dir);
dockpn->div_owner = child->div_owner; dockpn->div_owner = child->div_owner;
@ -3080,7 +3086,7 @@ namespace nana
adjusted_children.emplace_back(std::unique_ptr<division>{ dockpn }); 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) for (int i = static_cast<int>(adjusted_children.size()) - 1; i >= 0; --i)
{ {
adjusted_children[i]->div_next = next; adjusted_children[i]->div_next = next;
@ -3099,7 +3105,25 @@ namespace nana
div->visible = !(undisplayed || invisible); div->visible = !(undisplayed || invisible);
div->fit = fit; div->fit = fit;
div->fit_parameters = std::move(fit_parameters); div->fit_parameters = std::move(fit_parameters);
}
catch (place::error& e) { throw; }
catch ( error& e) { 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; return div;
} }
@ -3264,17 +3288,21 @@ namespace nana
} }
void place::div(std::string div_text) void place::div(std::string div_text)
{
try
{ {
place_parts::tokenizer tknizer(div_text.c_str()); place_parts::tokenizer tknizer(div_text.c_str());
impl_->disconnect(); impl_->disconnect();
auto div = impl_->scan_div(tknizer, true); auto div = impl_->scan_div(tknizer, true);
try
{
impl_->connect(div.get()); //throws if there is a redefined name of field. impl_->connect(div.get()); //throws if there is a redefined name of field.
impl_->root_division.reset(); //clear attachments div-fields impl_->root_division.reset(); //clear attachments div-fields
impl_->root_division.swap(div); impl_->root_division.swap(div);
impl_->div_text.swap(div_text); impl_->div_text.swap(div_text);
} }
catch (place::implement::error & e)
{
throw place::error("failed to set div('"+div_text+"'): " + e.what(), *this, e.field, e.pos);
}
catch (...) // tokenizer error catch (...) // tokenizer error
{ {
//redefined a name of field //redefined a name of field
@ -3295,19 +3323,15 @@ namespace nana
void place::modify(const char* name, const char* div_text) void place::modify(const char* name, const char* div_text)
{ {
if (nullptr == div_text) if (nullptr == div_text)
throw error("nana::place.modify(): invalid div-text (nullptr)", *this); throw error("modify(): invalid div-text (=nullptr)", *this);
if (! valid_field_name(name) ) if (! valid_field_name(name) )
throw badname("nana::place.modify()", *this, name); throw badname("modify()", *this, name);
auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name); auto div_ptr = impl_->search_div_name(impl_->root_division.get(), name);
if (!div_ptr) if (!div_ptr)
{ throw error("modify(): field was not found", *this, name);
std::string what = "nana::place.modify(): field '";
what += name;
what += "' was not found.";
throw error(what, *this, name);
}
std::unique_ptr<implement::division>* replaced = nullptr; std::unique_ptr<implement::division>* replaced = nullptr;
@ -3361,17 +3385,22 @@ namespace nana
} }
} }
} }
catch (...) /// todo throw error !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! catch (std::exception&e)
{ {
replaced->swap(impl_->tmp_replaced); replaced->swap(impl_->tmp_replaced);
throw; throw error( std::string("modify()")+e.what(), *this, name);
}
catch (...)
{
replaced->swap(impl_->tmp_replaced);
throw error("modify() unknonw error", *this, name);
} }
} }
place::field_reference place::field(const char* name) place::field_reference place::field(const char* name)
{ {
if (!valid_field_name(name)) if (!valid_field_name(name))
throw badname("nana::place.field()", *this, name); throw badname("field()", *this, name);
//get the field with the 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. //then create one.
@ -3387,8 +3416,7 @@ namespace nana
if (div) if (div)
{ {
if (div->field && (div->field != p)) if (div->field && (div->field != p))
throw error(std::string("nana::place.field(): unexpected error, the division attaches an unexpected field: ") + name, throw error("field(): the division attaches an unexpected field", *this, name);
*this, name);
div->field = p; div->field = p;
p->attached = div; p->attached = div;
@ -3466,7 +3494,7 @@ namespace nana
void place::field_visible(const char* name, bool vsb) void place::field_visible(const char* name, bool vsb)
{ {
if (!valid_field_name(name)) if (!valid_field_name(name))
throw badname("set nana::place.field_visible()", *this, name); throw badname("field_visible()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name); auto div = impl_->search_div_name(impl_->root_division.get(), name);
if (div) if (div)
@ -3479,7 +3507,7 @@ namespace nana
bool place::field_visible(const char* name) const bool place::field_visible(const char* name) const
{ {
if (!valid_field_name(name)) if (!valid_field_name(name))
throw badname("get nana::place.field_visible()", *this, name); throw badname("field_visible()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name); auto div = impl_->search_div_name(impl_->root_division.get(), name);
return (div && div->visible); return (div && div->visible);
@ -3488,7 +3516,7 @@ namespace nana
void place::field_display(const char* name, bool dsp) void place::field_display(const char* name, bool dsp)
{ {
if (!valid_field_name(name)) if (!valid_field_name(name))
throw badname("set nana::place.field_display()", *this, name); throw badname("field_display()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name); auto div = impl_->search_div_name(impl_->root_division.get(), name);
if (div) if (div)
@ -3502,7 +3530,7 @@ namespace nana
bool place::field_display(const char* name) const bool place::field_display(const char* name) const
{ {
if (!valid_field_name(name)) if (!valid_field_name(name))
throw badname("get nana::place.field_display()", *this, name); throw badname("field_display()", *this, name);
auto div = impl_->search_div_name(impl_->root_division.get(), name); auto div = impl_->search_div_name(impl_->root_division.get(), name);
return (div && div->display); return (div && div->display);
@ -3540,7 +3568,7 @@ namespace nana
place& place::dock(const std::string& name, std::string factory_name, std::function<std::unique_ptr<widget>(window)> factory) place& place::dock(const std::string& name, std::string factory_name, std::function<std::unique_ptr<widget>(window)> factory)
{ {
if (!valid_field_name(name.data())) if (!valid_field_name(name.data()))
throw badname("get nana::place.field_display()", *this, name.data()); throw badname("dock()", *this, name.data());
auto & dock_ptr = impl_->docks[name]; auto & dock_ptr = impl_->docks[name];
if (!dock_ptr) if (!dock_ptr)
@ -3550,7 +3578,7 @@ namespace nana
if (!factory_name.empty()) if (!factory_name.empty())
{ {
if (impl_->dock_factoris.find(factory_name) != impl_->dock_factoris.end()) 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; impl_->dock_factoris[factory_name] = dock_ptr;
dock_ptr->factories[factory_name] = std::move(factory); dock_ptr->factories[factory_name] = std::move(factory);
@ -3586,7 +3614,7 @@ namespace nana
{ {
auto i = impl_->dock_factoris.find(factory); auto i = impl_->dock_factoris.find(factory);
if (i == impl_->dock_factoris.end()) 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; auto dock_ptr = i->second;
if (dock_ptr->attached) if (dock_ptr->attached)
@ -3607,9 +3635,24 @@ namespace nana
return nullptr; return nullptr;
} }
//end class place
//class place::error place::error::error(const std::string& what,
const place& plc,
std::string field,
std::string::size_type pos)
: std::invalid_argument{ "nana::place error " + what
+ " from widget '" + API::window_caption(plc.window_handle()).substr(0,80)
+ "' in fleld '" + field
+ (pos == std::string::npos ? "' " : "' at 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) },
field{ field },
div_text{ plc.div() },
pos{ pos }
{}
//end class place
}//end namespace nana }//end namespace nana