Let the text widget use a font text object.

With this change a lot of helper code can be moved to pango. This is
also required since the text size between pango and the old SDL_TTF
library might differ. Also fixes some crashing bugs when special
characters were used in the text boxes.
This commit is contained in:
Mark de Wever 2008-08-27 16:43:54 +00:00
parent bbede1d7f6
commit 5c1fe9bec3
4 changed files with 65 additions and 155 deletions

View file

@ -67,7 +67,7 @@ void ttext_::mouse_left_button_double_click(tevent_handler&)
DBG_G_E << "Text: left mouse button double click.\n";
selection_start_ = 0;
selection_length_ = text_.size();
selection_length_ = text_.get_length();
}
@ -206,12 +206,11 @@ void ttext_::key_press(tevent_handler& /*event*/,
void ttext_::set_value(const std::string& text)
{
if(text != text_) {
text_ = text;
calculate_char_offset();
if(text != text_.text()) {
text_.set_text(text, false);
// default to put the cursor at the end of the buffer.
selection_start_ = text_.size();
selection_start_ = text_.get_length();
selection_length_ = 0;
set_canvas_text();
set_dirty();
@ -236,7 +235,7 @@ void ttext_::set_cursor(const size_t offset, const bool select)
set_dirty();
} else {
assert(offset <= text_.size());
assert(offset <= text_.get_length());
selection_start_ = offset;
selection_length_ = 0;
@ -245,6 +244,18 @@ void ttext_::set_cursor(const size_t offset, const bool select)
}
}
void ttext_::insert_char(const Uint16 unicode)
{
delete_selection();
text_.insert_unicode(selection_start_, unicode);
// Update status
set_cursor(selection_start_ + 1, false);
set_canvas_text();
set_dirty();
}
void ttext_::copy_selection(const bool mouse)
{
int length = selection_length_;
@ -255,7 +266,7 @@ void ttext_::copy_selection(const bool mouse)
start -= length;
}
const wide_string& wtext = utils::string_to_wstring(text_);
const wide_string& wtext = utils::string_to_wstring(text_.text());
const std::string& text = utils::wstring_to_string(
wide_string(wtext.begin() + start, wtext.begin() + start + length));
@ -271,11 +282,8 @@ void ttext_::paste_selection(const bool mouse)
delete_selection();
text_.insert(selection_start_, text);
selection_start_ += text_.insert_text(selection_start_, text);
selection_start_ += utils::string_to_wstring(text).size();
calculate_char_offset();
set_canvas_text();
set_dirty();
}
@ -323,7 +331,7 @@ void ttext_::handle_key_right_arrow(SDLMod modifier, bool& handled)
handled = true;
const int offset = selection_start_ + 1 + selection_length_;
if(offset <= text_.size()) {
if(offset <= text_.get_length()) {
set_cursor(offset, modifier & KMOD_SHIFT);
}
}
@ -369,7 +377,7 @@ void ttext_::handle_key_delete(SDLMod /*modifier*/, bool& handled)
handled = true;
if(selection_length_ != 0) {
delete_selection();
} else if (selection_start_ < text_.size()) {
} else if (selection_start_ < text_.get_length()) {
delete_char(false);
}
}

View file

@ -16,6 +16,7 @@
#define GUI_WIDGETS_TEXT_HPP_INCLUDED
#include "gui/widgets/control.hpp"
#include "../../text.hpp"
#include <string>
@ -72,9 +73,9 @@ public:
/***** ***** ***** setters / getters for members ***** ****** *****/
void set_value(const std::string& text);
std::string get_value() const { return text_; }
std::string get_value() const { return text_.text(); }
const std::string& text() const { return text_; }
const std::string& text() const { return text_.text(); }
protected:
@ -95,10 +96,10 @@ protected:
* position till the end of the data?
*/
void goto_end_of_data(const bool select = false)
{ set_cursor(text_.size(), select); }
{ set_cursor(text_.get_length(), select); }
/**
* Moves the cursor to the beginning of the line.
* Moves the cursor to the beginning of the line
*
* @param select Select the text from the original cursor
* position till the beginning of the line?
@ -133,7 +134,7 @@ protected:
*
* @param unicode The unicode value of the character to insert.
*/
virtual void insert_char(const Uint16 unicode) = 0;
void insert_char(const Uint16 unicode);
/**
* Deletes the character.
@ -153,6 +154,15 @@ protected:
/** Pastes the current selection. */
virtual void paste_selection(const bool mouse);
/***** ***** ***** ***** expose some functions ***** ***** ***** *****/
gui2::tpoint get_cursor_position(
const unsigned column, const unsigned line = 0) const
{ return text_.get_cursor_position(column, line); }
tpoint get_column_line(const tpoint& position) const
{ return text_.get_column_line(position); }
/***** ***** ***** setters / getters for members ***** ****** *****/
size_t get_selection_start() const { return selection_start_; }
@ -161,6 +171,7 @@ protected:
size_t get_selection_length() const { return selection_length_; }
void set_selection_length(const unsigned selection_length);
private:
/** Note the order of the states must be the same as defined in settings.hpp. */
enum tstate { ENABLED, DISABLED, FOCUSSED, COUNT };
@ -176,10 +187,7 @@ private:
tstate state_;
/** The text entered in the widget. */
std::string text_;
/** Calculates the offsets of all chars. */
virtual void calculate_char_offset() = 0;
font::ttext text_;
/** Start of the selected text. */
size_t selection_start_;

View file

@ -46,12 +46,6 @@
namespace gui2 {
static surface render_text(const std::string& text, unsigned font_size)
{
static SDL_Color col = {0, 0, 0, 0};
return font::get_rendered_text(text, font_size, col, TTF_STYLE_NORMAL);
}
ttext_history ttext_history::get_history(const std::string& id, const bool enabled)
{
std::vector<std::string>* vec = preferences::get_history(id);
@ -121,41 +115,36 @@ void ttext_box::set_size(const SDL_Rect& rect)
void ttext_box::set_canvas_text()
{
/***** Gather the info *****/
// Set the cursor info.
const unsigned start = get_selection_start();
const int length = get_selection_length();
// Set the selection info
unsigned start_offset = 0;
unsigned end_offset = 0;
if(length == 0) {
// No nothing.
} else if(length > 0) {
start_offset = get_cursor_position(start).x;
end_offset = get_cursor_position(start + length).x;
} else {
start_offset = get_cursor_position(start + length).x;
end_offset = get_cursor_position(start).x;
}
/***** Set in all canvases *****/
foreach(tcanvas& tmp, canvas()) {
// NOTE when get_selection_start() == - get_selection_length() then the
// offset calculation will access character_offset_[-1] so add special
// cases to use 0 instead. The same can happen if
// get_selection_start() == 0.
// Set the general variables.
tmp.set_variable("text", variant(get_value()));
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 = get_selection_start();
const int len = get_selection_length();
if(get_value().empty() || start + len == 0) {
tmp.set_variable("cursor_offset", variant(0));
} else {
tmp.set_variable("cursor_offset",
variant(character_offset_[start - 1 + len]));
}
tmp.set_variable("cursor_offset",
variant(get_cursor_position(start + length).x));
// 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 ));
}
@ -196,46 +185,6 @@ void ttext_box::mouse_left_button_double_click(tevent_handler&)
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(get_value());
tmp.insert(tmp.begin() + get_selection_start(), unicode);
// Update the widths.
character_offset_.insert(
character_offset_.begin() + get_selection_start(), width);
if(get_selection_start() != 0) {
character_offset_[get_selection_start()]
+= character_offset_[get_selection_start() - 1];
}
const unsigned start = get_selection_start() + 1;
// set_value also resets the selection start, maybe add a real insert
// member to avoid that.
set_value(utils::wstring_to_string(tmp));
for(size_t i = start;
i < character_offset_.size(); ++i) {
character_offset_[i] += width;
}
set_cursor(start, false);
set_canvas_text();
set_dirty();
}
void ttext_box::delete_char(const bool before_cursor)
{
if(before_cursor) {
@ -283,8 +232,8 @@ void ttext_box::handle_mouse_selection(
return;
}
int offset =
get_character_offset_at(mouse.x - static_cast<int>(text_x_offset_));
int offset = get_column_line(tpoint(
mouse.x - text_x_offset_, mouse.y - text_y_offset_)).x;
if(offset < 0) {
return;
@ -297,19 +246,6 @@ void ttext_box::handle_mouse_selection(
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 get_value().size();
}
void ttext_box::update_offsets()
{
assert(config());
@ -340,23 +276,6 @@ void ttext_box::update_offsets()
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(get_value())) {
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()) {

View file

@ -115,7 +115,6 @@ class ttext_box : public ttext_
public:
ttext_box() :
ttext_(),
character_offset_(),
history_(),
text_x_offset_(0),
text_y_offset_(0),
@ -161,9 +160,6 @@ protected:
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);
@ -176,32 +172,14 @@ protected:
private:
/**
* 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_;
/**
* 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()
* This value is needed to translate a location in the widget to a location
* in the text.
*/
unsigned text_x_offset_;
@ -225,9 +203,6 @@ private:
/** Is the mouse in dragging mode, this affects selection in mouse move */
bool dragging_;
/** Inherited from ttext_. */
void calculate_char_offset();
/**
* Inherited from ttext_.
*