added tooltips for text that cannot fit

This commit is contained in:
Dave White 2003-10-04 06:09:11 +00:00
parent 2fad190610
commit 35f11b1cee
9 changed files with 258 additions and 26 deletions

View file

@ -8,7 +8,7 @@ SDL_CFLAGS=`sdl-config --cflags` `freetype-config --cflags`
SDL_LIBS=`sdl-config --libs` `freetype-config --libs` -lSDL_mixer -lSDL_ttf -lSDL_image
LIBS=${SDL_LIBS} -lstdc++
INCLUDES=-I. -Isrc -Isrc/tools -Isrc/widgets
OBJS=src/actions.o src/ai.o src/ai_attack.o src/ai_move.o src/config.o src/dialogs.o src/display.o src/filesystem.o src/font.o src/game.o src/game_config.o src/game_events.o src/gamestatus.o src/hotkeys.o src/intro.o src/key.o src/language.o src/log.o src/map.o src/menu.o src/multiplayer.o src/pathfind.o src/playlevel.o src/playturn.o src/preferences.o src/replay.o src/sdl_utils.o src/sound.o src/team.o src/terrain.o src/unit.o src/unit_types.o src/video.o src/widgets/button.o src/widgets/slider.o src/widgets/textbox.o
OBJS=src/actions.o src/ai.o src/ai_attack.o src/ai_move.o src/config.o src/dialogs.o src/display.o src/filesystem.o src/font.o src/game.o src/game_config.o src/game_events.o src/gamestatus.o src/hotkeys.o src/intro.o src/key.o src/language.o src/log.o src/map.o src/menu.o src/multiplayer.o src/pathfind.o src/playlevel.o src/playturn.o src/preferences.o src/replay.o src/sdl_utils.o src/sound.o src/team.o src/terrain.o src/tooltips.o src/unit.o src/unit_types.o src/video.o src/widgets/button.o src/widgets/slider.o src/widgets/textbox.o
MAKE_TRANS_OBJS=src/tools/make_translation.o src/config.o src/filesystem.o src/log.o
MERGE_TRANS_OBJS=src/tools/merge_translations.o src/config.o src/filesystem.o src/log.o

View file

@ -21,6 +21,7 @@
#include "menu.hpp"
#include "sdl_utils.hpp"
#include "sound.hpp"
#include "tooltips.hpp"
#include "util.hpp"
#include "SDL_image.h"
@ -353,6 +354,8 @@ void display::redraw_everything()
if(update_locked())
return;
tooltips::clear_tooltips();
sideBarBgDrawn_ = false;
minimapDecorationsDrawn_ = false;
invalidate_all();
@ -421,6 +424,10 @@ void display::draw(bool update,bool force)
draw_sidebar();
int mousex, mousey;
const int mouse_flags = SDL_GetMouseState(&mousex,&mousey);
tooltips::process(mousex,mousey,mouse_flags & SDL_BUTTON_LMASK);
const int max_skips = 5;
const int time_between_draws = 20;
const int current_time = SDL_GetTicks();
@ -561,24 +568,18 @@ void display::draw_game_status(int x, int y)
details << "\n";
}
SDL_Rect clipRect;
clipRect.x = mapx();
clipRect.y = 0;
clipRect.w = this->x() - mapx();
clipRect.h = this->y();
SDL_Rect clipRect = screen_area();
gameStatusRect_ = font::draw_text(this,clipRect,14,font::NORMAL_COLOUR,
details.str(),x,y);
}
void display::draw_unit_details(int x, int y, const gamemap::location& loc,
const unit& u, SDL_Rect& description_rect, SDL_Rect& profile_rect)
const unit& u, SDL_Rect& description_rect, SDL_Rect& profile_rect,
SDL_Rect* clip_rect)
{
SDL_Rect clipRect;
clipRect.x = this->mapx();
clipRect.y = 0;
clipRect.w = this->x();
clipRect.h = this->y();
SDL_Rect clipRect = clip_rect != NULL ? *clip_rect : screen_area();
SDL_Surface* const background = getImage("misc/rightside.png",UNSCALED);
if(background == NULL)
@ -618,7 +619,7 @@ void display::draw_unit_details(int x, int y, const gamemap::location& loc,
std::stringstream details;
details << "+" << u.description() << "\n"
<< "+" << u.type().language_name()
<< "\n-(" << string_table["level"] << ""
<< "\n-(" << string_table["level"] << " "
<< u.type().level() << ")\n"
<< status << "\n"
<< unit_type::alignment_description(u.type().alignment())

View file

@ -96,7 +96,8 @@ public:
void remove_overlay(const gamemap::location& loc);
void draw_unit_details(int x, int y, const gamemap::location& loc,
const unit& u, SDL_Rect& description_rect, SDL_Rect& profile_rect);
const unit& u, SDL_Rect& description_rect, SDL_Rect& profile_rect,
SDL_Rect* clip_rect=NULL);
void update_display();

View file

@ -10,9 +10,12 @@
See the COPYING file for more details.
*/
#include "SDL_ttf.h"
#include "config.hpp"
#include "font.hpp"
#include "SDL_ttf.h"
#include "tooltips.hpp"
#include <cstdio>
#include <iostream>
@ -103,11 +106,11 @@ manager::~manager()
SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
COLOUR colour, const std::string& text, int x, int y,
SDL_Surface* bg)
SDL_Surface* bg, bool use_tooltips)
{
static const SDL_Color colours[] =
// neutral good bad
{ {0xFF,0xFF,0,0}, {0,0xFF,0,0}, {0xFF,0,0,0} };
// neutral good bad black
{ {0xFF,0xFF,0,0}, {0,0xFF,0,0}, {0xFF,0,0,0}, {0,0,0,0} };
const SDL_Color& col = colours[colour];
TTF_Font* const font = get_font(size);
@ -133,6 +136,19 @@ SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
dest.h = surface->h;
if(dest.x + dest.w > area.x + area.w) {
if(text.size() > 3) {
std::string txt = text;
if(std::count(txt.end()-3,txt.end(),'.') == 3) {
txt.erase(txt.end()-4);
} else {
tooltips::add_tooltip(dest,text);
std::fill(txt.end()-3,txt.end(),'.');
}
return draw_text_line(gui,area,size,colour,txt,x,y,bg,false);
}
dest.w = area.x + area.w - dest.x;
}
@ -147,13 +163,17 @@ SDL_Rect draw_text_line(display* gui, const SDL_Rect& area, int size,
SDL_BlitSurface(surface,&src,gui->video().getSurface(),&dest);
}
if(use_tooltips) {
tooltips::add_tooltip(dest,text);
}
return dest;
}
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
COLOUR colour, const std::string& txt, int x, int y,
SDL_Surface* bg)
SDL_Surface* bg, bool use_tooltips)
{
//make sure there's always at least a space, so we can ensure
//that we can return a rectangle for height
@ -170,7 +190,7 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
std::string::const_iterator i2 = std::find(i1,text.end(),'\n');
for(;;) {
if(i1 != i2) {
COLOUR col = NORMAL_COLOUR;
COLOUR col = colour;
int sz = size;
if(*i1 == '#') {
col = BAD_COLOUR;
@ -189,7 +209,8 @@ SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
if(i1 != i2) {
const std::string new_string(i1,i2);
const SDL_Rect rect =
draw_text_line(gui,area,sz,col,new_string,x,y,bg);
draw_text_line(gui,area,sz,col,new_string,x,y,bg,
use_tooltips);
if(rect.w > res.w)
res.w = rect.w;
res.h += rect.h;

View file

@ -27,10 +27,11 @@ struct manager {
~manager();
};
enum COLOUR { NORMAL_COLOUR, GOOD_COLOUR, BAD_COLOUR };
enum COLOUR { NORMAL_COLOUR, GOOD_COLOUR, BAD_COLOUR, BLACK_COLOUR };
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size, COLOUR colour,
const std::string& text, int x, int y, SDL_Surface* bg=NULL);
const std::string& text, int x, int y, SDL_Surface* bg=NULL,
bool use_tooltips=false);
}

View file

@ -17,6 +17,7 @@
#include "playlevel.hpp"
#include "language.hpp"
#include "sdl_utils.hpp"
#include "tooltips.hpp"
#include "widgets/button.hpp"
#include "widgets/textbox.hpp"
@ -667,9 +668,10 @@ int show_dialog(display& disp, SDL_Surface* image,
yloc+top_padding+image->h-6, NULL);
}
const int unitw = 200;
const int unith = disp.y()/2;
if(!units.empty()) {
const int unitw = 200;
const int unith = disp.y()/2;
draw_solid_tinted_rectangle(unitx,unity,unitw,unith,
0,0,0,1.0,scr);
draw_rectangle(unitx,unity,unitw,unith,border_colour,scr);
@ -764,9 +766,11 @@ int show_dialog(display& disp, SDL_Surface* image,
SDL_FillRect(screen,&unit_profile_rect,0);
}
SDL_Rect clip_rect = { unitx, unity, unitw, unith };
disp.draw_unit_details(unitx+left_padding,
unity+top_padding, gamemap::location(), units[selection],
unit_details_rect, unit_profile_rect);
unit_details_rect, unit_profile_rect, &clip_rect);
disp.update_display();
}
}

View file

@ -18,6 +18,7 @@
#include "preferences.hpp"
#include "replay.hpp"
#include "sound.hpp"
#include "tooltips.hpp"
#include <iostream>
@ -83,6 +84,7 @@ LEVEL_RESULT play_level(game_data& gameinfo, config& terrain_config,
display gui(units,video,map,status,teams);
const preferences::display_manager prefs_disp_manager(&gui);
const tooltips::manager tooltips_manager(gui);
if(recorder.skipping() == false) {
for(std::vector<config*>::iterator story_i = story.begin();

173
src/tooltips.cpp Normal file
View file

@ -0,0 +1,173 @@
#include "font.hpp"
#include "menu.hpp"
#include "tooltips.hpp"
#include "sdl_utils.hpp"
#include <vector>
namespace {
bool rectangles_overlap(const SDL_Rect& a, const SDL_Rect& b)
{
const bool xoverlap = a.x >= b.x && a.x < b.x + b.w ||
b.x >= a.x && b.x < a.x + a.w;
const bool yoverlap = a.y >= b.y && a.y < b.y + b.h ||
b.y >= a.y && b.y < a.y + a.h;
return xoverlap && yoverlap;
}
CVideo* video_ = NULL;
display* display_ = NULL;
struct tooltip
{
tooltip(const SDL_Rect& r, const std::string& msg) : rect(r), message(msg)
{}
SDL_Rect rect;
std::string message;
};
static const int font_size = 12;
std::vector<tooltip> tips;
std::string current_message;
SDL_Rect current_rect;
SDL_Surface* current_background = NULL;
SDL_Rect get_text_size(const std::string& msg)
{
SDL_Rect area = {0,0,1024,768};
return font::draw_text(NULL,area,font_size,font::BLACK_COLOUR,msg,0,0);
}
void clear_tooltip()
{
if(current_background == NULL)
return;
SDL_BlitSurface(current_background,NULL,video_->getSurface(),&current_rect);
SDL_FreeSurface(current_background);
current_background = NULL;
}
void draw_tooltip()
{
if(current_background != NULL)
clear_tooltip();
SDL_Surface* screen = video_->getSurface();
current_background = get_surface_portion(screen,current_rect);
if(current_background == NULL)
return;
gui::draw_solid_tinted_rectangle(current_rect.x,current_rect.y,
current_rect.w,current_rect.h,
180,180,0,1.0,screen);
gui::draw_rectangle(current_rect.x,current_rect.y,
current_rect.w-1,current_rect.h-1,0,screen);
SDL_Rect text_area = get_text_size(current_message);
text_area.x = current_rect.x + current_rect.w/2 - text_area.w/2;
text_area.y = current_rect.y + current_rect.h/2 - text_area.h/2;
font::draw_text(display_,text_area,font_size,font::BLACK_COLOUR,
current_message,text_area.x,text_area.y);
}
void show_tooltip(const tooltip& tip)
{
clear_tooltip();
const size_t xpadding = 10;
const size_t ypadding = 10;
SDL_Rect area = get_text_size(tip.message);
area.w += xpadding;
area.h += ypadding;
//see if there is enough room to fit it above the tip area
if(tip.rect.y > area.h)
area.y = tip.rect.y - area.h;
else if(tip.rect.y+tip.rect.h+area.h+1 < display_->y())
area.y = tip.rect.y + tip.rect.h;
else
return;
if(area.w >= display_->x())
return;
if(area.w/2 >= tip.rect.x + tip.rect.w/2)
area.x = 1;
else
area.x = tip.rect.x + tip.rect.w/2 - area.w/2;
if(area.x + area.w >= display_->x())
area.x = display_->x() - area.w - 1;
current_rect = area;
current_message = tip.message;
draw_tooltip();
}
}
namespace tooltips {
manager::manager(display& disp)
{
display_ = &disp;
video_ = &disp.video();
}
manager::~manager()
{
clear_tooltips();
display_ = NULL;
video_ = NULL;
}
void clear_tooltips()
{
clear_tooltip();
tips.clear();
current_message = "";
}
void add_tooltip(const SDL_Rect& rect, const std::string& message)
{
for(std::vector<tooltip>::iterator i = tips.begin(); i != tips.end(); ++i) {
if(rectangles_overlap(i->rect,rect)) {
*i = tooltip(rect,message);
return;
}
}
tips.push_back(tooltip(rect,message));
}
void process(int mousex, int mousey, bool lbutton)
{
for(std::vector<tooltip>::const_iterator i = tips.begin();
i != tips.end(); ++i) {
if(mousex > i->rect.x && mousey > i->rect.y &&
mousex < i->rect.x + i->rect.w && mousey < i->rect.y + i->rect.h) {
show_tooltip(*i);
return;
}
}
clear_tooltip();
}
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
font::COLOUR colour,
const std::string& text, int x, int y, SDL_Surface* bg)
{
return font::draw_text(gui,area,size,colour,text,x,y,bg,true);
}
}

29
src/tooltips.hpp Normal file
View file

@ -0,0 +1,29 @@
#ifndef TOOLTIPS_HPP_INCLUDED
#define TOOLTIPS_HPP_INCLUDED
#include "font.hpp"
#include "SDL.h"
#include "video.hpp"
namespace tooltips {
struct manager
{
manager(display& disp);
~manager();
};
void clear_tooltips();
void add_tooltip(const SDL_Rect& rect, const std::string& message);
void process(int mousex, int mousey, bool lbutton);
//a function exactly the same as font::draw_text, but will also register
//a tooltip
SDL_Rect draw_text(display* gui, const SDL_Rect& area, int size,
font::COLOUR colour,
const std::string& text, int x, int y, SDL_Surface* bg=NULL);
}
#endif