Problem Textbox

Started by
12 comments, last by bobojoga 12 years, 3 months ago
It appears the bug is that the formulae for "Right" and "Centre" are swapped. I Still haven't tested the code though!
Advertisement
I tried to fix that formula, but still it doesn't work. When I compile your code, I get this error:

/home/joga/Documents/projektni_zadatak/test/src/test.cpp:35: error: 'Text::Alignment' is not a class or namespace
Yes. The alignment enum does not introduce a new name space, so the correct version would be Text::Centre rather that Text::Alignment::Centre.

I've actually gone and tested it this time:

text.hpp


#ifndef TEXT_HPP
#define TEXT_HPP

#include <string>
#include "SDL.h"
#include "SDL_ttf.h"

// Usually in a separate utility header
class noncopyable
{
protected:
noncopyable() {}
private:
// Deliberately private and unimplemented!
noncopyable(const noncopyable &);
noncopyable &operator=(const noncopyable &);
};

class Font : noncopyable
{
public:
Font(const std::string &font, int size);

~Font();

SDL_Surface *renderText(const std::string &text, const SDL_Color &colour) const;
bool sizeText(const std::string &text, int &width, int &height) const;

private:
TTF_Font *font;
};

class Text : noncopyable
{
public:
enum Alignment
{
Left, Right, Centre
};

Text(Font *font);
~Text();

void setText(const std::string &text);
void setAlignment(Alignment alignment);
void setColour(int r, int g, int b);

void draw(SDL_Surface *screen, int x, int y);

private:
Font *font;
SDL_Surface *message;
Alignment alignment;
SDL_Color colour;
std::string string;
};

#endif



text.cpp


#include "text.hpp"
#include <stdexcept>

Font::Font(const std::string &filename, int size)
{
font = TTF_OpenFont(filename.c_str(), size);
if(!font)
{
// Error handling
throw std::runtime_error(std::string("Failed to open font: ") + filename);
}
}

Font::~Font()
{
TTF_CloseFont(font);
}

SDL_Surface *Font::renderText(const std::string &text, const SDL_Color &colour) const
{
SDL_Surface *result = TTF_RenderText_Blended(font, text.c_str(), colour);
if(result == NULL)
{
// Error handling
throw std::runtime_error(std::string("Failed to render blended text: ") + text);
}
return result;
}

bool Font::sizeText(const std::string &text, int &width, int &height) const
{
int result = TTF_SizeText(font, text.c_str(), &width, &height);
return (result == 0);
}

Text::Text(Font *font)
:
font(font),
message(0),
alignment(alignment)
{
if(font == NULL)
{
// Error handling
throw std::runtime_error("Cannot construct Text will NULL Font");
}
colour.r = 0;
colour.g = 0;
colour.b = 0;
}

Text::~Text()
{
if(message)
{
SDL_FreeSurface(message);
}
}

Uint8 sanitiseColour(int component)
{
if(component < 0)
{
return 0;
}
else if(component > 0xff)
{
return 0xff;
}
return component;
}

void Text::setColour(int r, int g, int b)
{
colour.r = sanitiseColour(r);
colour.g = sanitiseColour(g);
colour.b = sanitiseColour(b);
}

void Text::setText(const std::string &text)
{
if(string == text)
{
return;
}
string = text;

SDL_Surface *temp = font->renderText(string, colour);
if(temp)
{
std::swap(temp, message);
SDL_FreeSurface(temp);
}
else
{
throw std::runtime_error(std::string("Failed to render text: ") + string);
// Error handling
}
}

void Text::setAlignment(Alignment alignment)
{
this->alignment = alignment;
}

void Text::draw(SDL_Surface *screen, int x, int y)
{
if(!message)
{
return;
}

int width = 0;
int height = 0;
bool result = font->sizeText(string, width, height);
if(!result)
{
// Error handling...
throw std::runtime_error(std::string("Failed to size text: ") + string);
}
SDL_Rect destination = { x, y };
switch(alignment)
{
case Left:
destination.x = x - width;
break;
case Right:
destination.x = x;
break;
case Centre:
destination.x = x - width / 2;
break;
default:
// Error handling...
throw std::runtime_error("Unknown alignment");
break;
}

if(SDL_BlitSurface(message, NULL, screen, &destination) < 0)
{
// Error handling
throw std::runtime_error("Failed to blit text");
}
}



main.cpp


#include <sstream>
#include <cstdlib>

#include "SDL.h"
#include "text.hpp"

int main( int argc, char* args[] )
{
if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
{
return 1;
}

std::atexit(&SDL_Quit);

if( TTF_Init() < 0)
{
return 1;
}

std::atexit(&TTF_Quit);

SDL_Surface *screen = SDL_SetVideoMode( 800, 600, 0, SDL_SWSURFACE);
if(!screen)
{
return 1;
}

Font font("lazy.ttf", 16);
Text text(&font);

text.setColour(0xff, 0x00, 0x00);
text.setAlignment(Text::Centre);
text.setText("FPS: ?");

int frames = 0;
Uint32 previousTime = SDL_GetTicks();

bool running = true;
while(running)
{
SDL_Event event;
while( SDL_PollEvent(&event) )
{
if( event.type == SDL_QUIT )
{
running = false;
}
else if(event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_DOWN:
case SDLK_UP:
text.setAlignment(Text::Centre);
break;
case SDLK_LEFT:
text.setAlignment(Text::Left);
break;
case SDLK_RIGHT:
text.setAlignment(Text::Right);
break;
case SDLK_ESCAPE:
running = false;
break;
}
}
}

++frames;
Uint32 now = SDL_GetTicks();
if(now - previousTime > 1000)
{
std::stringstream stream;
stream << "FPS: " << frames;
text.setText(stream.str().c_str());
frames = 0;
previousTime = now;
}

SDL_FillRect(screen, 0, 0);
text.draw(screen, screen->w / 2, screen->h / 2);

if( SDL_Flip( screen ) < 0 )
{
return 1;
}
}

return 0;
}



Not exhaustively, mind you. I threw in some very rudimentary error handling. I'm using lazy.ttf from here. I've also added a way to dynamically change the alignment, using the cursor keys.
Works like a charm. Thanks for help.

Edit: But the code you made is not and insert input textbox. I mean it does take inputs from key, but i need to get string from that textbox. Like login on websites or something like scanf function in c. I'll try use your code it and experiment with it.

This topic is closed to new replies.

Advertisement