Merge pull request #300 from cbeck88/clickable_labels
Clickable hyperlinks in gui2 labels
This commit is contained in:
commit
455f6f7209
11 changed files with 430 additions and 8 deletions
|
@ -23,6 +23,9 @@
|
|||
text_font_size = {FONT_SIZE}
|
||||
text_font_style = {FONT_STYLE}
|
||||
|
||||
link_aware = true
|
||||
link_color = #ffff00
|
||||
|
||||
[state_enabled]
|
||||
|
||||
[draw]
|
||||
|
@ -38,6 +41,8 @@
|
|||
color = {FONT_COLOR_ENABLED}
|
||||
text = "(text)"
|
||||
text_markup = "(text_markup)"
|
||||
text_link_aware = "(text_link_aware)"
|
||||
text_link_color = "(text_link_color)"
|
||||
[/text]
|
||||
|
||||
[/draw]
|
||||
|
@ -59,6 +64,8 @@
|
|||
color = {FONT_COLOR_DISABLED}
|
||||
text = "(text)"
|
||||
text_markup = "(text_markup)"
|
||||
text_link_aware = "(text_link_aware)"
|
||||
text_link_color = "(text_link_color)"
|
||||
[/text]
|
||||
|
||||
[/draw]
|
||||
|
|
|
@ -366,6 +366,16 @@
|
|||
type="f_bool"
|
||||
default=false
|
||||
[/key]
|
||||
[key]
|
||||
name="text_link_aware"
|
||||
type="f_bool"
|
||||
default=false
|
||||
[/key]
|
||||
[key]
|
||||
name="text_link_color"
|
||||
type="string"
|
||||
default="#ffff00"
|
||||
[/key]
|
||||
[key]
|
||||
name="w"
|
||||
type="f_unsigned"
|
||||
|
@ -680,6 +690,16 @@
|
|||
max="1"
|
||||
super="generic/state"
|
||||
[/tag]
|
||||
[key]
|
||||
name="link_aware"
|
||||
type="bool"
|
||||
default="false"
|
||||
[/key]
|
||||
[key]
|
||||
name="link_color"
|
||||
type="string"
|
||||
default="#ffff00"
|
||||
[/key]
|
||||
[/tag]
|
||||
[/tag]
|
||||
[tag]
|
||||
|
|
|
@ -1270,6 +1270,12 @@ private:
|
|||
/** The text markup switch of the text. */
|
||||
tformula<bool> text_markup_;
|
||||
|
||||
/** The link aware switch of the text. */
|
||||
tformula<bool> link_aware_;
|
||||
|
||||
/** The link color of the text. */
|
||||
tformula<std::string> link_color_;
|
||||
|
||||
/** The maximum width for the text. */
|
||||
tformula<int> maximum_width_;
|
||||
|
||||
|
@ -1303,6 +1309,10 @@ private:
|
|||
* color & color & "" & The color of the text. $
|
||||
* text & f_tstring & "" & The text to draw (translatable). $
|
||||
* text_markup & f_bool & false & Can the text have mark-up? $
|
||||
* text_link_aware & f_bool & false &
|
||||
* Is the text link aware? $
|
||||
* text_link_color & f_string & "#ffff00" &
|
||||
* The color of links in the text $
|
||||
* maximum_width & f_int & -1 & The maximum width the text is allowed to
|
||||
* be. $
|
||||
* maximum_height & f_int & -1 & The maximum height the text is allowed
|
||||
|
@ -1336,6 +1346,8 @@ ttext::ttext(const config& cfg)
|
|||
, color_(decode_color(cfg["color"]))
|
||||
, text_(cfg["text"])
|
||||
, text_markup_(cfg["text_markup"], false)
|
||||
, link_aware_(cfg["text_link_aware"], false)
|
||||
, link_color_(cfg["text_link_color"], "#ffff00")
|
||||
, maximum_width_(cfg["maximum_width"], -1)
|
||||
, characters_per_line_(cfg["text_characters_per_line"])
|
||||
, maximum_height_(cfg["maximum_height"], -1)
|
||||
|
@ -1364,6 +1376,9 @@ void ttext::draw(surface& canvas,
|
|||
}
|
||||
|
||||
static font::ttext text_renderer;
|
||||
|
||||
text_renderer.set_link_aware(link_aware_(variables))
|
||||
.set_link_color(link_color_(variables));
|
||||
text_renderer.set_text(text, text_markup_(variables));
|
||||
|
||||
text_renderer.set_font_size(font_size_)
|
||||
|
|
|
@ -41,12 +41,24 @@ tlabel_definition::tlabel_definition(const config& cfg)
|
|||
* The reason is that labels are often used as visual indication of the state
|
||||
* of the widget it labels.
|
||||
*
|
||||
* Note: The above is outdated, if "link_aware" is enabled then there is interaction.
|
||||
*
|
||||
*
|
||||
* The following states exist:
|
||||
* * state_enabled, the label is enabled.
|
||||
* * state_disabled, the label is disabled.
|
||||
* @begin{parent}{name="gui/"}
|
||||
* @begin{tag}{name="label_definition"}{min=0}{max=-1}{super="generic/widget_definition"}
|
||||
* @begin{tag}{name="resolution"}{min=0}{max=-1}{super="generic/widget_definition/resolution"}
|
||||
* @begin{table}{config}
|
||||
* link_aware & f_bool & false & Whether the label is link aware. This means
|
||||
* it is rendered with links highlighted,
|
||||
* and responds to click events on those
|
||||
* links. $
|
||||
* link_color & string & #ffff00 & The color to render links with. This
|
||||
* string will be used verbatim in pango
|
||||
* markup for each link. $
|
||||
* @end{table}
|
||||
* @begin{tag}{name="state_enabled"}{min=0}{max=1}{super="generic/state"}
|
||||
* @end{tag}{name="state_enabled"}
|
||||
* @begin{tag}{name="state_disabled"}{min=0}{max=1}{super="generic/state"}
|
||||
|
@ -57,6 +69,8 @@ tlabel_definition::tlabel_definition(const config& cfg)
|
|||
*/
|
||||
tlabel_definition::tresolution::tresolution(const config& cfg)
|
||||
: tresolution_definition_(cfg)
|
||||
, link_aware(cfg["link_aware"].to_bool(false))
|
||||
, link_color(cfg["link_color"].str().size() > 0 ? cfg["link_color"].str() : "#ffff00")
|
||||
{
|
||||
// Note the order should be the same as the enum tstate is label.hpp.
|
||||
state.push_back(tstate_definition(cfg.child("state_enabled")));
|
||||
|
|
|
@ -28,6 +28,9 @@ struct tlabel_definition : public tcontrol_definition
|
|||
struct tresolution : public tresolution_definition_
|
||||
{
|
||||
explicit tresolution(const config& cfg);
|
||||
|
||||
bool link_aware;
|
||||
std::string link_color;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -173,6 +173,16 @@ unsigned tcontrol::get_characters_per_line() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool tcontrol::get_link_aware() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tcontrol::get_link_color() const
|
||||
{
|
||||
return "#ffff00";
|
||||
}
|
||||
|
||||
void tcontrol::layout_initialise(const bool full_initialisation)
|
||||
{
|
||||
// Inherited.
|
||||
|
@ -353,6 +363,8 @@ void tcontrol::update_canvas()
|
|||
{
|
||||
canvas.set_variable("text", variant(label_));
|
||||
canvas.set_variable("text_markup", variant(use_markup_));
|
||||
canvas.set_variable("text_link_aware", variant(get_link_aware()));
|
||||
canvas.set_variable("text_link_color", variant(get_link_color()));
|
||||
canvas.set_variable("text_alignment",
|
||||
variant(encode_text_alignment(text_alignment_)));
|
||||
canvas.set_variable("text_maximum_width", variant(max_width));
|
||||
|
@ -437,6 +449,9 @@ tpoint tcontrol::get_best_text_size(const tpoint& minimum_size,
|
|||
const tpoint border(config_->text_extra_width, config_->text_extra_height);
|
||||
tpoint size = minimum_size - border;
|
||||
|
||||
renderer_.set_link_aware(get_link_aware())
|
||||
.set_link_color(get_link_color());
|
||||
|
||||
renderer_.set_text(label_, use_markup_);
|
||||
|
||||
renderer_.set_font_size(config_->text_font_size);
|
||||
|
@ -543,4 +558,14 @@ void tcontrol::signal_handler_notify_remove_tooltip(const event::tevent event,
|
|||
handled = true;
|
||||
}
|
||||
|
||||
std::string tcontrol::get_label_token(const gui2::tpoint & position, const char * delim) const
|
||||
{
|
||||
return renderer_.get_token(position, delim);
|
||||
}
|
||||
|
||||
std::string tcontrol::get_label_link(const gui2::tpoint & position) const
|
||||
{
|
||||
return renderer_.get_link(position);
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -141,6 +141,29 @@ public:
|
|||
*/
|
||||
virtual unsigned get_characters_per_line() const;
|
||||
|
||||
/**
|
||||
* Returns whether the label should be link_aware, in
|
||||
* in rendering and in searching for links with get_link.
|
||||
*
|
||||
* This value is used to call @ref ttext::set_link_aware
|
||||
* (indirectly).
|
||||
*
|
||||
* @returns The link aware status. This impl always
|
||||
* always returns false.
|
||||
*/
|
||||
virtual bool get_link_aware() const;
|
||||
|
||||
/**
|
||||
* Returns the color string to be used with links.
|
||||
*
|
||||
* This value is used to call @ref ttext::set_link_color
|
||||
* (indirectly).
|
||||
*
|
||||
* @returns The link color string. This impl returns "#ffff00".
|
||||
*
|
||||
*/
|
||||
virtual std::string get_link_color() const;
|
||||
|
||||
/**
|
||||
* See @ref twidget::layout_initialise.
|
||||
*
|
||||
|
@ -421,6 +444,11 @@ protected:
|
|||
int x_offset,
|
||||
int y_offset) OVERRIDE;
|
||||
|
||||
/** Exposes font::ttext::get_token, for the text label of this control */
|
||||
std::string get_label_token(const gui2::tpoint & position, const char * delimiters = " \n\r\t") const;
|
||||
|
||||
std::string get_label_link(const gui2::tpoint & position) const;
|
||||
|
||||
private:
|
||||
#ifdef GUI2_EXPERIMENTAL_LISTBOX
|
||||
/**
|
||||
|
|
|
@ -16,18 +16,39 @@
|
|||
|
||||
#include "gui/widgets/label.hpp"
|
||||
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/auxiliary/widget_definition/label.hpp"
|
||||
#include "gui/auxiliary/window_builder/label.hpp"
|
||||
#include "gui/dialogs/message.hpp"
|
||||
#include "gui/widgets/detail/register.tpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
#include "gui/widgets/window.hpp"
|
||||
|
||||
#include "desktop/clipboard.hpp"
|
||||
#include "desktop/open.hpp"
|
||||
#include "gettext.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace gui2
|
||||
{
|
||||
|
||||
REGISTER_WIDGET(label)
|
||||
|
||||
tlabel::tlabel()
|
||||
: tcontrol(COUNT)
|
||||
, state_(ENABLED)
|
||||
, can_wrap_(false)
|
||||
, characters_per_line_(0)
|
||||
, link_aware_(false)
|
||||
, link_color_("#ffff00")
|
||||
{
|
||||
connect_signal<event::LEFT_BUTTON_CLICK>(boost::bind(&tlabel::signal_handler_left_button_click, this, _2, _3));
|
||||
connect_signal<event::RIGHT_BUTTON_CLICK>(boost::bind(&tlabel::signal_handler_right_button_click, this, _2, _3));
|
||||
}
|
||||
|
||||
bool tlabel::can_wrap() const
|
||||
{
|
||||
return can_wrap_ || characters_per_line_ != 0;
|
||||
|
@ -38,6 +59,16 @@ unsigned tlabel::get_characters_per_line() const
|
|||
return characters_per_line_;
|
||||
}
|
||||
|
||||
bool tlabel::get_link_aware() const
|
||||
{
|
||||
return link_aware_;
|
||||
}
|
||||
|
||||
std::string tlabel::get_link_color() const
|
||||
{
|
||||
return link_color_;
|
||||
}
|
||||
|
||||
void tlabel::set_active(const bool active)
|
||||
{
|
||||
if(get_active() != active) {
|
||||
|
@ -65,6 +96,27 @@ void tlabel::set_characters_per_line(const unsigned characters_per_line)
|
|||
characters_per_line_ = characters_per_line;
|
||||
}
|
||||
|
||||
void tlabel::set_link_aware(bool link_aware)
|
||||
{
|
||||
if(link_aware == link_aware_) {
|
||||
return;
|
||||
}
|
||||
|
||||
link_aware_ = link_aware;
|
||||
update_canvas();
|
||||
set_is_dirty(true);
|
||||
}
|
||||
|
||||
void tlabel::set_link_color(const std::string & color)
|
||||
{
|
||||
if(color == link_color_) {
|
||||
return;
|
||||
}
|
||||
link_color_ = color;
|
||||
update_canvas();
|
||||
set_is_dirty(true);
|
||||
}
|
||||
|
||||
void tlabel::set_state(const tstate state)
|
||||
{
|
||||
if(state != state_) {
|
||||
|
@ -79,4 +131,86 @@ const std::string& tlabel::get_control_type() const
|
|||
return type;
|
||||
}
|
||||
|
||||
void tlabel::load_config_extra()
|
||||
{
|
||||
assert(config());
|
||||
|
||||
boost::intrusive_ptr<const tlabel_definition::tresolution>
|
||||
conf = boost::dynamic_pointer_cast<const tlabel_definition::tresolution>(
|
||||
config());
|
||||
|
||||
assert(conf);
|
||||
|
||||
set_link_aware(conf->link_aware);
|
||||
set_link_color(conf->link_color);
|
||||
}
|
||||
|
||||
|
||||
void tlabel::signal_handler_left_button_click(const event::tevent /* event */, bool & handled)
|
||||
{
|
||||
DBG_GUI_E << "label click" << std::endl;
|
||||
|
||||
if (!get_link_aware()) {
|
||||
return ; // without marking event as "handled".
|
||||
}
|
||||
|
||||
if (!desktop::open_object_is_supported()) {
|
||||
gui2::show_message(get_window()->video(), "", _("Opening links is not supported, contact your packager."), gui2::tmessage::auto_close);
|
||||
handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
get_window()->mouse_capture();
|
||||
|
||||
tpoint mouse = get_mouse_position();
|
||||
|
||||
mouse.x -= get_x();
|
||||
mouse.y -= get_y();
|
||||
|
||||
std::string link = get_label_link(mouse);
|
||||
|
||||
if (link.length() == 0) {
|
||||
return ; // without marking event as "handled"
|
||||
}
|
||||
|
||||
DBG_GUI_E << "Clicked Link:\"" << link << "\"\n";
|
||||
|
||||
const int res = gui2::show_message(get_window()->video(), "", _("Do you want to open this link?") + std::string("\n") + link, gui2::tmessage::yes_no_buttons);
|
||||
if(res != gui2::twindow::CANCEL) {
|
||||
desktop::open_object(link);
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
void tlabel::signal_handler_right_button_click(const event::tevent /* event */, bool & handled)
|
||||
{
|
||||
DBG_GUI_E << "label right click" << std::endl;
|
||||
|
||||
if (!get_link_aware()) {
|
||||
return ; // without marking event as "handled".
|
||||
}
|
||||
|
||||
get_window()->mouse_capture();
|
||||
|
||||
tpoint mouse = get_mouse_position();
|
||||
|
||||
mouse.x -= get_x();
|
||||
mouse.y -= get_y();
|
||||
|
||||
std::string link = get_label_link(mouse);
|
||||
|
||||
if (link.length() == 0) {
|
||||
return ; // without marking event as "handled"
|
||||
}
|
||||
|
||||
DBG_GUI_E << "Right Clicked Link:\"" << link << "\"\n";
|
||||
|
||||
desktop::clipboard::copy_to_clipboard(link, false);
|
||||
|
||||
gui2::show_message(get_window()->video(), "", _("Copied link!"), gui2::tmessage::auto_close);
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -24,13 +24,7 @@ namespace gui2
|
|||
class tlabel : public tcontrol
|
||||
{
|
||||
public:
|
||||
tlabel()
|
||||
: tcontrol(COUNT)
|
||||
, state_(ENABLED)
|
||||
, can_wrap_(false)
|
||||
, characters_per_line_(0)
|
||||
{
|
||||
}
|
||||
tlabel();
|
||||
|
||||
/** See @ref twidget::can_wrap. */
|
||||
virtual bool can_wrap() const OVERRIDE;
|
||||
|
@ -38,6 +32,12 @@ public:
|
|||
/** See @ref tcontrol::get_characters_per_line. */
|
||||
virtual unsigned get_characters_per_line() const OVERRIDE;
|
||||
|
||||
/** See @ref tcontrol::get_link_aware. */
|
||||
virtual bool get_link_aware() const OVERRIDE;
|
||||
|
||||
/** See @ref tcontrol::get_link_aware. */
|
||||
virtual std::string get_link_color() const OVERRIDE;
|
||||
|
||||
/** See @ref tcontrol::set_active. */
|
||||
virtual void set_active(const bool active) OVERRIDE;
|
||||
|
||||
|
@ -59,6 +59,10 @@ public:
|
|||
|
||||
void set_characters_per_line(const unsigned set_characters_per_line);
|
||||
|
||||
void set_link_aware(bool l);
|
||||
|
||||
void set_link_color(const std::string & color);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Possible states of the widget.
|
||||
|
@ -91,8 +95,34 @@ private:
|
|||
*/
|
||||
unsigned characters_per_line_;
|
||||
|
||||
/**
|
||||
* Whether the label is link aware, rendering links with special formatting
|
||||
* and handling click events.
|
||||
*/
|
||||
bool link_aware_;
|
||||
|
||||
/**
|
||||
* What color links will be rendered in.
|
||||
*/
|
||||
std::string link_color_;
|
||||
|
||||
/** See @ref tcontrol::get_control_type. */
|
||||
virtual const std::string& get_control_type() const OVERRIDE;
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
void load_config_extra();
|
||||
|
||||
/***** ***** ***** signal handlers ***** ****** *****/
|
||||
|
||||
/**
|
||||
* Left click signal handler: checks if we clicked on a hyperlink
|
||||
*/
|
||||
void signal_handler_left_button_click(const event::tevent event, bool & handled);
|
||||
|
||||
/**
|
||||
* Right click signal handler: checks if we clicked on a hyperlink, copied to clipboard
|
||||
*/
|
||||
void signal_handler_right_button_click(const event::tevent event, bool & handled);
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
|
113
src/text.cpp
113
src/text.cpp
|
@ -68,6 +68,8 @@ const unsigned ttext::STYLE_BOLD = TTF_STYLE_BOLD;
|
|||
const unsigned ttext::STYLE_ITALIC = TTF_STYLE_ITALIC;
|
||||
const unsigned ttext::STYLE_UNDERLINE = TTF_STYLE_UNDERLINE;
|
||||
|
||||
static bool looks_like_url(const std::string & token);
|
||||
|
||||
std::string escape_text(const std::string& text)
|
||||
{
|
||||
std::string result;
|
||||
|
@ -99,6 +101,7 @@ ttext::ttext() :
|
|||
#endif
|
||||
text_(),
|
||||
markedup_text_(false),
|
||||
link_aware_(false),
|
||||
font_size_(14),
|
||||
font_style_(STYLE_NORMAL),
|
||||
foreground_color_(0xFFFFFFFF), // solid white
|
||||
|
@ -269,6 +272,53 @@ gui2::tpoint ttext::get_cursor_position(
|
|||
return gui2::tpoint(PANGO_PIXELS(rect.x), PANGO_PIXELS(rect.y));
|
||||
}
|
||||
|
||||
std::string ttext::get_token(const gui2::tpoint & position, const char * delim) const
|
||||
{
|
||||
recalculate();
|
||||
|
||||
// Get the index of the character.
|
||||
int index, trailing;
|
||||
if (!pango_layout_xy_to_index(layout_, position.x * PANGO_SCALE,
|
||||
position.y * PANGO_SCALE, &index, &trailing)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string txt = pango_layout_get_text(layout_);
|
||||
|
||||
std::string d(delim);
|
||||
|
||||
if (index < 0 || (static_cast<size_t>(index) >= txt.size()) || d.find(txt.at(index)) != std::string::npos) {
|
||||
return ""; // if the index is out of bounds, or the index character is a delimiter, return nothing
|
||||
}
|
||||
|
||||
size_t l = index;
|
||||
while (l > 0 && (d.find(txt.at(l-1)) == std::string::npos)) {
|
||||
--l;
|
||||
}
|
||||
|
||||
size_t r = index + 1;
|
||||
while (r < txt.size() && (d.find(txt.at(r)) == std::string::npos)) {
|
||||
++r;
|
||||
}
|
||||
|
||||
return txt.substr(l,r-l);
|
||||
}
|
||||
|
||||
std::string ttext::get_link(const gui2::tpoint & position) const
|
||||
{
|
||||
if (!link_aware_) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string tok = get_token(position, " \n\r\t");
|
||||
|
||||
if (looks_like_url(tok)) {
|
||||
return tok;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
gui2::tpoint ttext::get_column_line(const gui2::tpoint& position) const
|
||||
{
|
||||
recalculate();
|
||||
|
@ -477,6 +527,27 @@ ttext& ttext::set_maximum_length(const size_t maximum_length)
|
|||
return *this;
|
||||
}
|
||||
|
||||
ttext& ttext::set_link_aware(bool b)
|
||||
{
|
||||
if (link_aware_ != b) {
|
||||
calculation_dirty_ = true;
|
||||
surface_dirty_ = true;
|
||||
link_aware_ = b;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ttext& ttext::set_link_color(const std::string & color)
|
||||
{
|
||||
if(color != link_color_) {
|
||||
link_color_ = color;
|
||||
calculation_dirty_ = true;
|
||||
surface_dirty_ = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/** Small helper class to make sure the font object is destroyed properly. */
|
||||
|
@ -726,7 +797,47 @@ void ttext::create_surface_buffer(const size_t size) const
|
|||
memset(surface_buffer_, 0, size);
|
||||
}
|
||||
|
||||
bool ttext::set_markup(const std::string& text)
|
||||
bool ttext::set_markup(const std::string & text) {
|
||||
if (!link_aware_) {
|
||||
return set_markup_helper(text);
|
||||
} else {
|
||||
std::string delim = " \n\r\t";
|
||||
|
||||
// Tokenize according to these delimiters, and stream the results of `handle_token` on each token to get the new text.
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
int last_delim = -1;
|
||||
for (size_t index = 0; index < text.size(); ++index) {
|
||||
if (delim.find(text.at(index)) != std::string::npos) {
|
||||
ss << handle_token(text.substr(last_delim + 1, index - last_delim - 1)); // want to include chars from range since last token, dont want to include any delimiters
|
||||
ss << text.at(index);
|
||||
last_delim = index;
|
||||
}
|
||||
}
|
||||
if (last_delim < static_cast<int>(text.size()) - 1) {
|
||||
ss << handle_token(text.substr(last_delim + 1, text.size() - last_delim - 1));
|
||||
}
|
||||
|
||||
return set_markup_helper(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
static bool looks_like_url(const std::string & str)
|
||||
{
|
||||
return (str.size() >= 8) && ((str.substr(0,7) == "http://") || (str.substr(0,8) == "https://"));
|
||||
}
|
||||
|
||||
std::string ttext::handle_token(const std::string & token) const
|
||||
{
|
||||
if (looks_like_url(token)) {
|
||||
return "<span underline=\'single\' color=\'" + link_color_ + "\'>" + token + "</span>";
|
||||
} else {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
bool ttext::set_markup_helper(const std::string& text)
|
||||
{
|
||||
if(pango_parse_markup(text.c_str(), text.size()
|
||||
, 0, NULL, NULL, NULL, NULL)) {
|
||||
|
|
35
src/text.hpp
35
src/text.hpp
|
@ -162,6 +162,27 @@ public:
|
|||
gui2::tpoint get_cursor_position(
|
||||
const unsigned column, const unsigned line = 0) const;
|
||||
|
||||
/**
|
||||
* Gets the largest collection of characters, including the token at position,
|
||||
* and not including any characters from the delimiters set.
|
||||
*
|
||||
* @param position The pixel position in the text area.
|
||||
*
|
||||
* @returns The token containing position, and none of the
|
||||
* delimiter characters. If position is out of bounds,
|
||||
* it returns the empty string.
|
||||
*/
|
||||
std::string get_token(const gui2::tpoint & position, const char * delimiters = " \n\r\t") const;
|
||||
|
||||
/**
|
||||
* Checks if position points to a character in a link in the text, returns it
|
||||
* if so, empty string otherwise. Link-awareness must be enabled to get results.
|
||||
* @param position The pixel position in the text area.
|
||||
*
|
||||
* @returns The link if one is found, the empty string otherwise.
|
||||
*/
|
||||
std::string get_link(const gui2::tpoint & position) const;
|
||||
|
||||
/**
|
||||
* Gets the column of line of the character at the position.
|
||||
*
|
||||
|
@ -219,6 +240,11 @@ public:
|
|||
|
||||
ttext& set_maximum_length(const size_t maximum_length);
|
||||
|
||||
bool link_aware() const { return link_aware_; }
|
||||
|
||||
ttext& set_link_aware(bool b);
|
||||
|
||||
ttext& set_link_color(const std::string & color);
|
||||
private:
|
||||
|
||||
/***** ***** ***** ***** Pango variables ***** ***** ***** *****/
|
||||
|
@ -244,6 +270,12 @@ private:
|
|||
/** Is the text markedup if so the markedup render routines need to be used. */
|
||||
bool markedup_text_;
|
||||
|
||||
/** Are hyperlinks in the text marked-up, and will get_link return them. */
|
||||
bool link_aware_;
|
||||
|
||||
/** The color to render links in. */
|
||||
std::string link_color_;
|
||||
|
||||
/** The font size to draw. */
|
||||
unsigned font_size_;
|
||||
|
||||
|
@ -369,6 +401,9 @@ private:
|
|||
*/
|
||||
bool set_markup(const std::string& text);
|
||||
|
||||
bool set_markup_helper(const std::string & text);
|
||||
|
||||
std::string handle_token(const std::string & token) const;
|
||||
};
|
||||
|
||||
} // namespace font
|
||||
|
|
Loading…
Add table
Reference in a new issue