00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00049 void EditWidget::InitGump(Gump* newparent, bool take_focus)
00050 {
00051 Gump::InitGump(newparent, take_focus);
00052
00053 Pentagram::Font *font = getFont();
00054
00055
00056 dims.y = -font->getBaseline();
00057
00058
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
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
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
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 }