insert paragraph breaks correctly

This commit is contained in:
Subhraman Sarkar 2024-08-07 12:55:20 +05:30 committed by Celtic Minstrel
parent b1fc4701aa
commit ce9d3bdc38
4 changed files with 39 additions and 26 deletions

View file

@ -197,7 +197,7 @@ When you win a scenario, the map grays over and the <bold>text='End Turn'</bold>
[topic]
id=recruit_and_recall
title= _ "Recruiting and Recalling"
text="<img>src=help/recruit.png align=left float=yes</img>" + _ "Each side begins with one leader in their keep. At the start of any battle, and at times during it, you will need to recruit <ref>dst='..units' text='units'</ref> into your army. To recruit, you must have your leader (for instance, Konrad in the <italic>text='Heir to the Throne'</italic> campaign) on the keep hex of a <ref>dst='..terrain_castle' text='castle'</ref>. Then you may recruit by either choosing <bold>text='Recruit'</bold> from the menu or right-clicking on a hex and selecting <bold>text='Recruit'</bold>. This brings up the recruit menu, which lists units available for recruitment, along with their gold cost. Click on a unit to see its statistics, then press the <bold>text='Recruit'</bold> button to recruit it." + _ "
text="<img>src=help/recruit.png align=right float=yes</img>" + _ "Each side begins with one leader in their keep. At the start of any battle, and at times during it, you will need to recruit <ref>dst='..units' text='units'</ref> into your army. To recruit, you must have your leader (for instance, Konrad in the <italic>text='Heir to the Throne'</italic> campaign) on the keep hex of a <ref>dst='..terrain_castle' text='castle'</ref>. Then you may recruit by either choosing <bold>text='Recruit'</bold> from the menu or right-clicking on a hex and selecting <bold>text='Recruit'</bold>. This brings up the recruit menu, which lists units available for recruitment, along with their gold cost. Click on a unit to see its statistics, then press the <bold>text='Recruit'</bold> button to recruit it." + _ "
If you right-clicked on a castle hex and selected recruit, the new unit will appear in that hex. Otherwise, it will appear in a free hex near the keep. You may only recruit as many units as you have free hexes in your castle, and you cannot spend more gold than you actually have on recruiting." + _ "
@ -261,7 +261,7 @@ While most units have three levels, not all do. Occasional units (such as <ref>d
[topic]
id=movement
title= _ "Movement"
text="<img>src=help/moving1.png align=left float=yes</img>" + "<img>src=help/moving2.png align=left float=yes</img>" + _ "Movement in <italic>text='Battle for Wesnoth'</italic> is simple. Click on the unit you wish to move to select it, then click on the hex you wish to move it to. When a unit is selected, everywhere it can move this turn will be highlighted, and all other hexes on the map are made dull. Mousing over a highlighted hex shows the defense rating the unit would have if you moved it to that hex. Mousing over a dull hex will also show the number of turns required to reach it, and clicking will cause the unit to move towards it by the fastest route over this and subsequent turns. If you dont use up all of a units movement when you first move a unit, you may move it again. This is useful when having two units switch places. Attacking with a unit will use up its movement. Ending a move in a village you dont already own will also use up a units movement, but will still allow it to attack." + _ "
text="<img>src=help/moving1.png align=right float=yes</img>" + "<img>src=help/moving2.png align=right float=yes</img>" + _ "Movement in <italic>text='Battle for Wesnoth'</italic> is simple. Click on the unit you wish to move to select it, then click on the hex you wish to move it to. When a unit is selected, everywhere it can move this turn will be highlighted, and all other hexes on the map are made dull. Mousing over a highlighted hex shows the defense rating the unit would have if you moved it to that hex. Mousing over a dull hex will also show the number of turns required to reach it, and clicking will cause the unit to move towards it by the fastest route over this and subsequent turns. If you dont use up all of a units movement when you first move a unit, you may move it again. This is useful when having two units switch places. Attacking with a unit will use up its movement. Ending a move in a village you dont already own will also use up a units movement, but will still allow it to attack." + _ "
Each unit has a certain number of movement points which are used up when moving into a new hex, depending on the Terrain of that particular hex. For instance, grassland nearly always costs 1 movement point to enter. Exactly how many movement points are spent entering a hex depends on the unit type — in forest, elvish units only spend 1 movement point, most human and orc units spend 2, while horsemen spend 3. You can learn how many movement points a unit requires to enter a certain terrain type by right-clicking on it, selecting <bold>text='Unit Description'</bold>, and then looking at <bold>text='Terrain Modifiers'</bold>." + _ "
@ -352,7 +352,7 @@ The “Damage Calculations” dialog shows some statistics that can help determi
[topic]
id=combat
title= _ "Combat"
text= "<img>src=help/combat1.png align=left float=yes</img>" + _ "Combat in <italic>text='Battle for Wesnoth'</italic> always takes place between units in adjacent hexes. Click on your unit, and click on the enemy you want to attack: your unit will move towards the enemy unit, and when they are next to each other, combat will begin. The attacker and defender alternate strikes until each has used their allotted number of strikes. The attacker chooses one of its weapons to attack with, and the defender retaliates with one of its attacks of the same type. There are two types of attacks: <italic>text='melee'</italic>, which usually involves weapons such as swords, axes or fangs; and <italic>text='ranged'</italic>, which usually involves weapons such as bows, spears and fireballs." + _ "
text= "<img>src=help/combat1.png align=right float=yes</img>" + _ "Combat in <italic>text='Battle for Wesnoth'</italic> always takes place between units in adjacent hexes. Click on your unit, and click on the enemy you want to attack: your unit will move towards the enemy unit, and when they are next to each other, combat will begin. The attacker and defender alternate strikes until each has used their allotted number of strikes. The attacker chooses one of its weapons to attack with, and the defender retaliates with one of its attacks of the same type. There are two types of attacks: <italic>text='melee'</italic>, which usually involves weapons such as swords, axes or fangs; and <italic>text='ranged'</italic>, which usually involves weapons such as bows, spears and fireballs." + _ "
<header>text='Order and Number of Strikes'</header>" + _ "

View file

@ -40,7 +40,7 @@
static lg::log_domain log_rich_label("gui/widget/rich_label");
#define DBG_GUI_RL LOG_STREAM(debug, log_rich_label)
#define DEBUG_LINES false
#define DEBUG_LINES true
namespace gui2
{
@ -296,7 +296,7 @@ size_t rich_label::get_split_location(std::string text, const point& pos) {
void rich_label::set_topic(const help::topic* topic)
{
set_parsed_text(topic->text.parsed_text());
text_dom_ = get_parsed_text(topic->text.parsed_text());
}
void rich_label::set_label(const t_string& text)
@ -304,21 +304,22 @@ void rich_label::set_label(const t_string& text)
unparsed_text_ = text;
help::topic_text marked_up_text(text);
const config& parsed_text = marked_up_text.parsed_text();
set_parsed_text(parsed_text);
text_dom_ = get_parsed_text(parsed_text);
}
void rich_label::set_parsed_text(const config& parsed_text)
config rich_label::get_parsed_text(const config& parsed_text)
{
// Initialization
w_ = (w_ == 0) ? styled_widget::calculate_best_size().x : w_;
DBG_GUI_RL << "Width: " << w_;
x_ = 0;
h_ = 0;
text_dom_.clear();
config text_dom;
links_.clear();
config* curr_item = nullptr;
bool is_text = false;
bool is_image = false;
bool is_float = false;
bool wrap_mode = false;
@ -357,18 +358,19 @@ void rich_label::set_parsed_text(const config& parsed_text)
}
DBG_GUI_RL << "floating: " << wrap_mode << ", " << is_float;
curr_item = &(text_dom_.add_child("image"));
curr_item = &(text_dom.add_child("image"));
add_image(*curr_item, name, align, is_image, is_float, is_curr_float, img_size, float_size);
DBG_GUI_RL << "image: src=" << name << ", size=" << get_image_size(*curr_item);
is_image = true;
is_float = is_curr_float;
is_text = false;
new_text_block = true;
} else if(tag.key == "table") {
if (curr_item == nullptr) {
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
new_text_block = false;
}
@ -395,7 +397,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
// DEBUG: debug lines for table
#if DEBUG_LINES
config& link_rect_cfg = text_dom_.add_child("line");
config& link_rect_cfg = text_dom.add_child("line");
link_rect_cfg["x1"] = 0;
link_rect_cfg["y1"] = prev_blk_height_;
link_rect_cfg["x2"] = w_;
@ -403,6 +405,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
link_rect_cfg["color"] = "255, 0, 0, 255";
#endif
is_text = false;
new_text_block = true;
is_image = false;
@ -411,7 +414,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
} else if(tag.key == "jump") {
if (curr_item == nullptr) {
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
new_text_block = false;
}
@ -437,9 +440,11 @@ void rich_label::set_parsed_text(const config& parsed_text)
is_image = false;
}
is_text = false;
} else if(tag.key == "break" || tag.key == "br") {
if (curr_item == nullptr) {
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
new_text_block = false;
}
@ -462,7 +467,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
// DEBUG: debug lines for table
#if DEBUG_LINES
config& link_rect_cfg = text_dom_.add_child("line");
config& link_rect_cfg = text_dom.add_child("line");
link_rect_cfg["x1"] = 0;
link_rect_cfg["y1"] = prev_blk_height_;
link_rect_cfg["x2"] = w_;
@ -483,10 +488,11 @@ void rich_label::set_parsed_text(const config& parsed_text)
if (!is_image) {
new_text_block = true;
}
is_text = false;
} else if(tag.key == "endtable") {
if (curr_item == nullptr) {
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
new_text_block = false;
}
@ -495,6 +501,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
col_width = 0;
in_table = false;
is_image = false;
is_text = false;
row_y = 0;
} else {
@ -517,7 +524,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
txt_height_ = 0;
}
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
new_text_block = false;
}
@ -525,6 +532,11 @@ void rich_label::set_parsed_text(const config& parsed_text)
// }---------- TEXT TAGS -----------{
int tmp_h = get_text_size(*curr_item, w_ - (x_ == 0 ? float_size.x : x_)).y;
if (is_text && tag.key == "text") {
add_text_with_attribute(*curr_item, "\n\n");
}
is_text = false;
if(tag.key == "ref") {
add_link(*curr_item, line, child["dst"], float_size.x);
@ -560,16 +572,13 @@ void rich_label::set_parsed_text(const config& parsed_text)
append_if_not_empty(&((*curr_item)["attr_end"]), ",");
append_if_not_empty(&((*curr_item)["attr_data"]), ",");
std::stringstream header_text;
// Header starts in a new line
header_text << "\n" + line + "\n";
std::vector<std::string> attrs = {"face", "color", "size"};
std::vector<std::string> attr_data;
attr_data.push_back("serif");
attr_data.push_back(font::string_to_color("white").to_hex_string());
attr_data.push_back(std::to_string(font::SIZE_TITLE - 2));
add_text_with_attributes((*curr_item), header_text.str(), attrs, attr_data);
add_text_with_attributes((*curr_item), line, attrs, attr_data);
is_image = false;
@ -609,6 +618,8 @@ void rich_label::set_parsed_text(const config& parsed_text)
point text_size = get_text_size(*curr_item, w_ - (x_ == 0 ? float_size.x : x_));
text_size.x -= x_;
is_text = true;
if (wrap_mode && (float_size.y > 0) && (text_size.y > float_size.y)) {
DBG_GUI_RL << "wrap start";
@ -636,7 +647,7 @@ void rich_label::set_parsed_text(const config& parsed_text)
wrap_mode = false;
// rest of the text
curr_item = &(text_dom_.add_child("text"));
curr_item = &(text_dom.add_child("text"));
default_text_config(curr_item);
tmp_h = get_text_size(*curr_item, w_).y;
add_text_with_attribute(*curr_item, *removed_part);
@ -684,17 +695,17 @@ void rich_label::set_parsed_text(const config& parsed_text)
}
// reset all canvas variables to zero, otherwise they grow infinitely
config& break_cfg = text_dom_.add_child("text");
config& break_cfg = text_dom.add_child("text");
default_text_config(&break_cfg, " ");
break_cfg["actions"] = "([set_var('pos_x', 0), set_var('pos_y', 0), set_var('img_x', 0), set_var('img_y', 0), set_var('ww', 0), set_var('tw', 0)])";
DBG_GUI_RL << text_dom_.debug();
DBG_GUI_RL << text_dom.debug();
DBG_GUI_RL << "Height: " << h_;
// DEBUG: draw boxes around links
#if DEBUG_LINES
for (const auto& entry : links_) {
config& link_rect_cfg = text_dom_.add_child("rectangle");
config& link_rect_cfg = text_dom.add_child("rectangle");
link_rect_cfg["x"] = entry.first.x;
link_rect_cfg["y"] = entry.first.y;
link_rect_cfg["w"] = entry.first.w;
@ -703,6 +714,8 @@ void rich_label::set_parsed_text(const config& parsed_text)
link_rect_cfg["border_color"] = "255, 180, 0, 255";
}
#endif
return text_dom;
} // function ends
void rich_label::default_text_config(config* txt_ptr, t_string text) {

View file

@ -127,7 +127,7 @@ public:
void set_topic(const help::topic* topic);
// Show a help config
void set_parsed_text(const config& parsed_text);
config get_parsed_text(const config& parsed_text);
// Attaches a callback function that will be called when a link is clicked
void register_link_callback(std::function<void(std::string)> link_handler)

View file

@ -185,7 +185,7 @@ std::string terrain_topic_generator::operator()() const {
}
if(!special_notes.empty()) {
ss << "\n\n" << _("<header>Special Notes</header>") << "\n";
ss << "\n\n" << _("<header>Special Notes</header>") << "\n\n";
for(const auto& note : special_notes) {
ss << font::unicode_bullet << " " << note << '\n';
}