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

@ -107,22 +107,10 @@ namespace nana
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::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 }
{}
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

View File

@ -61,9 +61,11 @@ namespace nana
const tokenizer& tok)
: 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 div_str;
};
enum class token
@ -105,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()
@ -227,7 +229,7 @@ namespace nana
return token::number;
}
else
throw("invalid character '" + std::string(1, *sp_) + "'", *this);
throw error("invalid character '" + std::string(1, *sp_) + "'", *this);
break;
default:
if ('0' <= *sp_ && *sp_ <= '9')
@ -349,7 +351,7 @@ namespace nana
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.
}
private:
@ -472,7 +474,7 @@ namespace nana
return 0;
}
private:
const char* divstr_{};
const char* divstr_{};
const char* sp_{};
std::string idstr_;
number_t number_;
@ -609,13 +611,16 @@ namespace nana
/// usefull ??
struct error : std::invalid_argument
{
error(std::string what,
const implement& impl)
error(std::string what,
std::string field = "unknown",
std::string::size_type pos = std::string::npos)
: std::invalid_argument{ what + " from implementation " }/*,
pos{ static_cast<std::string::size_type>(tok.sp_ - tok.divstr_) }*/
: 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;
@ -2007,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 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);
@ -2727,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.
@ -2755,82 +2760,83 @@ namespace nana
bool invisible = false;
token tk = token::eof;
for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
{
switch (tk)
try {
for (tk = tknizer.read(); (tk != token::eof && tk != token::div_end); tk = tknizer.read())
{
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()));
div_type = token::dock;
break;
case token::fit:
fit = fit_policy::both;
break;
case token::hfit:
case token::vfit:
fit = (token::hfit == tk ? fit_policy::horz : fit_policy::vert);
fit_parameters = tknizer.reparray();
break;
case token::splitter:
//Ignore the splitter when there is not a division.
if (!children.empty() && (division::kind::splitter != children.back()->kind_of_division))
switch (tk)
{
auto splitter = new div_splitter(tknizer.number(), this);
children.back()->div_next = splitter;
case token::dock:
if (token::eof != div_type && token::dock != div_type)
throw std::invalid_argument("conflict of div type -expected dock type-");
//Hides the splitter if its left leaf is undisplayed.
if (!children.back()->display)
splitter->display = false;
div_type = token::dock;
break;
case token::fit:
fit = fit_policy::both;
break;
case token::hfit:
case token::vfit:
fit = (token::hfit == tk ? fit_policy::horz : fit_policy::vert);
fit_parameters = tknizer.reparray();
break;
case token::splitter:
//Ignore the splitter when there is not a division.
if (!children.empty() && (division::kind::splitter != children.back()->kind_of_division))
{
auto splitter = new div_splitter(tknizer.number(), this);
children.back()->div_next = splitter;
children.emplace_back(std::unique_ptr<division>{ splitter });
//Hides the splitter if its left leaf is undisplayed.
if (!children.back()->display)
splitter->display = false;
children.emplace_back(std::unique_ptr<division>{ splitter });
}
break;
case token::div_start:
{
auto div = scan_div(tknizer, false, ignore_duplicate);
if (!children.empty())
{
//Hides the splitter if its right leaf is undisplayed.
if ((children.back()->kind_of_division == division::kind::splitter) && !div->display)
children.back()->display = false;
children.back()->div_next = div.get();
}
children.emplace_back(std::move(div));
}
break;
case token::div_start:
{
auto div = scan_div(tknizer, false, ignore_duplicate);
if (!children.empty())
{
//Hides the splitter if its right leaf is undisplayed.
if ((children.back()->kind_of_division == division::kind::splitter) && !div->display)
children.back()->display = false;
children.back()->div_next = div.get();
}
children.emplace_back(std::move(div));
}
break;
case token::switchable:
div_type = token::switchable;
break;
case token::vert:
div_type = tk;
break;
case token::grid:
div_type = tk;
switch (tknizer.read())
{
case token::number:
array.push_back(tknizer.number());
array.push_back(tknizer.number());
case token::switchable:
div_type = token::switchable;
break;
case token::array:
tknizer.array().swap(array);
case token::vert:
div_type = tk;
break;
case token::reparray:
array.push_back(tknizer.reparray().at(0));
array.push_back(tknizer.reparray().at(1));
case token::grid:
div_type = tk;
switch (tknizer.read())
{
case token::number:
array.push_back(tknizer.number());
array.push_back(tknizer.number());
break;
case token::array:
tknizer.array().swap(array);
break;
case token::reparray:
array.push_back(tknizer.reparray().at(0));
array.push_back(tknizer.reparray().at(1));
break;
default:
break;
}
break;
default:
break;
}
break;
case token::collapse:
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),
@ -2845,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)
{
@ -2859,7 +2865,7 @@ namespace nana
}
}
break;
case token::weight: case token::min_px: case token::max_px: case token::width: case token::height:
case token::weight: case token::min_px: case token::max_px: case token::width: case token::height:
{
auto n = tknizer.number();
//If n is the type of real, convert it to integer.
@ -2870,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;
@ -2878,228 +2884,246 @@ namespace nana
}
}
break;
case token::arrange:
arrange = tknizer.reparray();
break;
case token::gap:
gap = tknizer.reparray();
break;
case token::margin:
margin.clear();
switch (tknizer.read())
{
case token::number:
margin.push(tknizer.number(), true);
case token::arrange:
arrange = tknizer.reparray();
break;
case token::array:
margin.set_array(tknizer.array());
case token::gap:
gap = tknizer.reparray();
break;
case token::reparray:
for (std::size_t i = 0; i < 4; ++i)
case token::margin:
margin.clear();
switch (tknizer.read())
{
auto n = tknizer.reparray().at(i);
if (n.empty()) n.assign(0);
margin.push(n);
}
break;
default:
break;
}
break;
case token::identifier:
name = tknizer.idstr();
break;
case token::left:
div_dir = ::nana::direction::west; break;
case token::right:
div_dir = ::nana::direction::east; break;
case token::top:
div_dir = ::nana::direction::north; break;
case token::bottom:
div_dir = ::nana::direction::south; break;
case token::undisplayed:
undisplayed = true; break;
case token::invisible:
invisible = true; break;
default: break;
}
}
if (implicitly_started && (tk == token::div_end))
throw std::invalid_argument("nana.place: the div-text ends prematurely at " + std::to_string(tknizer.pos()));
field_gather * attached_field = nullptr;
//find the field with specified name.
//the field may not be created.
auto i = fields.find(name);
if (fields.end() != i)
{
attached_field = i->second;
//the field is attached to a division, it means there is another division with same name.
if (attached_field->attached)
{
//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.
bool allow_same_name = false;
if (!ignore_duplicate.empty())
{
auto f = attached_field->attached->div_owner;
while (f)
{
if (f->name == ignore_duplicate)
case token::number:
margin.push(tknizer.number(), true);
break;
case token::array:
margin.set_array(tknizer.array());
break;
case token::reparray:
for (std::size_t i = 0; i < 4; ++i)
{
allow_same_name = true;
break;
auto n = tknizer.reparray().at(i);
if (n.empty()) n.assign(0);
margin.push(n);
}
f = f->div_owner;
break;
default:
break;
}
break;
case token::identifier:
name = tknizer.idstr();
break;
case token::left:
div_dir = ::nana::direction::west; break;
case token::right:
div_dir = ::nana::direction::east; break;
case token::top:
div_dir = ::nana::direction::north; break;
case token::bottom:
div_dir = ::nana::direction::south; break;
case token::undisplayed:
undisplayed = true; break;
case token::invisible:
invisible = true; break;
default: break;
}
if (!allow_same_name)
throw std::runtime_error("place, the name '" + name + "' is redefined.");
}
}
token unmatch = token::width;
switch (div_type)
{
case token::eof: // "horizontal" div
case token::vert: // "vertical" div
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);
div.reset(new div_arrange(token::vert == div_type, std::move(name), std::move(arrange)));
break;
case token::grid:
{
std::unique_ptr<div_grid> p(new div_grid(std::move(name), std::move(arrange), std::move(collapses)));
if (array.size())
p->dimension.first = array[0].integer();
if (array.size() > 1)
p->dimension.second = array[1].integer();
if (0 == p->dimension.first)
p->dimension.first = 1;
if (0 == p->dimension.second)
p->dimension.second = 1;
p->revise_collapses();
div = std::move(p);
}
break;
case token::dock:
div.reset(new div_dock(std::move(name), this));
break;
case token::switchable:
div.reset(new div_switchable(std::move(name), this));
break;
default:
throw std::invalid_argument("nana.place: invalid division type.");
}
div->weigth_type = weight_type;
//Requirements for min/max
//1, min and max != negative
//2, max >= min
if (min_px.is_negative()) min_px.reset();
if (max_px.is_negative()) max_px.reset();
if ((!min_px.empty()) && (!max_px.empty()) && (min_px.get_value(100) > max_px.get_value(100)))
{
min_px.reset();
max_px.reset();
}
if (!min_px.empty())
div->min_px = min_px;
if (!max_px.empty())
div->max_px = max_px;
if ((!min_px.empty()) && (!weight.empty()) && (weight.get_value(100) < min_px.get_value(100)))
weight.reset();
if ((!max_px.empty()) && (!weight.empty()) && (weight.get_value(100) > max_px.get_value(100)))
weight.reset();
if (!weight.empty())
div->weight = weight;
div->gap = std::move(gap);
//attach the field to the division
div->field = attached_field;
if (attached_field)
{
//Replaces the previous div with the new div which is allowed to have a same name.
//Detaches the field from the previous div.
if (attached_field->attached)
attached_field->attached->field = nullptr;
//Attaches new div
attached_field->attached = div.get();
}
if (children.size())
{
if (division::kind::splitter == children.back()->kind_of_division)
{
children.pop_back();
if (children.size())
children.back()->div_next = nullptr;
}
for (auto& child : children)
{
child->div_owner = div.get();
if (division::kind::splitter == child->kind_of_division)
dynamic_cast<div_splitter&>(*child).direction(div_type != token::vert);
}
if (implicitly_started && (tk == token::div_end))
throw std::invalid_argument("the div-text ends prematurely");
if (token::dock == div_type)
field_gather * attached_field = nullptr;
//find the field with specified name.
//the field may not be created.
auto i = fields.find(name);
if (fields.end() != i)
{
//adjust these children for dock division
std::vector<std::unique_ptr<division>> adjusted_children;
for (auto & child : children)
attached_field = i->second;
//the field is attached to a division, it means there is another division with same name.
if (attached_field->attached)
{
auto dockpn = new div_dockpane(std::move(child->name), this, child->dir);
dockpn->div_owner = child->div_owner;
dockpn->weight = child->weight;
adjusted_children.emplace_back(std::unique_ptr<division>{ dockpn });
}
//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 std::invalid_argument.
division * next = nullptr;
for (int i = static_cast<int>(adjusted_children.size()) - 1; i >= 0; --i)
{
adjusted_children[i]->div_next = next;
next = adjusted_children[i].get();
}
bool allow_same_name = false;
if (!ignore_duplicate.empty())
{
auto f = attached_field->attached->div_owner;
while (f)
{
if (f->name == ignore_duplicate)
{
allow_same_name = true;
break;
}
children.swap(adjusted_children);
f = f->div_owner;
}
}
if (!allow_same_name)
throw std::invalid_argument("redefined field name");
}
}
token unmatch = token::width;
switch (div_type)
{
case token::eof: // "horizontal" div
case token::vert: // "vertical" div
if (token::eof == div_type)
unmatch = token::height;
for (auto& ch : children)
if (ch->weigth_type == unmatch)
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;
case token::grid:
{
std::unique_ptr<div_grid> p(new div_grid(std::move(name), std::move(arrange), std::move(collapses)));
if (array.size())
p->dimension.first = array[0].integer();
if (array.size() > 1)
p->dimension.second = array[1].integer();
if (0 == p->dimension.first)
p->dimension.first = 1;
if (0 == p->dimension.second)
p->dimension.second = 1;
p->revise_collapses();
div = std::move(p);
}
break;
case token::dock:
div.reset(new div_dock(std::move(name), this));
break;
case token::switchable:
div.reset(new div_switchable(std::move(name), this));
break;
default:
throw std::invalid_argument("invalid division type.");
}
div->weigth_type = weight_type;
//Requirements for min/max
//1, min and max != negative
//2, max >= min
if (min_px.is_negative()) min_px.reset();
if (max_px.is_negative()) max_px.reset();
if ((!min_px.empty()) && (!max_px.empty()) && (min_px.get_value(100) > max_px.get_value(100)))
{
min_px.reset();
max_px.reset();
}
if (!min_px.empty())
div->min_px = min_px;
if (!max_px.empty())
div->max_px = max_px;
if ((!min_px.empty()) && (!weight.empty()) && (weight.get_value(100) < min_px.get_value(100)))
weight.reset();
if ((!max_px.empty()) && (!weight.empty()) && (weight.get_value(100) > max_px.get_value(100)))
weight.reset();
if (!weight.empty())
div->weight = weight;
div->gap = std::move(gap);
//attach the field to the division
div->field = attached_field;
if (attached_field)
{
//Replaces the previous div with the new div which is allowed to have a same name.
//Detaches the field from the previous div.
if (attached_field->attached)
attached_field->attached->field = nullptr;
//Attaches new div
attached_field->attached = div.get();
}
if (children.size())
{
if (division::kind::splitter == children.back()->kind_of_division)
{
children.pop_back();
if (children.size())
children.back()->div_next = nullptr;
}
for (auto& child : children)
{
child->div_owner = div.get();
if (division::kind::splitter == child->kind_of_division)
dynamic_cast<div_splitter&>(*child).direction(div_type != token::vert);
}
if (token::dock == div_type)
{
//adjust these children for dock division
std::vector<std::unique_ptr<division>> adjusted_children;
for (auto& child : children)
{
auto dockpn = new div_dockpane(std::move(child->name), this, child->dir);
dockpn->div_owner = child->div_owner;
dockpn->weight = child->weight;
adjusted_children.emplace_back(std::unique_ptr<division>{ dockpn });
}
division* next = nullptr;
for (int i = static_cast<int>(adjusted_children.size()) - 1; i >= 0; --i)
{
adjusted_children[i]->div_next = next;
next = adjusted_children[i].get();
}
children.swap(adjusted_children);
}
}
div->children.swap(children);
div->margin = std::move(margin);
div->dir = div_dir;
div->display = !undisplayed;
div->visible = !(undisplayed || invisible);
div->fit = fit;
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());
}
div->children.swap(children);
div->margin = std::move(margin);
div->dir = div_dir;
div->display = !undisplayed;
div->visible = !(undisplayed || invisible);
div->fit = fit;
div->fit_parameters = std::move(fit_parameters);
return div;
}
@ -3265,16 +3289,20 @@ namespace nana
void place::div(std::string div_text)
{
place_parts::tokenizer tknizer(div_text.c_str());
impl_->disconnect();
auto div = impl_->scan_div(tknizer, true);
try
{
place_parts::tokenizer tknizer(div_text.c_str());
impl_->disconnect();
auto div = impl_->scan_div(tknizer, true);
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::implement::error & e)
{
throw place::error("failed to set div('"+div_text+"'): " + e.what(), *this, e.field, e.pos);
}
catch (...) // tokenizer error
{
//redefined a name of field
@ -3295,19 +3323,15 @@ namespace nana
void place::modify(const char* name, const char* 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) )
throw badname("nana::place.modify()", *this, 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.modify(): field '";
what += name;
what += "' was not found.";
throw error(what, *this, name);
}
throw error("modify(): field was not found", *this, name);
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);
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)
{
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
//then create one.
@ -3387,8 +3416,7 @@ namespace nana
if (div)
{
if (div->field && (div->field != p))
throw error(std::string("nana::place.field(): unexpected error, the division attaches an unexpected field: ") + name,
*this, name);
throw error("field(): the division attaches an unexpected field", *this, name);
div->field = p;
p->attached = div;
@ -3466,7 +3494,7 @@ namespace nana
void place::field_visible(const char* name, bool vsb)
{
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);
if (div)
@ -3479,7 +3507,7 @@ namespace nana
bool place::field_visible(const char* name) const
{
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);
return (div && div->visible);
@ -3488,7 +3516,7 @@ namespace nana
void place::field_display(const char* name, bool dsp)
{
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);
if (div)
@ -3502,7 +3530,7 @@ namespace nana
bool place::field_display(const char* name) const
{
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);
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)
{
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];
if (!dock_ptr)
@ -3550,7 +3578,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);
@ -3586,7 +3614,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)
@ -3607,9 +3635,24 @@ namespace nana
return nullptr;
}
//end class place
place::error::error(const std::string& what,
const place& plc,
std::string field,
std::string::size_type pos)
//class place::error
: 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