diff options
author | pauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-03-31 05:34:04 +0000 |
---|---|---|
committer | pauldubois <pauldubois@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-03-31 05:34:04 +0000 |
commit | 64f107bdd6e7ec9b5c5a1e17474e956a71326b3a (patch) | |
tree | 267d95cee5ded8d24f244bc9a0808a7dd2dc603c /crawl-ref/source/view.cc | |
parent | ae03c1a6490a00ed5131041fc584afa5c1418be8 (diff) | |
download | crawl-ref-64f107bdd6e7ec9b5c5a1e17474e956a71326b3a.tar.gz crawl-ref-64f107bdd6e7ec9b5c5a1e17474e956a71326b3a.zip |
Refactor the layout logic for the inline and mlist-col layouts into a
couple classes. Hopefully it will be much easier to tune the layouts
now.
Fixed problem I introduced earlier today that didn't let message pane
use the bottom-most line. Stole a couple cols from the HUD and one
from the HUD gutter to potentially give to the mlist or to the main
view. Stole a row from the message area so even 80x24 players get
get one line of monster list
Made the mlist-col layout not so unfair to the main view, and not
truncate the mlist width so much. It used to pop in if you had an
81-col display; now the display needs to be larger (~95) for it to be
used, but it is a lot more functional.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3972 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/view.cc')
-rw-r--r-- | crawl-ref/source/view.cc | 337 |
1 files changed, 219 insertions, 118 deletions
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index 14b61f6e31..bb4db7041b 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -4554,10 +4554,14 @@ static void _debug_pane_bounds() // Doesn't work for HUD because print_stats() overwrites it. // To debug HUD, add viewwindow(false,false) at end of _prep_input. - cgotoxy(1,1, GOTO_MLIST); - cprintf("+ L"); - cgotoxy(crawl_view.mlistsz.x-4, crawl_view.mlistsz.y, GOTO_MLIST); - cprintf("L +"); + if (crawl_view.mlistsz.y > 0) + { + textcolor(WHITE); + cgotoxy(1,1, GOTO_MLIST); + cprintf("+ L"); + cgotoxy(crawl_view.mlistsz.x-4, crawl_view.mlistsz.y, GOTO_MLIST); + cprintf("L +"); + } cgotoxy(1,1, GOTO_STAT); cprintf("+ H"); @@ -4574,6 +4578,7 @@ static void _debug_pane_bounds() cgotoxy(crawl_view.viewp.x+crawl_view.viewsz.x-2, crawl_view.viewp.y+crawl_view.viewsz.y-1); cprintf("V+"); + textcolor(LIGHTGREY); #endif } @@ -4908,15 +4913,192 @@ void crawl_view_buffer::size(const coord_def &sz) ////////////////////////////////////////////////////////////////////////////// // crawl_view_geometry -// already defined in header -// const int crawl_view_geometry::message_min_lines; -// const int crawl_view_geometry::hud_min_width; -// const int crawl_view_geometry::hud_min_gutter; -// const int crawl_view_geometry::hud_max_gutter; +// ---------------------------------------------------------------------- +// Layout helper classes +// ---------------------------------------------------------------------- + +// Moved from direct.h, where they didn't need to be. +// define VIEW_MIN_HEIGHT defined elsewhere +// define VIEW_MAX_HEIGHT use Options.view_max_height +// define VIEW_MIN_WIDTH defined elsewhere +// define VIEW_MAX_WIDTH use Options.view_max_width +#define HUD_WIDTH 39 +#define HUD_HEIGHT 17 +#define MSG_MIN_HEIGHT 6 +// #define MLIST_MIN_HEIGHT use Options.mlist_min_height +#define MLIST_MIN_WIDTH 25 /* non-inline layout only */ +#define MLIST_MAX_WIDTH 42 +#define MLIST_GUTTER 1 +#define HUD_MIN_GUTTER 2 +#define HUD_MAX_GUTTER 4 + +// Helper for layouts. Tries to increment lvalue without overflowing it. +static void _increment(int& lvalue, int delta, int max_value) +{ + lvalue = std::min(lvalue+delta, max_value); +} + +class _layout +{ + public: + _layout(coord_def termsz_) : + termp(1,1), termsz(termsz_), + viewp(-1,-1), viewsz(VIEW_MIN_WIDTH, VIEW_MIN_HEIGHT), + hudp(-1,-1), hudsz(HUD_WIDTH, HUD_HEIGHT), + msgp(-1,-1), msgsz(0, MSG_MIN_HEIGHT), + mlistp(-1,-1), mlistsz(MLIST_MIN_WIDTH, 0), + hud_gutter(HUD_MIN_GUTTER), + valid(false) {} + + protected: + void _assert_validity() const + { +#ifndef USE_TILE + // Check that all the panes fit in the view. + ASSERT( (viewp+viewsz - termp).x <= termsz.x ); + ASSERT( (viewp+viewsz - termp).y <= termsz.y ); + + ASSERT( (hudp+hudsz - termp).x <= termsz.x ); + ASSERT( (hudp+hudsz - termp).y <= termsz.y ); + + ASSERT( (msgp+msgsz - termp).x <= termsz.x ); + ASSERT( (msgp+msgsz - termp).y <= termsz.y ); + // Don't stretch message all the way to the bottom-right + // character; it causes scrolling and badness. + ASSERT( (msgp+msgsz - termp) != termsz ); + + ASSERT( (mlistp+mlistsz-termp).x <= termsz.x ); + ASSERT( (mlistp+mlistsz-termp).y <= termsz.y ); +#endif + } + public: + const coord_def termp, termsz; + coord_def viewp, viewsz; + coord_def hudp; + const coord_def hudsz; + coord_def mlistp, mlistsz; + coord_def msgp, msgsz; + int hud_gutter; + bool valid; +}; + +// vvvvvvghhh v=view, g=hud gutter, h=hud, l=list, m=msg +// vvvvvvghhh +// vvvvvv lll +// lll +// mmmmmmmmmm +class _inline_layout : public _layout +{ + public: + _inline_layout(coord_def c) : _layout(c) { valid = _init(); } + bool _init() + { + // x: View gets leftover; then mlist; then hud gutter + if (leftover_x() < 0) return false; + _increment(viewsz.x, leftover_x(), Options.view_max_width); + if ((viewsz.x % 2) != 1) --viewsz.x; + mlistsz.x = hudsz.x; + _increment(mlistsz.x, leftover_x(), MLIST_MAX_WIDTH); + _increment(hud_gutter, leftover_x(), HUD_MAX_GUTTER); + _increment(mlistsz.x, leftover_x(), INT_MAX); + msgsz.x = termsz.x-1; // Can't use last character + + // y: View gets leftover; then mlist; then message + // mlist might be left with less than MLIST_MIN_HEIGHT, but + // that's the breaks. + if (leftover_y() < 0) { return false; } + { + const int saved_leftover_y = leftover_y(); + _increment(viewsz.y, saved_leftover_y, Options.view_max_height); + if ((viewsz.y % 2) != 1) --viewsz.y; + if (mlistsz.y < Options.mlist_min_height) + { + _increment(mlistsz.y, saved_leftover_y, Options.mlist_min_height); + } + } + _increment(msgsz.y, leftover_y(), INT_MAX); + + // Finish off by doing the positions + viewp = termp; + msgp = termp + coord_def(0, std::max(viewsz.y, hudsz.y+mlistsz.y)); + hudp = viewp + coord_def(viewsz.x+hud_gutter, 0); + mlistp = hudp + coord_def(0, hudsz.y); + + _assert_validity(); + return true; + } + + int leftover_x() const + { + int width = (viewsz.x + hud_gutter + std::max(hudsz.x, mlistsz.x)); + return (termsz.x - width); + } + int leftover_y() const + { + // hud+mlist can grow longer than the view, believe it or not + int height = std::max(viewsz.y, hudsz.y+mlistsz.y) + msgsz.y; + return (termsz.y - height); + } +}; + +// ll vvvvvvghhh v=view, g=hud gutter, h=hud, l=list, m=msg +// ll vvvvvvghhh +// ll vvvvvv +// mmmmmmmmmmmmm +class _mlist_col_layout : public _layout +{ + public: + _mlist_col_layout(coord_def c) : _layout(c) { valid = _init(); } + bool _init() + { + // Don't let the mlist column steal all the width. Up front, + // take some for the view. If it makes the layout fail, that's fine. + _increment(viewsz.x, MLIST_MIN_WIDTH/2, Options.view_max_width); + + // x: View and mlist share leftover; then hud gutter + if (leftover_x() < 0) return false; + + _increment(mlistsz.x, leftover_x()/2, MLIST_MAX_WIDTH); + _increment(viewsz.x, leftover_x(), Options.view_max_width); + if ((viewsz.x % 2) != 1) --viewsz.x; + _increment(mlistsz.x, leftover_x(), MLIST_MAX_WIDTH); + _increment(hud_gutter, leftover_x(), HUD_MAX_GUTTER); + msgsz.x = termsz.x-1; // Can't use last character + + // y: View gets leftover; then message + if (leftover_y() < 0) return false; + _increment(viewsz.y, leftover_y(), Options.view_max_height); + if ((viewsz.y % 2) != 1) --viewsz.y; + _increment(msgsz.y, leftover_y(), INT_MAX); + mlistsz.y = viewsz.y; + + // Finish off by doing the positions + mlistp = termp; + viewp = mlistp+ coord_def(mlistsz.x+MLIST_GUTTER, 0); + msgp = termp + coord_def(0, viewsz.y); + hudp = viewp + coord_def(viewsz.x+hud_gutter, 0); + + _assert_validity(); + return true; + } + private: + int leftover_x() const + { + int width = (mlistsz.x + MLIST_GUTTER + viewsz.x + hud_gutter + hudsz.x); + return (termsz.x - width); + } + int leftover_y() const + { + const int top_y = std::max(std::max(viewsz.y, hudsz.y), mlistsz.y); + const int height = top_y + msgsz.y; + return (termsz.y - height); + } +}; crawl_view_geometry::crawl_view_geometry() - : termsz(80, 24), viewp(1, 1), viewsz(33, 17), - hudp(40, 1), hudsz(41, 17), + : termp(1, 1), termsz(80, 24), + viewp(1, 1), viewsz(33, 17), + hudp(40, 1), hudsz(HUD_WIDTH, HUD_HEIGHT), msgp(1, viewp.y + viewsz.y), msgsz(80, 7), mlistp(hudp.x, hudp.y + hudsz.y), mlistsz(hudsz.x, msgp.y - mlistp.y), @@ -4989,102 +5171,37 @@ void crawl_view_geometry::set_player_at(const coord_def &c, bool centre) void crawl_view_geometry::init_geometry() { - // Points and sizes can be combined in these ways: - // p+p=meaningless, p+sz=p, p-p=sz, p-sz=p - // sz+p=p, sz+sz=sz, sz-p=meaningless, sz-sz=sz - - const coord_def termp(1,1); - termsz = coord_def( get_number_of_cols(), get_number_of_lines() ); -#ifndef USE_TILE - // If the terminal is too small, exit with an error. - if ((termsz.x < 80 || termsz.y < 24) && !crawl_state.need_save) - end(1, false, "Terminal too small (%d,%d), need at least (80,24)", - termsz.x, termsz.y); -#endif - - int freeheight = termsz.y - message_min_lines; - - // Make the viewport as tall as possible. - viewsz.y = freeheight < Options.view_max_height? - freeheight : Options.view_max_height; - - // Make sure we're odd-sized. - if (!(viewsz.y % 2)) - --viewsz.y; - - // If the view is too short, force it to minimum height. - if (viewsz.y < VIEW_MIN_HEIGHT) - viewsz.y = VIEW_MIN_HEIGHT; + const _inline_layout lay_inline(termsz); + const _mlist_col_layout lay_mlist(termsz); - // Determine if the monster list can have its own column. - int freewidth = termsz.x - (viewsz.x + mlist_gutter + - mlist_min_width + hud_min_gutter + hudsz.x); - mlist_inline = (freewidth < 0) || Options.mlist_force_inline; - if (mlist_inline) - freewidth = termsz.x - (hud_min_width + hud_min_gutter); - - // Make the viewport as wide as possible. - viewsz.x = freewidth < Options.view_max_width? - freewidth : Options.view_max_width; - - if (!(viewsz.x % 2)) - --viewsz.x; - - if (viewsz.x < VIEW_MIN_WIDTH) - viewsz.x = VIEW_MIN_WIDTH; - - vbuf.size(viewsz); - - if (!mlist_inline) + if (! lay_inline.valid) { - mlistp = termp; - const int _mlist_max_width = mlist_max_width; // work around link problem? - mlistsz.x = std::min(mlist_min_width + freewidth, _mlist_max_width); - mlistsz.y = viewsz.y; - - viewp.x = mlistp.x + mlistsz.x; - } - - // The hud appears after the viewport + gutter and possibly the mlist. - hudp = coord_def(viewp.x + viewsz.x + hud_min_gutter, 1); - - // HUD size never changes, but we may increase the gutter size (up to - // the current max of 6). - if (hudp.x + hudsz.x - 1 < termsz.x) - { - const int hudmarg = termsz.x - (hudp.x + hudsz.x - 1); - const int hud_increase_max = hud_max_gutter - hud_min_gutter; - hudp.x += hudmarg > hud_increase_max? hud_increase_max : hudmarg; +#ifndef USE_TILE + // Terminal too small; exit with an error + if (!crawl_state.need_save) + { + end(1, false, "Terminal too small (%d,%d); need at least (%d,%d)", + termsz.x, termsz.y, + termsz.x + std::max(0, -lay_inline.leftover_x()), + termsz.y + std::max(0, -lay_inline.leftover_y())); + } +#endif } - if (mlist_inline) - { - // Monster list takes up all space between the hud and the message pane - mlistp = coord_def(hudp.x, hudp.y + hudsz.y); - - // Try to grow the length of the monster list based on the options, - // but only grow if there's room for the minimum message lines. - int len = 1 + viewsz.y - mlistp.y; - len = std::max(len, Options.mlist_min_height); - len = std::min(len, 1 + termsz.y - message_min_lines - (hudp.y + hudsz.y)); - mlistsz = coord_def(termsz.x - (mlistp.x - 1), len); - } + const _layout* winner = &lay_inline; + if (!Options.mlist_force_inline && lay_mlist.valid) + winner = &lay_mlist; - // Calculate message area - { - // Always from lhs of term to rhs of term - msgp.x = termp.x; - msgsz.x = termsz.x; - // From bottom of mlist or view, whichever is lower, to bottom of term - msgp.y = std::max((mlistp+mlistsz).y, (viewp+viewsz).y); - msgsz.y = termsz.y - (msgp-termp).y; - - // Well, actually not to the very bottom. Drawing the last line causes - // the screen to scroll. If this is fixed, we get another line of message. - msgsz.y -= 1; - } + msgp = winner->msgp; + msgsz = winner->msgsz; + viewp = winner->viewp; + viewsz = winner->viewsz; + hudp = winner->hudp; + // hudsz = winner->hudsz; size is constant + mlistp = winner->mlistp; + mlistsz = winner->mlistsz; #ifdef USE_TILE // libgui may redefine these based on its own settings @@ -5092,25 +5209,9 @@ void crawl_view_geometry::init_geometry() #endif viewhalfsz = viewsz / 2; - + vbuf.size(viewsz); init_view(); - -#ifndef USE_TILE - // Check that all the panes fit in the view. Note that currently - // no pane is allowed to stretch all the way to the bottom (see - // comment by message pane calculation, above. - ASSERT( (viewp+viewsz-termp).x <= termsz.x ); - ASSERT( (viewp+viewsz-termp).y <= termsz.y-1 ); - - ASSERT( (hudp+hudsz-termp).x <= termsz.x ); - ASSERT( (hudp+hudsz-termp).y <= termsz.y-1 ); - - ASSERT( (msgp+msgsz-termp).x <= termsz.x ); - ASSERT( (msgp+msgsz-termp).y <= termsz.y-1 ); - - ASSERT( (mlistp+mlistsz-termp).x <= termsz.x ); - ASSERT( (mlistp+mlistsz-termp).y <= termsz.y-1 ); -#endif + return; } //////////////////////////////////////////////////////////////////////////// |