Code and comment cleanup.

This commit is contained in:
Mark de Wever 2008-08-16 11:15:03 +00:00
parent bda69a35ca
commit 72b02bfdd6
2 changed files with 427 additions and 354 deletions

View file

@ -52,291 +52,6 @@ static surface render_text(const std::string& text, unsigned font_size)
return font::get_rendered_text(text, font_size, col, TTF_STYLE_NORMAL);
}
//! Helper function for text more efficient as set_text.
//! Inserts a character at the cursor.
void ttext_box::insert_char(const Uint16 unicode)
{
delete_selection();
// Determine the width of the new character.
std::string tmp_text;
tmp_text.insert(tmp_text.begin(), unicode);
surface surf = render_text(tmp_text, config()->text_font_size);
assert(surf);
const unsigned width = surf->w;
// Insert the char in the buffer, we need to assume it's a wide string.
wide_string tmp = utils::string_to_wstring(text());
tmp.insert(tmp.begin() + sel_start(), unicode);
text() = utils::wstring_to_string(tmp);
// Update the widths.
character_offset_.insert(character_offset_.begin() + sel_start(), width);
if(sel_start() != 0) {
character_offset_[sel_start()] += character_offset_[sel_start() - 1];
}
++sel_start();
for(size_t i = sel_start(); i < character_offset_.size(); ++i) {
character_offset_[i] += width;
}
set_cursor(sel_start(), false);
set_canvas_text();
set_dirty();
}
//! Deletes the character.
//!
//! @param before_cursor If true it deletes the character before the cursor
//! (backspace) else the character after the cursor
//! (delete).
void ttext_box::delete_char(const bool before_cursor)
{
if(before_cursor) {
--sel_start();
set_cursor(sel_start(), false);
}
sel_len() = 1;
delete_selection();
}
//! Deletes the current selection.
void ttext_box::delete_selection()
{
if(sel_len() == 0) {
return;
}
// If we have a negative range change it to a positive range.
// This makes the rest of the algoritms easier.
int len = sel_len();
unsigned start = sel_start();
if(len < 0) {
len = - len;
start -= len;
}
// Update the text, we need to assume it's a wide string.
wide_string tmp = utils::string_to_wstring(text());
tmp.erase(tmp.begin() + start, tmp.begin() + start + len);
const std::string& text = utils::wstring_to_string(tmp);
set_value(text);
set_cursor(start, false);
}
//! Inherited from tcontrol.
void ttext_box::set_canvas_text()
{
foreach(tcanvas& tmp, canvas()) {
// NOTE when sel_start() == - sel_len() then the offset calculation will
// access character_offset_[-1] so add special cases to use 0 instead.
// The same can happen if sel_start() == 0.
// Set the general variables.
tmp.set_variable("text", variant(text()));
tmp.set_variable("text_x_offset", variant(text_x_offset_));
tmp.set_variable("text_y_offset", variant(text_y_offset_));
// Set the cursor info.
const unsigned start = sel_start();
const int len = sel_len();
if(text().empty() || start + len == 0) {
tmp.set_variable("cursor_offset", variant(0));
} else {
tmp.set_variable("cursor_offset", variant(character_offset_[start - 1 + len]));
}
// Set the seleciton info
unsigned start_offset = 0;
unsigned end_offset = 0;
if(len == 0) {
// No nothing.
} else if(len > 0) {
start_offset = start == 0 ? 0 :character_offset_[start - 1];
end_offset = character_offset_[start - 1 + len];
} else {
start_offset =
(start + len == 0) ? 0 : character_offset_[start - 1 + len];
end_offset = character_offset_[start - 1];
}
tmp.set_variable("selection_offset", variant(start_offset));
tmp.set_variable("selection_width", variant(end_offset - start_offset ));
}
}
void ttext_box::set_size(const SDL_Rect& rect)
{
// Inherited.
tcontrol::set_size(rect);
update_offsets();
}
//! Handles the selection in a mouse down or mouse move event.
void ttext_box::handle_mouse_selection(
tevent_handler& event, const bool start_selection)
{
tpoint mouse = event.get_mouse();
mouse.x -= get_x();
mouse.y -= get_y();
// FIXME we dont test for overflow in width
if(mouse.x < static_cast<int>(text_x_offset_) ||
mouse.y < static_cast<int>(text_y_offset_) ||
mouse.y >= static_cast<int>(text_y_offset_ + text_height_)) {
return;
}
int offset = get_character_offset_at(mouse.x - static_cast<int>(text_x_offset_));
if(offset < 0) {
return;
}
set_cursor(offset, !start_selection);
set_canvas_text();
set_dirty();
dragging_ |= start_selection;
}
void ttext_box::mouse_left_button_down(tevent_handler& event)
{
// Inherit.
ttext_::mouse_left_button_down(event);
DBG_G_E << "Text box: left mouse down.\n";
handle_mouse_selection(event, true);
}
//! Inherited from twidget.
void ttext_box::mouse_move(tevent_handler& event)
{
DBG_G_E << "Text box: mouse move.\n";
if(!dragging_) {
return;
}
handle_mouse_selection(event, false);
}
//! Inherited from twidget.
void ttext_box::mouse_left_button_up(tevent_handler& /*event*/)
{
DBG_G_E << "Text box: left mouse up.\n";
dragging_ = false;
}
//! Inherited from twidget.
void ttext_box::mouse_left_button_double_click(tevent_handler&)
{
DBG_G_E << "Text box: left mouse double click.\n";
select_all();
}
//! Calculates the offsets of all chars.
void ttext_box::calculate_char_offset()
{
assert(config());
character_offset_.clear();
std::string rendered_text;
const unsigned font_size = config()->text_font_size;
foreach(const wchar_t& unicode, utils::string_to_wstring(text())) {
rendered_text.insert(rendered_text.end(), unicode);
surface surf = render_text(rendered_text, font_size);
assert(surf);
character_offset_.push_back(surf->w);
}
}
//! Gets the character at the wanted offset, everything beyond will
//! select the last character.
unsigned ttext_box::get_character_offset_at(const unsigned offset)
{
unsigned result = 0;
foreach(unsigned off, character_offset_) {
if(offset < off) {
return result;
}
++result;
}
return text().size();
}
void ttext_box::handle_key_clear_line(SDLMod /*modifier*/, bool& handled)
{
handled = true;
set_value("");
}
void ttext_box::handle_key_up_arrow(SDLMod /*modifier*/, bool& handled)
{
if (history_.get_enabled()) {
std::string s = history_.up(text());
if (!s.empty()) {
set_value(s);
}
handled = true;
}
}
void ttext_box::handle_key_down_arrow(SDLMod /*modifier*/, bool& handled)
{
if (history_.get_enabled()) {
set_value(history_.down(text()));
handled = true;
}
}
//! Inherited from tcontrol.
void ttext_box::load_config_extra()
{
update_offsets();
}
// Updates text_x_offset_ and text_x_offset_.
void ttext_box::update_offsets()
{
assert(config());
boost::intrusive_ptr<const ttext_box_definition::tresolution> conf =
boost::dynamic_pointer_cast<const ttext_box_definition::tresolution>(config());
assert(conf);
text_height_ = font::get_max_height(conf->text_font_size);
game_logic::map_formula_callable variables;
variables.add("height", variant(get_height()));
variables.add("width", variant(get_width()));
variables.add("text_font_height", variant(text_height_));
text_x_offset_ = conf->text_x_offset(variables);
text_y_offset_ = conf->text_y_offset(variables);
// Since this variable doesn't change set it here instead of in
// set_canvas_text().
foreach(tcanvas& tmp, canvas()) {
tmp.set_variable("text_font_height", variant(text_height_));
}
// Force an update of the canvas since now text_font_height is known.
set_canvas_text();
}
ttext_history ttext_history::get_history(const std::string& id, const bool enabled)
{
std::vector<std::string>* vec = preferences::get_history(id);
@ -374,7 +89,6 @@ std::string ttext_history::up(const std::string& text)
return get_value();
}
// Will push text to history if it is pointing at the end of the vector.
std::string ttext_history::down(const std::string& text)
{
if (!enabled_) {
@ -397,6 +111,272 @@ std::string ttext_history::get_value() const
}
}
void ttext_box::set_size(const SDL_Rect& rect)
{
// Inherited.
tcontrol::set_size(rect);
update_offsets();
}
void ttext_box::set_canvas_text()
{
foreach(tcanvas& tmp, canvas()) {
// NOTE when sel_start() == - sel_len() then the offset calculation will
// access character_offset_[-1] so add special cases to use 0 instead.
// The same can happen if sel_start() == 0.
// Set the general variables.
tmp.set_variable("text", variant(text()));
tmp.set_variable("text_x_offset", variant(text_x_offset_));
tmp.set_variable("text_y_offset", variant(text_y_offset_));
// Set the cursor info.
const unsigned start = sel_start();
const int len = sel_len();
if(text().empty() || start + len == 0) {
tmp.set_variable("cursor_offset", variant(0));
} else {
tmp.set_variable("cursor_offset",
variant(character_offset_[start - 1 + len]));
}
// Set the seleciton info
unsigned start_offset = 0;
unsigned end_offset = 0;
if(len == 0) {
// No nothing.
} else if(len > 0) {
start_offset = start == 0 ? 0 :character_offset_[start - 1];
end_offset = character_offset_[start - 1 + len];
} else {
start_offset =
(start + len == 0) ? 0 : character_offset_[start - 1 + len];
end_offset = character_offset_[start - 1];
}
tmp.set_variable("selection_offset", variant(start_offset));
tmp.set_variable("selection_width", variant(end_offset - start_offset ));
}
}
void ttext_box::mouse_move(tevent_handler& event)
{
DBG_G_E << "Text box: mouse move.\n";
if(!dragging_) {
return;
}
handle_mouse_selection(event, false);
}
void ttext_box::mouse_left_button_down(tevent_handler& event)
{
// Inherited.
ttext_::mouse_left_button_down(event);
DBG_G_E << "Text box: left mouse down.\n";
handle_mouse_selection(event, true);
}
void ttext_box::mouse_left_button_up(tevent_handler& /*event*/)
{
DBG_G_E << "Text box: left mouse up.\n";
dragging_ = false;
}
void ttext_box::mouse_left_button_double_click(tevent_handler&)
{
DBG_G_E << "Text box: left mouse double click.\n";
select_all();
}
void ttext_box::insert_char(const Uint16 unicode)
{
delete_selection();
// Determine the width of the new character.
std::string tmp_text;
tmp_text.insert(tmp_text.begin(), unicode);
surface surf = render_text(tmp_text, config()->text_font_size);
assert(surf);
const unsigned width = surf->w;
// Insert the char in the buffer, we need to assume it's a wide string.
wide_string tmp = utils::string_to_wstring(text());
tmp.insert(tmp.begin() + sel_start(), unicode);
text() = utils::wstring_to_string(tmp);
// Update the widths.
character_offset_.insert(character_offset_.begin() + sel_start(), width);
if(sel_start() != 0) {
character_offset_[sel_start()] += character_offset_[sel_start() - 1];
}
++sel_start();
for(size_t i = sel_start(); i < character_offset_.size(); ++i) {
character_offset_[i] += width;
}
set_cursor(sel_start(), false);
set_canvas_text();
set_dirty();
}
void ttext_box::delete_char(const bool before_cursor)
{
if(before_cursor) {
--sel_start();
set_cursor(sel_start(), false);
}
sel_len() = 1;
delete_selection();
}
void ttext_box::delete_selection()
{
if(sel_len() == 0) {
return;
}
// If we have a negative range change it to a positive range.
// This makes the rest of the algoritms easier.
int len = sel_len();
unsigned start = sel_start();
if(len < 0) {
len = - len;
start -= len;
}
// Update the text, we need to assume it's a wide string.
wide_string tmp = utils::string_to_wstring(text());
tmp.erase(tmp.begin() + start, tmp.begin() + start + len);
const std::string& text = utils::wstring_to_string(tmp);
set_value(text);
set_cursor(start, false);
}
void ttext_box::handle_mouse_selection(
tevent_handler& event, const bool start_selection)
{
tpoint mouse = event.get_mouse();
mouse.x -= get_x();
mouse.y -= get_y();
// FIXME we dont test for overflow in width
if(mouse.x < static_cast<int>(text_x_offset_) ||
mouse.y < static_cast<int>(text_y_offset_) ||
mouse.y >= static_cast<int>(text_y_offset_ + text_height_)) {
return;
}
int offset = get_character_offset_at(mouse.x - static_cast<int>(text_x_offset_));
if(offset < 0) {
return;
}
set_cursor(offset, !start_selection);
set_canvas_text();
set_dirty();
dragging_ |= start_selection;
}
unsigned ttext_box::get_character_offset_at(const unsigned offset)
{
unsigned result = 0;
foreach(unsigned off, character_offset_) {
if(offset < off) {
return result;
}
++result;
}
return text().size();
}
void ttext_box::update_offsets()
{
assert(config());
boost::intrusive_ptr<const ttext_box_definition::tresolution> conf =
boost::dynamic_pointer_cast<const ttext_box_definition::tresolution>(config());
assert(conf);
text_height_ = font::get_max_height(conf->text_font_size);
game_logic::map_formula_callable variables;
variables.add("height", variant(get_height()));
variables.add("width", variant(get_width()));
variables.add("text_font_height", variant(text_height_));
text_x_offset_ = conf->text_x_offset(variables);
text_y_offset_ = conf->text_y_offset(variables);
// Since this variable doesn't change set it here instead of in
// set_canvas_text().
foreach(tcanvas& tmp, canvas()) {
tmp.set_variable("text_font_height", variant(text_height_));
}
// Force an update of the canvas since now text_font_height is known.
set_canvas_text();
}
void ttext_box::calculate_char_offset()
{
assert(config());
character_offset_.clear();
std::string rendered_text;
const unsigned font_size = config()->text_font_size;
foreach(const wchar_t& unicode, utils::string_to_wstring(text())) {
rendered_text.insert(rendered_text.end(), unicode);
surface surf = render_text(rendered_text, font_size);
assert(surf);
character_offset_.push_back(surf->w);
}
}
void ttext_box::handle_key_up_arrow(SDLMod /*modifier*/, bool& handled)
{
if (history_.get_enabled()) {
std::string s = history_.up(text());
if (!s.empty()) {
set_value(s);
}
handled = true;
}
}
void ttext_box::handle_key_down_arrow(SDLMod /*modifier*/, bool& handled)
{
if (history_.get_enabled()) {
set_value(history_.down(text()));
handled = true;
}
}
void ttext_box::handle_key_clear_line(SDLMod /*modifier*/, bool& handled)
{
handled = true;
set_value("");
}
void ttext_box::load_config_extra()
{
update_offsets();
}
} //namespace gui2

View file

@ -17,17 +17,28 @@
#include "gui/widgets/text.hpp"
namespace gui2 {
//! Class for text input history
/**
* Class for text input history.
*
* The history of text items can be stored in the preferences. This class
* handles that. Every item needs an id by which the history is loaded and
* saved.
*/
class ttext_history
{
public:
//! Gets history that matches id and enables or disables it.
/**
* Gets history that matches id.
*
* @param id The id of the history to look for.
* @param enabled The enabled state of the history.
*
* @returns The history object.
*/
static ttext_history get_history(const std::string& id, const bool enabled);
// Defaults to a disabled history
ttext_history() :
history_(0),
pos_(0),
@ -35,18 +46,49 @@ public:
{
}
//! Push string into the history if it is non-empty and is not the same as the last item
//! updates position to end of history.
/**
* Push string into the history.
*
* If the string is empty or the same as the last item in the history this
* function is a nop.
*
* @param text The text to push in the history.
*/
void push(const std::string& text);
//! One step up/down in history. Pushes text to the history if at the end.
/**
* One step up in the history.
*
* Pushes text to the history if at the end.
*
* @param text The text to push in the history.
*
* @returns The current value of the history.
*/
std::string up(const std::string& text = "");
/**
* One step down in the history.
*
* Pushes text to the history if at the end.
*
* @param text The text to push in the history.
*
* @returns The current value of the history.
*/
std::string down(const std::string& text = "");
//! Returns the value at the current history position. Returns "" if not enabled
//! or if at the end of the history.
/**
* Gets the current history value.
*
* @returns If enabled return the current history
* position, otherwise an empty string is
* returned.
*/
std::string get_value() const;
/***** ***** ***** setters / getters for members ***** ****** *****/
void set_enabled(bool enabled = true) { enabled_ = enabled; }
bool get_enabled() const { return enabled_; }
@ -57,18 +99,20 @@ private:
enabled_(enabled)
{}
/** The items in the history. */
std::vector<std::string>* history_;
/** The current position in the history. */
unsigned pos_;
/** Is the history enabled. */
bool enabled_;
};
//! Class for a single line text area.
/** Class for a single line text area. */
class ttext_box : public ttext_
{
public:
ttext_box() :
ttext_(),
character_offset_(),
@ -81,75 +125,134 @@ public:
set_wants_mouse_left_double_click();
}
/** Saves the text in the widget to the history. */
void save_to_history() { history_.push(get_text()); }
/***** ***** ***** setters / getters for members ***** ****** *****/
void set_history(const std::string& id)
{ history_ = ttext_history::get_history(id, true); }
void save_to_history() { history_.push(text()); }
void save_to_history(const std::string& text) { history_.push(text); }
protected:
// Gets the character position at the wanted place
// as if the mouse would click there.
// virtual unsigned get_position_at(tpoint& coordinate);
// void delete_selection();
// void copy();
// void paste();
//
//! Inherited from ttext_.
void insert_char(const Uint16 unicode);
//! Inherited from ttext_.
void delete_char(const bool before_cursor);
//! Inherited from ttext_.
void delete_selection();
//! Inherited from tcontrol.
void set_canvas_text();
//! Inherited from tcontrol..
/** Inherited from tcontrol. */
void set_size(const SDL_Rect& rect);
void goto_end_of_line(const bool select = false) { goto_end_of_data(select); }
void goto_start_of_line(const bool select = false) { goto_start_of_data(select); }
/** Inherited from tcontrol. */
void set_canvas_text();
//! Handles the selection in a mouse down or mouse move event.
void handle_mouse_selection(tevent_handler& event, const bool start_selection);
/** Inherited from ttext_. */
void mouse_move(tevent_handler& event);
/** Inherited from ttext_. */
void mouse_left_button_down(tevent_handler& event);
//! Inherited from twidget.
void mouse_move(tevent_handler& event);
//! Inherited from twidget.
/** Inherited from ttext_. */
void mouse_left_button_up(tevent_handler&);
//! Inherited from twidget.
/** Inherited from ttext_. */
void mouse_left_button_double_click(tevent_handler&);
/** Inherited from ttext_. */
void goto_end_of_line(const bool select = false)
{ goto_end_of_data(select); }
/** Inherited from ttext_. */
void goto_start_of_line(const bool select = false)
{ goto_start_of_data(select); }
/** Inherited from ttext_. */
void insert_char(const Uint16 unicode);
/** Inherited from ttext_. */
void delete_char(const bool before_cursor);
/** Inherited from ttext_. */
void delete_selection();
/** Handles the selection in a mouse down or mouse move event. */
void handle_mouse_selection(
tevent_handler& event, const bool start_selection);
private:
void handle_key_up_arrow(SDLMod modifier, bool& handled);
void handle_key_down_arrow(SDLMod modifier, bool& handled);
// Clears the current line
void handle_key_clear_line(SDLMod modifier, bool& handled);
//! Contains the end offset of each character in the text area.
/**
* Contains the end offset of each character in the text area.
*
* This is used for placing the cursor at the proper offset and determine
* the offset for a mouse click.
*/
std::vector<unsigned> character_offset_;
//! Inherited from ttext_.
void calculate_char_offset();
//! Gets the character at the wanted offset, everything beyond will
//! select the last character.
/**
* Gets the character at the wanted offset.
*
* If the click is beyond the text, the last character will be selected.
*
* @param offset The offset in the widget to test.
*
* @returns The character offset where the click occured.
*/
unsigned get_character_offset_at(const unsigned offset);
/** The history text for this widget. */
ttext_history history_;
/**
* The x offset in the widget where the text starts.
*
* This value is needed for get_character_offset_at()
*/
unsigned text_x_offset_;
/**
* The y offset in the widget where the text starts.
*
* Needed to determine whether a click is on the text.
*/
unsigned text_y_offset_;
/**
* The height of the text itself.
*
* Needed to determine whether a click is on the text.
*/
unsigned text_height_;
/** Updates text_x_offset_ and text_y_offset_. */
void update_offsets();
/** Is the mouse in dragging mode, this affects selection in mouse move */
bool dragging_;
/** Inherited from ttext_. */
void calculate_char_offset();
/**
* Inherited from ttext_.
*
* Unmodified If there is a history, goes one item up in the
* history, otherwise ignored.
* Control Ignored.
* Shift Ignored.
* Alt Ignored.
*/
void handle_key_up_arrow(SDLMod modifier, bool& handled);
/**
* Inherited from ttext_.
*
* Unmodified If there is a history, goes one item down in the
* history, otherwise ignored.
* Control Ignored.
* Shift Ignored.
* Alt Ignored.
*/
void handle_key_down_arrow(SDLMod modifier, bool& handled);
/** Inherited from ttext_. */
void handle_key_clear_line(SDLMod modifier, bool& handled);
//! Inherited from tcontrol.
const std::string& get_control_type() const
{ static const std::string type = "text_box"; return type; }
@ -157,18 +260,8 @@ private:
//! Inherited from tcontrol.
void load_config_extra();
unsigned text_x_offset_;
unsigned text_y_offset_;
unsigned text_height_;
// Updates text_x_offset_ and text_x_offset_.
void update_offsets();
bool dragging_;
};
} //namespace gui2
#endif