add a new helper class text_aligner

This commit is contained in:
Jinhao 2016-06-18 07:23:01 +08:00
parent 8bcfc82580
commit 58d517d166
2 changed files with 122 additions and 1 deletions

View File

@ -9,7 +9,7 @@ namespace nana
class text_renderer
{
public:
typedef graphics & graph_reference;
using graph_reference = graphics &;
text_renderer(graph_reference graph, align = align::left);
@ -22,6 +22,35 @@ namespace nana
graph_reference graph_;
align text_align_;
};
/// Draw aligned string
class aligner
{
public:
using graph_reference = graphics&;
/// Constructor
/**
* @param graph Reference to a graphics object
* @param text_align Alignment of text
* @param text_align_if_too_long Alignment of text if the pixels of string is larger than text area
*/
aligner(graph_reference graph, align text_align = align::left);
aligner(graph_reference graph, align text_align, align text_align_if_too_long);
/// Draws a text with specified text alignment.
/**
* @param text Text to draw
* @param pos Postion where the text to draw
* @param width The width of text area. If the pixels of text is larger than this parameter, it draws ellipsis
*/
void draw(const std::string& text, point pos, unsigned width);
void draw(const std::wstring& text, point pos, unsigned width);
private:
graph_reference graph_;
align text_align_;
align text_align_ex_;
};
}
}

View File

@ -582,5 +582,97 @@ namespace nana
}
}
//end class text_renderer
//class aligner
//Constructor
aligner::aligner(graph_reference graph, align text_align)
: aligner{ graph, text_align, text_align }
{}
aligner::aligner(graph_reference graph, align text_align, align text_align_ex) :
graph_(graph),
text_align_(text_align),
text_align_ex_(text_align_ex)
{}
// Draws a text with specified text alignment.
void aligner::draw(const std::string& text, point pos, unsigned width)
{
draw(to_wstring(text), pos, width);
}
void aligner::draw(const std::wstring& text, point pos, unsigned width)
{
auto text_px = graph_.text_extent_size(text).width;
if (text_px <= width)
{
switch (text_align_)
{
case align::center:
pos.x += static_cast<int>(width - text_px) / 2;
break;
case align::right:
pos.x += static_cast<int>(width - text_px);
default:
break;
}
graph_.bidi_string(pos, text.c_str(), text.size());
return;
}
const auto ellipsis = graph_.text_extent_size("...", 3).width;
std::unique_ptr<unsigned[]> pixels(new unsigned[text.size()]);
graph_.glyph_pixels(text.c_str(), text.size(), pixels.get());
unsigned substr_len = 0;
unsigned substr_px = 0;
if (align::right == text_align_ex_)
{
auto end = pixels.get();
auto p = end + text.size();
do
{
--p;
if (substr_px + *p + ellipsis > width)
{
substr_len = p - pixels.get() + 1;
break;
}
substr_px += *p;
} while (p != end);
pos.x += static_cast<int>(width - ellipsis - substr_px);
graph_.string(pos, "...");
pos.x += ellipsis;
graph_.bidi_string(pos, text.c_str() + substr_len, text.size() - substr_len);
}
else
{
for (auto p = pixels.get(), end = pixels.get() + text.size(); p != end; ++p)
{
if (substr_px + *p + ellipsis > width)
{
substr_len = p - pixels.get();
break;
}
substr_px += *p;
}
if (align::center == text_align_ex_)
pos.x += (width - substr_px - ellipsis) / 2;
graph_.bidi_string(pos, text.c_str(), substr_len);
pos.x += substr_px;
graph_.string(pos, "...");
}
}
//end class string
}
}