added tooltips for text that cannot fit
This commit is contained in:
parent
2fad190610
commit
35f11b1cee
9 changed files with 258 additions and 26 deletions
2
Makefile
2
Makefile
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
35
src/font.cpp
35
src/font.cpp
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
10
src/menu.cpp
10
src/menu.cpp
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
173
src/tooltips.cpp
Normal 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(),¤t_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
29
src/tooltips.hpp
Normal 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
|
Loading…
Add table
Reference in a new issue