new vfit/hfit for place
added fit-content support for button/picture/combox/label
This commit is contained in:
parent
f43d54d7e2
commit
f0dc62cc21
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -68,7 +68,7 @@ namespace nana
|
||||
void key_press(graph_reference, const arg_keyboard&) override;
|
||||
void key_char(graph_reference, const arg_keyboard&) override;
|
||||
private:
|
||||
drawer_impl * drawer_;
|
||||
drawer_impl * const drawer_;
|
||||
};
|
||||
|
||||
class item_proxy
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* A Picture Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
|
@ -56,7 +56,7 @@ namespace nana
|
||||
enum class token
|
||||
{
|
||||
div_start, div_end, splitter,
|
||||
identifier, dock, fit, fit_s, vert, grid, number, array, reparray,
|
||||
identifier, dock, fit, hfit, vfit, vert, grid, number, array, reparray,
|
||||
weight, gap, margin, arrange, variable, repeated, min_px, max_px, left, right, top, bottom, undisplayed, invisible,
|
||||
collapse, parameters,
|
||||
equal,
|
||||
@ -249,17 +249,22 @@ namespace nana
|
||||
return token::dock;
|
||||
else if ("fit" == idstr_)
|
||||
return token::fit;
|
||||
else if ("fit_s" == idstr_)
|
||||
return token::fit_s;
|
||||
else if ("vertical" == idstr_ || "vert" == idstr_)
|
||||
return token::vert;
|
||||
else if ("variable" == idstr_ || "repeated" == idstr_)
|
||||
return ('v' == idstr_[0] ? token::variable : token::repeated);
|
||||
else if ("arrange" == idstr_ || "gap" == idstr_)
|
||||
else if ("arrange" == idstr_ || "hfit" == idstr_ || "vfit" == idstr_ || "gap" == idstr_)
|
||||
{
|
||||
auto ch = idstr_[0];
|
||||
_m_attr_reparray();
|
||||
return ('a' == ch ? token::arrange : token::gap);
|
||||
switch (ch)
|
||||
{
|
||||
case 'a': return token::arrange;
|
||||
case 'h': return token::hfit;
|
||||
case 'v': return token::vfit;
|
||||
case 'g': return token::gap;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if ("grid" == idstr_ || "margin" == idstr_)
|
||||
{
|
||||
@ -722,7 +727,8 @@ namespace nana
|
||||
{
|
||||
none, //Doesn't fit the content
|
||||
both, //Fits both width and height of content
|
||||
single //Fits only width or height of content
|
||||
horz, //Fits width of content with a specified height
|
||||
vert //Fits height of content with a specified width
|
||||
};
|
||||
|
||||
class place::implement::division
|
||||
@ -767,6 +773,7 @@ namespace nana
|
||||
std::pair<double, double> calc_weight_floor()
|
||||
{
|
||||
std::pair<double, double> floor;
|
||||
run_.fit_extents.clear();
|
||||
|
||||
run_.weight_floor = floor;
|
||||
|
||||
@ -789,8 +796,9 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
auto const vert = (this->div_owner && (this->div_owner->kind_of_division == kind::vertical_arrange));
|
||||
double& fv = (vert ? floor.second : floor.first);
|
||||
auto const vert_fields = (kind::vertical_arrange == this->kind_of_division);
|
||||
auto const vert_div = (this->div_owner && (kind::vertical_arrange == this->div_owner->kind_of_division));
|
||||
double& fv = (vert_div ? floor.second : floor.first);
|
||||
|
||||
if((ratio > 0.001) && (fv > 0))
|
||||
fv /= ratio;
|
||||
@ -804,34 +812,49 @@ namespace nana
|
||||
{
|
||||
if (fit_policy::none != this->fit)
|
||||
{
|
||||
unsigned limited_px = 0;
|
||||
bool limit_width = false;
|
||||
|
||||
std::size_t fit_count = 0;
|
||||
|
||||
unsigned max_value = 0;
|
||||
auto const fit_horz = (fit_policy::vert == this->fit);
|
||||
|
||||
std::size_t pos = 0;
|
||||
for (auto & elm : this->field->elements)
|
||||
{
|
||||
auto extent = API::content_extent(elm.handle, 0, false);
|
||||
++pos;
|
||||
|
||||
unsigned edge_px = 0;
|
||||
if (fit_policy::both != this->fit)
|
||||
{
|
||||
auto fit_val = this->fit_parameters.at(pos - 1);
|
||||
if (fit_val.empty())
|
||||
continue;
|
||||
|
||||
edge_px = fit_val.integer();
|
||||
}
|
||||
|
||||
auto extent = API::content_extent(elm.handle, edge_px, fit_horz);
|
||||
if (extent)
|
||||
{
|
||||
run_.fit_extents[elm.handle] = extent->second;
|
||||
++fit_count;
|
||||
if (vert)
|
||||
if (vert_fields)
|
||||
floor.second += extent->second.height;
|
||||
else
|
||||
floor.first += extent->second.width;
|
||||
|
||||
max_value = (std::max)(max_value, (vert ? extent->second.width : extent->second.height));
|
||||
max_value = (std::max)(max_value, (vert_fields ? extent->second.width : extent->second.height));
|
||||
}
|
||||
}
|
||||
|
||||
if (max_value)
|
||||
{
|
||||
if (vert)
|
||||
if (vert_fields)
|
||||
floor.first = max_value;
|
||||
else
|
||||
floor.second = max_value;
|
||||
}
|
||||
|
||||
|
||||
if (fit_count > 1)
|
||||
{
|
||||
double percent = 0;
|
||||
@ -1005,6 +1028,7 @@ namespace nana
|
||||
bool display{ true };
|
||||
bool visible{ true };
|
||||
fit_policy fit{ fit_policy::none };
|
||||
repeated_array fit_parameters; //it is ignored when fit is not fit_policy::horz or fit_policy::vert
|
||||
::nana::direction dir{::nana::direction::west};
|
||||
std::string name;
|
||||
std::vector<std::unique_ptr<division>> children;
|
||||
@ -1022,6 +1046,7 @@ namespace nana
|
||||
struct run_data
|
||||
{
|
||||
std::pair<double, double> weight_floor;
|
||||
std::map<window, ::nana::size> fit_extents;
|
||||
}run_;
|
||||
};//end class division
|
||||
|
||||
@ -1069,6 +1094,7 @@ namespace nana
|
||||
child_px = adjustable_px;
|
||||
|
||||
child_px = limit_px(child, child_px, area_px);
|
||||
|
||||
auto npx = static_cast<unsigned>(child_px);
|
||||
precise_px = child_px - npx;
|
||||
child_px = npx;
|
||||
@ -1109,9 +1135,23 @@ namespace nana
|
||||
unsigned px = 0;
|
||||
|
||||
auto move_r = element_r.result();
|
||||
if (fit_policy::both == this->fit)
|
||||
if (fit_policy::none != this->fit)
|
||||
{
|
||||
auto extent = API::content_extent(el.handle, 0, false);
|
||||
auto i = run_.fit_extents.find(el.handle);
|
||||
if (run_.fit_extents.end() != i)
|
||||
{
|
||||
move_r.dimension(i->second);
|
||||
|
||||
if (vert)
|
||||
move_r.x += place_parts::differ(area_margined.width, move_r.width) / 2;
|
||||
else
|
||||
move_r.y += place_parts::differ(area_margined.height, move_r.height) / 2;
|
||||
|
||||
px = (vert ? move_r.height : move_r.width);
|
||||
moved = true;
|
||||
}
|
||||
/*
|
||||
auto extent = API::content_extent(el.handle, 0, false); //deprecated
|
||||
if (extent)
|
||||
{
|
||||
move_r.dimension(extent->second);
|
||||
@ -1124,6 +1164,7 @@ namespace nana
|
||||
px = (vert ? move_r.height : move_r.width);
|
||||
moved = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (!moved)
|
||||
@ -1178,12 +1219,26 @@ namespace nana
|
||||
std::pair<unsigned, std::size_t> result;
|
||||
if (field && (kind_of_division == match_kind))
|
||||
{
|
||||
auto const vert = (kind_of_division == kind::vertical_arrange);
|
||||
|
||||
//Calculate fixed and adjustable of elements
|
||||
double precise_px = 0;
|
||||
auto count = field->elements.size();
|
||||
for (decltype(count) i = 0; i < count; ++i)
|
||||
{
|
||||
auto fa = _m_calc_fa(arrange_.at(i), area_px, precise_px);
|
||||
|
||||
//The fit-content element is like a fixed element
|
||||
if (fit_policy::none != this->fit)
|
||||
{
|
||||
auto fi = this->run_.fit_extents.find(field->elements[i].handle);
|
||||
if (this->run_.fit_extents.cend() != fi)
|
||||
{
|
||||
fa.first = (vert ? fi->second.height : fi->second.width);
|
||||
fa.second = 0; //This isn't an adjustable element
|
||||
}
|
||||
}
|
||||
|
||||
result.first += fa.first;
|
||||
result.second += fa.second;
|
||||
|
||||
@ -2515,6 +2570,7 @@ namespace nana
|
||||
std::unique_ptr<division> div;
|
||||
token div_type = token::eof;
|
||||
auto fit = fit_policy::none;
|
||||
place_parts::repeated_array fit_parameters;
|
||||
|
||||
//These variables stand for the new division's attributes
|
||||
std::string name;
|
||||
@ -2542,8 +2598,10 @@ namespace nana
|
||||
case token::fit:
|
||||
fit = fit_policy::both;
|
||||
break;
|
||||
case token::fit_s:
|
||||
fit = fit_policy::single;
|
||||
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.
|
||||
@ -2809,6 +2867,8 @@ namespace nana
|
||||
div->display = !undisplayed;
|
||||
div->visible = !(undisplayed || invisible);
|
||||
div->fit = fit;
|
||||
div->fit_parameters = std::move(fit_parameters);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,10 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
|
||||
{
|
||||
//Button doesn't provide a support of vfit and hfit
|
||||
if (limit_pixels)
|
||||
return{};
|
||||
|
||||
wchar_t shortkey;
|
||||
std::string::size_type shortkey_pos;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Combox Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -17,8 +17,10 @@
|
||||
#include <nana/gui/widgets/float_listbox.hpp>
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
|
||||
#include <nana/gui/detail/widget_content_measurer_interface.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -80,6 +82,46 @@ namespace nana
|
||||
|
||||
class drawer_impl
|
||||
{
|
||||
class content_measurer
|
||||
: public dev::widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
content_measurer(drawer_impl* drwimpl)
|
||||
: drw_{ drwimpl }
|
||||
{}
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
|
||||
{
|
||||
//Button doesn't provide a support of vfit and hfit
|
||||
if (limit_pixels)
|
||||
return{};
|
||||
|
||||
size content_size;
|
||||
for (auto i = 0; i < drw_->the_number_of_options(); ++i)
|
||||
{
|
||||
auto & m = drw_->at(i);
|
||||
auto sz = graph.text_extent_size(m.item_text);
|
||||
|
||||
content_size.width = (std::max)(content_size.width, sz.width);
|
||||
content_size.height = (std::max)(content_size.height, sz.height);
|
||||
}
|
||||
|
||||
return content_size;
|
||||
}
|
||||
|
||||
size extension() const override
|
||||
{
|
||||
auto text_size = drw_->editor()->text_area(false).dimension();
|
||||
auto wdg_size = drw_->widget_ptr()->size();
|
||||
|
||||
return{
|
||||
wdg_size.width > text_size.width ? wdg_size.width - text_size.width : 0,
|
||||
wdg_size.height > text_size.height ? wdg_size.height - text_size.height : 0
|
||||
};
|
||||
}
|
||||
private:
|
||||
drawer_impl* const drw_;
|
||||
};
|
||||
public:
|
||||
using graph_reference = paint::graphics&;
|
||||
using widget_reference = widget&;
|
||||
@ -92,6 +134,8 @@ namespace nana
|
||||
state_.button_state = element_state::normal;
|
||||
state_.pointer_where = parts::none;
|
||||
state_.lister = nullptr;
|
||||
|
||||
measurer_.reset(new content_measurer{this});
|
||||
}
|
||||
|
||||
void renderer(drawerbase::float_listbox::item_renderer* ir)
|
||||
@ -111,6 +155,8 @@ namespace nana
|
||||
|
||||
evt_agent_.reset(new event_agent{ static_cast<nana::combox&>(wd) });
|
||||
editor_->textbase().set_event_agent(evt_agent_.get());
|
||||
|
||||
API::dev::set_measurer(wd, measurer_.get());
|
||||
}
|
||||
|
||||
void detached()
|
||||
@ -528,6 +574,8 @@ namespace nana
|
||||
unsigned image_pixels_{ 16 };
|
||||
widgets::skeletons::text_editor * editor_{ nullptr };
|
||||
std::unique_ptr<event_agent> evt_agent_;
|
||||
|
||||
std::unique_ptr<content_measurer> measurer_;
|
||||
struct state_type
|
||||
{
|
||||
bool focused;
|
||||
@ -537,13 +585,16 @@ namespace nana
|
||||
nana::float_listbox * lister;
|
||||
std::size_t item_index_before_selection;
|
||||
}state_;
|
||||
};
|
||||
|
||||
|
||||
}; //end class drawer_impl
|
||||
|
||||
|
||||
//class trigger
|
||||
trigger::trigger()
|
||||
: drawer_(new drawer_impl)
|
||||
{}
|
||||
trigger::trigger() :
|
||||
drawer_(new drawer_impl)
|
||||
{
|
||||
}
|
||||
|
||||
trigger::~trigger()
|
||||
{
|
||||
|
@ -184,10 +184,10 @@ namespace nana
|
||||
rs.text_align = th;
|
||||
rs.text_align_v = tv;
|
||||
|
||||
for(auto i = dstream_.begin(), end = dstream_.end(); i != end; ++i)
|
||||
for(auto & line: dstream_)
|
||||
{
|
||||
rs.pixels.clear();
|
||||
unsigned w = _m_line_pixels(*i, def_line_pixels, rs);
|
||||
unsigned w = _m_line_pixels(line, def_line_pixels, rs);
|
||||
|
||||
if(limited && (w > limited))
|
||||
w = limited;
|
||||
@ -366,7 +366,8 @@ namespace nana
|
||||
sz.height = max_ascent + max_descent;
|
||||
}
|
||||
|
||||
if(w + sz.width <= rs.allowed_width)
|
||||
//Check if the content is displayed in a new line.
|
||||
if((0 == rs.allowed_width) || (w + sz.width <= rs.allowed_width))
|
||||
{
|
||||
w += sz.width;
|
||||
|
||||
@ -620,7 +621,7 @@ namespace nana
|
||||
|
||||
widget * wd{nullptr};
|
||||
paint::graphics * graph{nullptr};
|
||||
class measurer * measurer{ nullptr };
|
||||
std::unique_ptr<measurer> msr_ptr{ nullptr };
|
||||
|
||||
align text_align{align::left};
|
||||
align_v text_align_v;
|
||||
@ -657,9 +658,10 @@ namespace nana
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
|
||||
{
|
||||
if (graph)
|
||||
//Label now doesn't support to measure content with a specified height.
|
||||
if (graph && ((0 == limit_pixels) || limit_width))
|
||||
{
|
||||
|
||||
return impl_->renderer.measure(graph, limit_pixels, impl_->text_align, impl_->text_align_v);
|
||||
}
|
||||
return{};
|
||||
}
|
||||
@ -674,7 +676,9 @@ namespace nana
|
||||
|
||||
trigger::trigger()
|
||||
:impl_(new implement)
|
||||
{}
|
||||
{
|
||||
impl_->msr_ptr.reset(new trigger::implement::measurer{impl_});
|
||||
}
|
||||
|
||||
trigger::~trigger()
|
||||
{
|
||||
@ -690,6 +694,7 @@ namespace nana
|
||||
{
|
||||
impl_->graph = &graph;
|
||||
impl_->wd = &widget;
|
||||
API::dev::set_measurer(widget, impl_->msr_ptr.get());
|
||||
}
|
||||
|
||||
void trigger::mouse_move(graph_reference, const arg_mouse& arg)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* A Picture Implementation
|
||||
* Nana C++ Library(http://www.nanapro.org)
|
||||
* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com)
|
||||
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
@ -16,6 +16,7 @@
|
||||
#include <nana/gui/layout_utility.hpp>
|
||||
#include <nana/paint/image.hpp>
|
||||
#include <nana/gui/element.hpp>
|
||||
#include <nana/gui/detail/widget_content_measurer_interface.hpp>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
@ -23,11 +24,13 @@ namespace nana
|
||||
{
|
||||
namespace picture
|
||||
{
|
||||
class content_measurer;
|
||||
|
||||
struct implement
|
||||
{
|
||||
widget* wdg_ptr{nullptr};
|
||||
paint::graphics* graph_ptr{nullptr};
|
||||
|
||||
std::unique_ptr<content_measurer> measurer;
|
||||
|
||||
struct gradual_bground_tag
|
||||
{
|
||||
@ -47,9 +50,37 @@ namespace nana
|
||||
}backimg;
|
||||
};
|
||||
|
||||
class content_measurer
|
||||
: public dev::widget_content_measurer_interface
|
||||
{
|
||||
public:
|
||||
content_measurer(implement* impl)
|
||||
: impl_{impl}
|
||||
{}
|
||||
|
||||
optional<size> measure(graph_reference graph, unsigned limit_pixels, bool limit_width) const override
|
||||
{
|
||||
//Button doesn't provide a support of vfit and hfit
|
||||
if (!limit_pixels)
|
||||
{
|
||||
if (impl_->backimg.valid_area.empty())
|
||||
return impl_->backimg.image.size();
|
||||
}
|
||||
return{};
|
||||
}
|
||||
|
||||
size extension() const override
|
||||
{
|
||||
return{};
|
||||
}
|
||||
private:
|
||||
implement* const impl_;
|
||||
};
|
||||
|
||||
//class drawer
|
||||
drawer::drawer() :impl_(new implement)
|
||||
{
|
||||
impl_->measurer.reset(new content_measurer{impl_});
|
||||
}
|
||||
|
||||
drawer::~drawer()
|
||||
@ -61,6 +92,7 @@ namespace nana
|
||||
{
|
||||
impl_->wdg_ptr = &wdg;
|
||||
impl_->graph_ptr = &graph;
|
||||
API::dev::set_measurer(wdg, impl_->measurer.get());
|
||||
}
|
||||
|
||||
void drawer::refresh(graph_reference graph)
|
||||
|
Loading…
x
Reference in New Issue
Block a user