Showing with 67 additions and 5 deletions.
  1. +12 −2 src/editor/ui_menus/main_menu_random_map.cc
  2. +51 −2 src/ui_basic/editbox.cc
  3. +4 −1 src/ui_basic/editbox.h
@@ -564,7 +564,7 @@ bool MainMenuNewRandomMapPanel::do_generate_map(Widelands::EditorGameBase& egbas
}
log_info("\n");

const bool result = gen.create_random_map();
bool result = gen.create_random_map();

egbase.create_tempfile_and_save_mapdata(FileSystem::ZIP);

@@ -589,10 +589,20 @@ bool MainMenuNewRandomMapPanel::do_generate_map(Widelands::EditorGameBase& egbas
UI::WLMessageBox::MBoxType::kOk);
mbox.run<UI::Panel::Returncodes>();
} else {
const unsigned nr_players = map->get_nrplayers();
if (result) {
// Check that the starting positions are not too close
for (unsigned i = 1; i <= nr_players && result; ++i) {
for (unsigned j = 1; j < i && result; ++j) {
result &= (map->calc_distance(map->get_starting_pos(i), map->get_starting_pos(j)) >
Widelands::kMinSpaceAroundPlayers);
}
}
}

if (result) {
// Initialize with some good default values

const unsigned nr_players = map->get_nrplayers();
const unsigned plnum = std::rand() % nr_players; // NOLINT

map->set_name(_("Random Map"));
@@ -195,8 +195,9 @@ void EditBox::set_font_scale(float scale) {
/**
* The mouse was clicked on this editbox
*/
bool EditBox::handle_mousepress(const uint8_t btn, int32_t, int32_t) {
bool EditBox::handle_mousepress(const uint8_t btn, int32_t x, int32_t) {
if (btn == SDL_BUTTON_LEFT && get_can_focus()) {
set_caret_to_cursor_pos(x);
focus();
clicked();
return true;
@@ -205,6 +206,54 @@ bool EditBox::handle_mousepress(const uint8_t btn, int32_t, int32_t) {
return false;
}

void EditBox::set_caret_to_cursor_pos(int32_t cursor_pos_x) {
if (m_->text.empty() || cursor_pos_x <= kMarginX) {
set_caret_pos(0);
return;
}

int text_w = text_width(m_->text, m_->font_style(), m_->font_scale);

// mouse coordinate cursor_pos_x=0 means leftmost spot in editbox but text starts with margin ->
// adjust
cursor_pos_x -= kMarginX;

double x_relative = static_cast<double>(cursor_pos_x - m_->scrolloffset) / text_w;
if (x_relative > 1) {
set_caret_pos(m_->text.size());
return;
}

// initial guess of approx_caret_pos which works well already if all characters would be of same
// width
int approx_caret_pos = x_relative * m_->text.size();

approx_caret_pos = approximate_cursor(cursor_pos_x, approx_caret_pos);

set_caret_pos(approx_caret_pos);
}
int EditBox::approximate_cursor(int32_t cursor_pos_x, int approx_caret_pos) const {
static constexpr int error = 4;

// approximate using the first guess as start and increasing/decreasing text until error is small
int text_w = calculate_text_width(approx_caret_pos);
if (cursor_pos_x > text_w) {
while (cursor_pos_x - text_w > error) {
text_w = calculate_text_width(++approx_caret_pos);
}
} else if (cursor_pos_x < text_w) {
while (text_w - cursor_pos_x > error) {
text_w = calculate_text_width(--approx_caret_pos);
}
}
return snap_to_char(approx_caret_pos);
}
int EditBox::calculate_text_width(int pos) const {
std::string prefix = m_->text.substr(0, snap_to_char(pos));
int prefix_width = text_width(prefix, m_->font_style(), m_->font_scale) + m_->scrolloffset;
return prefix_width;
}

/**
* Handle keypress/release events
*/
@@ -611,7 +660,7 @@ void EditBox::reset_selection() {
/**
* Return the starting offset of the (multi-byte) character that @p cursor points to.
*/
uint32_t EditBox::snap_to_char(uint32_t cursor) {
uint32_t EditBox::snap_to_char(uint32_t cursor) const {
while (cursor > 0 && Utf8::is_utf8_extended(m_->text[cursor])) {
--cursor;
}
@@ -94,13 +94,16 @@ struct EditBox : public Panel {
std::string history_[CHAT_HISTORY_SIZE];
bool password_;
bool warning_;
uint32_t snap_to_char(uint32_t cursor);
uint32_t snap_to_char(uint32_t cursor) const;
void select_until(uint32_t end) const;
uint32_t next_char(uint32_t cursor) const;
uint32_t prev_char(uint32_t cursor) const;
void calculate_selection_boundaries(uint32_t& start, uint32_t& end);
void delete_selected_text();
void copy_selected_text();
void set_caret_to_cursor_pos(int32_t cursor_pos_x);
int calculate_text_width(int pos) const;
int approximate_cursor(int32_t cursor_pos_x, int approx_caret_pos) const;
};
} // namespace UI