summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/format.cc21
-rw-r--r--crawl-ref/source/format.h3
-rw-r--r--crawl-ref/source/invent.cc7
-rw-r--r--crawl-ref/source/invent.h8
-rw-r--r--crawl-ref/source/menu.cc7
-rw-r--r--crawl-ref/source/menu.h4
-rw-r--r--crawl-ref/source/tilefont.cc112
-rw-r--r--crawl-ref/source/tilefont.h14
-rw-r--r--crawl-ref/source/tilereg.cc142
-rw-r--r--crawl-ref/source/tilereg.h2
10 files changed, 276 insertions, 44 deletions
diff --git a/crawl-ref/source/format.cc b/crawl-ref/source/format.cc
index 9cd282e058..cf884f8220 100644
--- a/crawl-ref/source/format.cc
+++ b/crawl-ref/source/format.cc
@@ -329,6 +329,27 @@ inline void cap(int &i, int max)
i = 0;
}
+char &formatted_string::operator [] (size_t idx)
+{
+ size_t rel_idx = idx;
+ int size = ops.size();
+ for (int i = 0; i < size; ++i)
+ {
+ if (ops[i] != FSOP_TEXT)
+ continue;
+
+ size_t len = ops[i].text.length();
+ if (rel_idx >= len)
+ rel_idx -= len;
+ else
+ return ops[i].text[rel_idx];
+ }
+ ASSERT(!"Invalid index");
+ char *invalid = NULL;
+ return *invalid;
+}
+
+
std::string formatted_string::tostring(int s, int e) const
{
std::string st;
diff --git a/crawl-ref/source/format.h b/crawl-ref/source/format.h
index 9ddd43576d..297e793106 100644
--- a/crawl-ref/source/format.h
+++ b/crawl-ref/source/format.h
@@ -26,7 +26,7 @@ class formatted_string
{
public:
formatted_string(int init_colour = 0);
- formatted_string(const std::string &s, int init_colour = 0);
+ explicit formatted_string(const std::string &s, int init_colour = 0);
operator std::string() const;
void display(int start = 0, int end = -1) const;
@@ -51,6 +51,7 @@ public:
bool operator < ( const formatted_string &other ) const;
const formatted_string &operator += (const formatted_string &other);
+ char &operator [] (size_t idx);
public:
static formatted_string parse_string(
diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc
index 5c4c7ecad5..fbef463669 100644
--- a/crawl-ref/source/invent.cc
+++ b/crawl-ref/source/invent.cc
@@ -268,6 +268,13 @@ InvShowPrices::~InvShowPrices()
InvEntry::set_show_prices(false);
}
+InvMenu::InvMenu(int mflags)
+ : Menu(mflags, "inventory"), type(MT_INVLIST), pre_select(NULL),
+ title_annotate(NULL)
+{
+ mdisplay->set_num_columns(2);
+}
+
// Returns vector of item_def pointers to each item_def in the given
// vector. Note: make sure the original vector stays around for the lifetime
// of the use of the item pointers, or mayhem results!
diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h
index 8cdabe01b1..5e5e95f53a 100644
--- a/crawl-ref/source/invent.h
+++ b/crawl-ref/source/invent.h
@@ -117,11 +117,7 @@ public:
class InvMenu : public Menu
{
public:
- InvMenu(int mflags = MF_MULTISELECT)
- : Menu(mflags, "inventory"), type(MT_INVLIST), pre_select(NULL),
- title_annotate(NULL)
- {
- }
+ InvMenu(int mflags = MF_MULTISELECT);
unsigned char getkey() const;
@@ -155,6 +151,8 @@ public:
// of the use of the item pointers, or mayhem results!
static std::vector<const item_def*> xlat_itemvect(
const std::vector<item_def> &);
+
+ virtual int max_columns() const { return 2; }
protected:
bool process_key(int key);
void do_preselect(InvEntry *ie);
diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc
index a3c7b1e155..a9f4f33109 100644
--- a/crawl-ref/source/menu.cc
+++ b/crawl-ref/source/menu.cc
@@ -69,6 +69,11 @@ void MenuDisplayTile::draw_more()
{
tiles.get_menu()->set_more(m_menu->get_more());
}
+
+void MenuDisplayTile::set_num_columns(int columns)
+{
+ tiles.get_menu()->set_num_columns(columns);
+}
#endif
Menu::Menu( int _flags, const std::string& tagname )
@@ -83,6 +88,7 @@ Menu::Menu( int _flags, const std::string& tagname )
#else
mdisplay = new MenuDisplayText(this);
#endif
+ mdisplay->set_num_columns(1);
set_flags(flags);
}
@@ -102,6 +108,7 @@ Menu::Menu( const formatted_string &fs )
#else
mdisplay = new MenuDisplayText(this);
#endif
+ mdisplay->set_num_columns(1);
int colour = LIGHTGREY;
int last_text_colour = LIGHTGREY;
diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h
index ce2b857ada..ca48475b64 100644
--- a/crawl-ref/source/menu.h
+++ b/crawl-ref/source/menu.h
@@ -196,6 +196,7 @@ public:
virtual void draw_stock_item(int index, const MenuEntry *me) = 0;
virtual void set_offset(int lines) = 0;
virtual void draw_more() = 0;
+ virtual void set_num_columns(int columns) = 0;
protected:
Menu *m_menu;
};
@@ -207,6 +208,7 @@ public:
virtual void draw_stock_item(int index, const MenuEntry *me);
virtual void draw_more();
virtual void set_offset(int lines) { m_starty = lines; }
+ virtual void set_num_columns(int columns) {}
protected:
int m_starty;
};
@@ -218,6 +220,7 @@ public:
virtual void draw_stock_item(int index, const MenuEntry *me);
virtual void set_offset(int lines);
virtual void draw_more();
+ virtual void set_num_columns(int columns);
};
///////////////////////////////////////////////////////////////////////
@@ -294,7 +297,6 @@ public:
virtual int item_colour(int index, const MenuEntry *me) const;
int get_y_offset() const { return y_offset; }
int get_pagesize() const { return pagesize; }
-
public:
typedef std::string (*selitem_tfn)( const std::vector<MenuEntry*> *sel );
typedef void (*drawitem_tfn)(int index, const MenuEntry *me);
diff --git a/crawl-ref/source/tilefont.cc b/crawl-ref/source/tilefont.cc
index 93d14aa9dc..e2251d2042 100644
--- a/crawl-ref/source/tilefont.cc
+++ b/crawl-ref/source/tilefont.cc
@@ -447,7 +447,29 @@ static void _draw_box(int x_pos, int y_pos, float width, float height,
glVertexPointer(2, GL_FLOAT, sizeof(box_vert), &verts[0].x);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(box_vert), &verts[0].r);
glDrawArrays(GL_QUADS, 0, sizeof(verts) / sizeof(box_vert));
+}
+unsigned int FTFont::string_height(const formatted_string &str)
+{
+ std::string temp = str.tostring();
+ return string_height(temp.c_str());
+}
+
+unsigned int FTFont::string_height(const char *text)
+{
+ int height = 1;
+ for (const char *itr = text; (*itr); itr++)
+ {
+ if (*itr == '\n')
+ height++;
+ }
+ return char_height() * height;
+}
+
+unsigned int FTFont::string_width(const formatted_string &str)
+{
+ std::string temp = str.tostring();
+ return string_width(temp.c_str());
}
unsigned int FTFont::string_width(const char *text)
@@ -455,7 +477,7 @@ unsigned int FTFont::string_width(const char *text)
unsigned int base_width = std::max(-m_min_offset, 0);
unsigned int max_width = 0;
- unsigned int width = 0;
+ unsigned int width = base_width;
unsigned int adjust = 0;
for (const char *itr = text; *itr; itr++)
{
@@ -476,6 +498,79 @@ unsigned int FTFont::string_width(const char *text)
return max_width;
}
+int FTFont::find_index_before_width(const char *text, int max_width)
+{
+ int width = std::max(-m_min_offset, 0);
+
+ for (int i = 0; text[i]; i++)
+ {
+ char c = text[i];
+ width += m_glyphs[c].advance;
+ int adjust = std::max(0, m_glyphs[c].width - m_glyphs[c].advance);
+ if (width + adjust > max_width)
+ return i;
+ }
+
+ return -1;
+}
+
+formatted_string FTFont::split(const formatted_string &str,
+ unsigned int max_width, unsigned int max_height)
+{
+ int max_lines = max_height / char_height();
+
+ if (max_lines < 1)
+ return formatted_string();
+
+ formatted_string ret;
+ ret += str;
+
+ std::string base = str.tostring();
+ int num_lines = 0;
+
+ char *line = &base[0];
+ while (true)
+ {
+ int line_end = find_index_before_width(line, max_width);
+ if (line_end == -1)
+ break;
+
+ int space_idx = 0;
+ for (char *search = &line[line_end]; search > line; search--)
+ {
+ if (*search == ' ')
+ {
+ space_idx = search - line;
+ break;
+ }
+ }
+
+ if (++num_lines >= max_lines || !space_idx)
+ {
+ int ellipses;
+ if (space_idx && (space_idx - line_end > 2))
+ ellipses = space_idx;
+ else
+ ellipses = line_end - 2;
+
+ size_t idx = &line[ellipses] - &base[0];
+ ret[idx] = '.';
+ ret[idx+1] = '.';
+
+ return ret.substr(0, idx + 2);
+ }
+ else
+ {
+ line[space_idx] = '\n';
+ ret[&line[space_idx] - &base[0]] = '\n';
+ }
+
+ line = &line[space_idx+1];
+ }
+
+ return ret;
+}
+
void FTFont::render_string(unsigned int px, unsigned int py,
const char *text,
const coord_def &min_pos, const coord_def &max_pos,
@@ -561,11 +656,18 @@ void FTFont::render_string(unsigned int px, unsigned int py,
void FTFont::store(FontBuffer &buf, float &x, float &y,
const std::string &str, const VColour &col)
{
+ store(buf, x, y, str, col, x);
+}
+
+void FTFont::store(FontBuffer &buf, float &x, float &y,
+ const std::string &str, const VColour &col, float orig_x)
+{
for (unsigned int i = 0; i < str.size(); i++)
{
char c = str[i];
if (c == '\n')
{
+ x = orig_x;
y += m_max_advance.y;
}
else
@@ -578,6 +680,12 @@ void FTFont::store(FontBuffer &buf, float &x, float &y,
void FTFont::store(FontBuffer &buf, float &x, float &y,
const formatted_string &fs)
{
+ store(buf, x, y, fs, x);
+}
+
+void FTFont::store(FontBuffer &buf, float &x, float &y,
+ const formatted_string &fs, float orig_x)
+{
int colour = LIGHTGREY;
for (unsigned int i = 0; i < fs.ops.size(); i++)
{
@@ -588,7 +696,7 @@ void FTFont::store(FontBuffer &buf, float &x, float &y,
colour = fs.ops[i].x & 0xF;
break;
case FSOP_TEXT:
- store(buf, x, y, fs.ops[i].text, term_colours[colour]);
+ store(buf, x, y, fs.ops[i].text, term_colours[colour], orig_x);
break;
default:
case FSOP_CURSOR:
diff --git a/crawl-ref/source/tilefont.h b/crawl-ref/source/tilefont.h
index ba4101f167..ab81353be4 100644
--- a/crawl-ref/source/tilefont.h
+++ b/crawl-ref/source/tilefont.h
@@ -57,10 +57,24 @@ public:
unsigned int char_height() const { return m_max_advance.y; }
unsigned int string_width(const char *text);
+ unsigned int string_width(const formatted_string &str);
+ unsigned int string_height(const char *text);
+ unsigned int string_height(const formatted_string &str);
+
+ // Try to split this string to fit in w x h pixel area.
+ formatted_string split(const formatted_string &str, unsigned int max_width,
+ unsigned int max_height);
const GenericTexture *font_tex() const { return &m_tex; }
protected:
+ void store(FontBuffer &buf, float &x, float &y,
+ const std::string &s, const VColour &c, float orig_x);
+ void store(FontBuffer &buf, float &x, float &y, const formatted_string &fs,
+ float orig_x);
+
+ int find_index_before_width(const char *str, int max_width);
+
struct GlyphInfo
{
// offset before drawing glyph; can be negative
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 6fea149787..021fd9c2bb 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -2357,7 +2357,7 @@ int CRTRegion::handle_mouse(MouseEvent &event)
MenuRegion::MenuRegion(ImageManager *im, FTFont *entry) :
m_image(im), m_font_entry(entry), m_mouse_idx(-1),
- m_dirty(false), m_font_buf(entry), m_tile_buf(NULL)
+ m_max_columns(1), m_dirty(false), m_font_buf(entry), m_tile_buf(NULL)
{
ASSERT(m_image);
ASSERT(m_font_entry);
@@ -2368,6 +2368,11 @@ MenuRegion::MenuRegion(ImageManager *im, FTFont *entry) :
m_entries.resize(128);
}
+void MenuRegion::set_num_columns(int columns)
+{
+ m_max_columns = std::max(1, columns);
+}
+
int MenuRegion::mouse_entry(int x, int y)
{
if (m_dirty)
@@ -2450,10 +2455,9 @@ void MenuRegion::place_entries()
m_dirty = false;
const int heading_indent = 10;
- const int tile_ident = 20;
+ const int tile_indent = 20;
const int text_indent = 58;
- const unsigned int max_tile_height = 32;
- const int column_width = mx / 2;
+ const int max_tile_height = 32;
const int entry_buffer = 1;
const VColour selected_colour(50, 50, 10, 255);
@@ -2464,8 +2468,11 @@ void MenuRegion::place_entries()
TextureID tex = TEX_MAX;
int height = 2;
+ int prev_height = height;
- bool mouse_selected = false;
+ int column = 0;
+ const int max_columns = std::min(2, m_max_columns);
+ const int column_width = mx / max_columns;
for (unsigned int i = 0; i < m_entries.size(); i++)
{
@@ -2478,45 +2485,110 @@ void MenuRegion::place_entries()
continue;
}
- m_entries[i].sy = height;
-
- int text_start = 0;
- int text_height = height;
+ int text_width = m_font_entry->string_width(m_entries[i].text);
+ int text_height = m_font_entry->char_height();
if (m_entries[i].heading)
{
- mouse_selected = false;
m_entries[i].sx = heading_indent;
- text_start = heading_indent;
- height += m_font_entry->char_height();
- }
- else if (m_entries[i].tile)
- {
- m_entries[i].sx = tile_ident;
- text_start = text_indent;
- int entry_height =
- std::max(max_tile_height, m_font_entry->char_height());
- height += entry_height;
- text_height += (entry_height - m_font_entry->char_height()) / 2;
-
- ASSERT(m_entries[i].texture == tex || tex == TEX_MAX);
- tex = m_entries[i].texture;
- m_tile_buf.set_tex(&m_image->m_textures[tex]);
-
- m_tile_buf.add(m_entries[i].tile, m_entries[i].sx, m_entries[i].sy);
+ m_entries[i].ex = m_entries[i].sx + text_width;
+ m_entries[i].sy = height;
+ m_entries[i].ey = m_entries[i].sy + text_height;
+
+ m_font_buf.add(m_entries[i].text, m_entries[i].sx, m_entries[i].sy);
+
+ height += text_height;
+ prev_height = height;
+ column = 0;
}
else
{
- m_entries[i].sx = text_start + text_indent;
- height += m_font_entry->char_height();
- }
+ int entry_start;
+ if (column > 0)
+ {
+ entry_start = column * column_width;
+ m_entries[i].sy = prev_height;
+ }
+ else
+ {
+ entry_start = 0;
+ m_entries[i].sy = height;
+ }
+
+ int text_sx = entry_start + text_indent;
- std::string unfrm = m_entries[i].text.tostring();
- m_entries[i].ex = text_start + m_font_entry->string_width(unfrm.c_str());
- m_entries[i].ex = std::max(m_entries[i].ex, column_width);
- m_entries[i].ey = height;
+ int entry_height;
+ if (m_entries[i].tile)
+ {
+ m_entries[i].sx = entry_start + tile_indent;
+ entry_height = std::max(max_tile_height, text_height);
+
+ // Currently, menus only support one texture at a time.
+ tex = m_entries[i].texture;
+ ASSERT(m_entries[i].texture == tex || tex == TEX_MAX);
+
+ m_tile_buf.set_tex(&m_image->m_textures[tex]);
+ m_tile_buf.add(m_entries[i].tile, m_entries[i].sx,
+ m_entries[i].sy);
+ }
+ else
+ {
+ m_entries[i].sx = text_sx;
+ entry_height = text_height;
+ }
- m_font_buf.add(m_entries[i].text, text_start, text_height);
+ int text_sy = m_entries[i].sy;
+ text_sy += (entry_height - m_font_entry->char_height()) / 2;
+ if (text_sx + text_width > entry_start + column_width)
+ {
+ // [enne] - Ugh, hack. Maybe MenuEntry could specify the
+ // presence and length of this substring?
+ std::string unfm = m_entries[i].text.tostring();
+ bool let = (unfm[1] >= 'a' && unfm[1] <= 'z'
+ || unfm[1] >= 'A' && unfm[1] <= 'Z');
+ bool plus = (unfm[3] == '-' || unfm[3] == '+');
+
+ formatted_string text;
+ if (let && plus && unfm[0] == ' ' && unfm[2] == ' '
+ && unfm[4] == ' ')
+ {
+ formatted_string header = m_entries[i].text.substr(0, 5);
+ m_font_buf.add(header, text_sx, text_sy);
+ text_sx += m_font_entry->string_width(header);
+ text = m_entries[i].text.substr(5);
+ }
+ else
+ {
+ text += m_entries[i].text;
+ }
+
+ int w = entry_start + column_width - text_sx;
+ int h = m_font_entry->char_height() * 2;
+ formatted_string split = m_font_entry->split(text, w, h);
+
+ int string_height = m_font_entry->string_height(split);
+ if (string_height > entry_height)
+ {
+ text_sy = m_entries[i].sy;
+ }
+ m_font_buf.add(split, text_sx, text_sy);
+
+ m_entries[i].ex = entry_start + column_width;
+
+ entry_height = std::max(entry_height, string_height);
+ }
+ else
+ {
+ m_entries[i].ex = entry_start + column_width;
+ m_font_buf.add(m_entries[i].text, text_sx, text_sy);
+ }
+
+ m_entries[i].ey = m_entries[i].sy + entry_height;
+
+ prev_height = m_entries[i].sy;
+ height = std::max(height, m_entries[i].ey);
+ column = (column + 1) % max_columns;
+ }
if (m_entries[i].selected)
{
diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h
index 4111e6152a..55205ed3e3 100644
--- a/crawl-ref/source/tilereg.h
+++ b/crawl-ref/source/tilereg.h
@@ -193,6 +193,7 @@ public:
void set_entry(int index, const std::string &s, int colour, const MenuEntry *me);
void set_offset(int lines);
void set_more(const formatted_string &more);
+ void set_num_columns(int columns);
protected:
virtual void on_resize();
virtual void place_entries();
@@ -214,6 +215,7 @@ protected:
FTFont *m_font_entry;
formatted_string m_more;
int m_mouse_idx;
+ int m_max_columns;
bool m_dirty;
std::vector<MenuRegionEntry> m_entries;