EditWidget.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2005-2006  The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 #include "pent_include.h"
00019 #include "EditWidget.h"
00020 #include "ShapeFont.h"
00021 #include "RenderedText.h"
00022 #include "RenderSurface.h"
00023 #include "FontManager.h"
00024 #include "IDataSource.h"
00025 #include "ODataSource.h"
00026 #include "TTFont.h"
00027 #include "encoding.h"
00028 
00029 #include "SDL.h"
00030 
00031 DEFINE_RUNTIME_CLASSTYPE_CODE(EditWidget,Gump);
00032 
00033 EditWidget::EditWidget(int X, int Y, std::string txt, bool gamefont_, int font,
00034                                            int w, int h, unsigned int maxlength_, bool multiline_)
00035         : Gump(X, Y, w, h), text(txt), gamefont(gamefont_), fontnum(font),
00036           maxlength(maxlength_), multiline(multiline_),
00037           cursor_changed(0), cursor_visible(true), cached_text(0)
00038 {
00039         cursor = text.size();
00040 }
00041 
00042 EditWidget::~EditWidget(void)
00043 {
00044         delete cached_text;
00045         cached_text = 0;
00046 }
00047 
00048 // Init the gump, call after construction
00049 void EditWidget::InitGump(Gump* newparent, bool take_focus)
00050 {
00051         Gump::InitGump(newparent, take_focus);
00052 
00053         Pentagram::Font *font = getFont();
00054 
00055         // Y offset is always baseline
00056         dims.y = -font->getBaseline();
00057 
00058         // No X offset
00059         dims.x = 0;
00060 
00061         if (gamefont && getFont()->isHighRes()) 
00062         {
00063                 int x = 0, y = 0, w = 0;
00064                 ScreenSpaceToGumpRect(x, y, w, dims.y, ROUND_OUTSIDE);
00065         }
00066 }
00067 
00068 Pentagram::Font* EditWidget::getFont() const
00069 {
00070         if (gamefont)
00071                 return FontManager::get_instance()->getGameFont(fontnum, true);
00072         else
00073                 return FontManager::get_instance()->getTTFont(fontnum);
00074 }
00075 
00076 void EditWidget::setText(const std::string& t)
00077 {
00078         text = t;
00079         cursor = text.size();
00080         FORGET_OBJECT(cached_text);
00081 }
00082 
00083 void EditWidget::ensureCursorVisible()
00084 {
00085         cursor_visible = true;
00086         cursor_changed = SDL_GetTicks();
00087 }
00088 
00089 bool EditWidget::textFits(std::string& t)
00090 {
00091         Pentagram::Font *font = getFont();
00092         
00093         unsigned int remaining;
00094         int width, height;
00095 
00096         int max_width = multiline ? dims.w : 0;
00097         int max_height = dims.h;
00098         if (gamefont && font->isHighRes()) {
00099                 int x = 0, y = 0;
00100                 GumpRectToScreenSpace(x, y, max_width, max_height, ROUND_INSIDE);
00101         }
00102 
00103         font->getTextSize(t, width, height, remaining,
00104                                           max_width, max_height,
00105                                           Pentagram::Font::TEXT_LEFT, false);
00106 
00107         if (gamefont && font->isHighRes()) {
00108                 int x = 0, y = 0;
00109                 ScreenSpaceToGumpRect(x, y, width, height, ROUND_OUTSIDE);
00110         }
00111 
00112         if (multiline)
00113                 return (remaining >= t.size());
00114         else
00115                 return (width <= dims.w);
00116 }
00117 
00118 void EditWidget::renderText()
00119 {
00120         bool cv = cursor_visible;
00121         if (!IsFocus()) {
00122                 cv = false;
00123         } else {
00124                 uint32 now = SDL_GetTicks();
00125                 if (now > cursor_changed + 750) {
00126                         cv = !cursor_visible;
00127                         cursor_changed = now;
00128                 }
00129         }
00130 
00131         if (cv != cursor_visible) {
00132                 FORGET_OBJECT(cached_text);
00133                 cursor_visible = cv;
00134         }
00135 
00136         if (!cached_text) {
00137                 Pentagram::Font *font = getFont();
00138 
00139                 int max_width = multiline ? dims.w : 0;
00140                 int max_height = dims.h;
00141                 if (gamefont && font->isHighRes()) {
00142                         int x = 0, y = 0;
00143                         GumpRectToScreenSpace(x, y, max_width, max_height, ROUND_INSIDE);
00144                 }
00145 
00146                 unsigned int remaining;
00147                 cached_text = font->renderText(text, remaining,
00148                                                                            max_width, max_height,
00149                                                                            Pentagram::Font::TEXT_LEFT,
00150                                                                            false, cv ? cursor : std::string::npos);
00151         }
00152 }
00153 
00154 // Overloadable method to Paint just this Gump (RenderSurface is relative to this)
00155 void EditWidget::PaintThis(RenderSurface*surf, sint32 lerp_factor, bool scaled)
00156 {
00157         Gump::PaintThis(surf,lerp_factor, scaled);
00158 
00159         renderText();
00160 
00161         if (scaled && gamefont && getFont()->isHighRes())
00162         {
00163                 surf->FillAlpha(0xFF,dims.x,dims.y,dims.w, dims.h);
00164                 return;
00165         }
00166 
00167         cached_text->draw(surf, 0, 0);
00168 }
00169 
00170 // Overloadable method to Paint just this gumps unscaled components that require compositing (RenderSurface is relative to parent).
00171 void EditWidget::PaintComposited(RenderSurface* surf, sint32 lerp_factor, sint32 sx, sint32 sy)
00172 {
00173         Pentagram::Font *font = getFont();
00174 
00175         if (!gamefont || !font->isHighRes()) return;
00176 
00177         int x=0,y=0;
00178         GumpToScreenSpace(x,y,ROUND_BOTTOMRIGHT);
00179 
00180         cached_text->draw(surf, x, y, true);
00181 
00182         x=dims.x; y=dims.y;
00183         int w=dims.w, h=dims.h;
00184         GumpRectToScreenSpace(x, y, w, h, ROUND_OUTSIDE);
00185         surf->FillAlpha(0x00, x, y, w, h);
00186 }
00187 
00188 // don't handle any mouse motion events, so let parent handle them for us.
00189 Gump* EditWidget::OnMouseMotion(int mx, int my)
00190 {
00191         return 0;
00192 }
00193 
00194 bool EditWidget::OnKeyDown(int key, int mod)
00195 {
00196         switch (key) {
00197         case SDLK_RETURN:
00198         case SDLK_KP_ENTER:
00199                 parent->ChildNotify(this, EDIT_ENTER);
00200                 break;
00201         case SDLK_ESCAPE:
00202                 parent->ChildNotify(this, EDIT_ESCAPE);
00203                 break;
00204         case SDLK_BACKSPACE:
00205                 if (cursor > 0) {
00206                         text.erase(--cursor, 1);
00207                         FORGET_OBJECT(cached_text);
00208                         ensureCursorVisible();
00209                 }
00210                 break;
00211         case SDLK_DELETE:
00212                 if (cursor != text.size()) {
00213                         text.erase(cursor, 1);
00214                         FORGET_OBJECT(cached_text);
00215                 }
00216                 break;
00217         case SDLK_LEFT:
00218                 if (cursor > 0) {
00219                         cursor--;
00220                         FORGET_OBJECT(cached_text);
00221                         ensureCursorVisible();
00222                 }
00223                 break;
00224         case SDLK_RIGHT:
00225                 if (cursor < text.size()) {
00226                         cursor++;
00227                         FORGET_OBJECT(cached_text);
00228                         ensureCursorVisible();
00229                 }
00230                 break;
00231         default:
00232                 break;
00233         }
00234 
00235         return true;
00236 }
00237 
00238 bool EditWidget::OnKeyUp(int key)
00239 {
00240         return true;
00241 }
00242 
00243 
00244 bool EditWidget::OnTextInput(int unicode)
00245 {
00246         if (maxlength > 0 && text.size() >= maxlength)
00247                 return true;
00248 
00249         char c = 0;
00250         if (unicode >= 0 && unicode < 256)
00251                 c = Pentagram::reverse_encoding[unicode];
00252         if (!c) return true;
00253 
00254         std::string newtext = text;
00255         newtext.insert(cursor, 1, c);
00256 
00257         if (textFits(newtext)) {
00258                 text = newtext;
00259                 cursor++;
00260                 FORGET_OBJECT(cached_text);
00261         }
00262 
00263         return true;
00264 }

Generated on Fri Jul 27 22:27:14 2007 for pentagram by  doxygen 1.4.7