00001 #include "glwx.h"
00002
00003 GUITextBox::GUITextBox(const std::string &callback, const std::string &text) : GUIAlphaElement(callback)
00004
00005 {
00006 setBordersColor(0.3f, 0.3f, 0.3f);
00007 setDimensions(80, 18);
00008 setPadding(2, 2);
00009 setColor(0.5f, 0.5f, 0.5f);
00010 label.setString(text);
00011
00012 blinkerPosition = 2;
00013 blinkerTimer = 0.0f;
00014 blinkerOn = false;
00015
00016 textStartIndex = 0;
00017 textEndIndex = 0;
00018
00019 dimensions.y = GUIFontManager::getDefaultFont() ?
00020 GUIFontManager::getDefaultFont()->getFontObject()->getHeight() + padding.y : dimensions.y;
00021 widgetType = WT_TEXT_BOX;
00022 }
00023
00024 bool GUITextBox::loadXMLSettings(const TiXmlElement* element)
00025 {
00026 if(!XMLArbiter::inspectElementInfo(element, "TextBox"))
00027 return Logger::writeErrorLog("Need a TextBox node in the xml file");
00028
00029 setBordersColor(XMLArbiter::fillComponents3f(XMLArbiter::getChildElementByName(element, "BordersColor"),bordersColor));
00030 return GUIAlphaElement::loadXMLSettings(element);
00031 return false;
00032 }
00033
00034 void GUITextBox::setBordersColor(const Tuple3f& color)
00035 {
00036 setBordersColor(color.x, color.y, color.z);
00037 }
00038
00039 const Tuple3f &GUITextBox::getBordersColor() const
00040 {
00041 return bordersColor;
00042 }
00043
00044 void GUITextBox::setBordersColor(float r, float g, float b)
00045 {
00046 bordersColor.set(clamp(r, 0.0f, 255.0f),
00047 clamp(g, 0.0f, 255.0f),
00048 clamp(b, 0.0f, 255.0f));
00049 bordersColor.x /= (bordersColor.x > 1.0) ? 255.0f : 1.0f;
00050 bordersColor.y /= (bordersColor.y > 1.0) ? 255.0f : 1.0f;
00051 bordersColor.z /= (bordersColor.z > 1.0) ? 255.0f : 1.0f;
00052 }
00053
00054 void GUITextBox::setPadding(const Tuple2i& p)
00055 {
00056 setPadding(p.x, p.y);
00057 }
00058
00059 void GUITextBox::setPadding(int x, int y)
00060 {
00061 padding.set(clamp(x, 0, 25),
00062 clamp(y, 0, 25));
00063 }
00064
00065 const Tuple2i &GUITextBox::getPadding() const
00066 {
00067 return padding;
00068 }
00069
00070 void GUITextBox::render(float clockTick)
00071 {
00072 if(!parent || !visible)
00073 return;
00074
00075 modifyCurrentAlpha(clockTick);
00076 getWindowBounds();
00077
00078 size_t realBlinkerPosition = clamp(blinkerPosition, size_t(windowBounds.x + padding.x),
00079 size_t(windowBounds.z - padding.x));
00080 blinkerTimer += clockTick;
00081 blinkerTimer -= blinkerTimer > 1.0f ? 1.0f : 0.0f;
00082
00083 glEnable(GL_BLEND);
00084 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00085 glColor4fv(color);
00086
00087 glBegin(GL_TRIANGLE_STRIP);
00088 glVertex2i(windowBounds.x, windowBounds.y);
00089 glVertex2i(windowBounds.x, windowBounds.w);
00090 glVertex2i(windowBounds.z + padding.x, windowBounds.y);
00091 glVertex2i(windowBounds.z + padding.x, windowBounds.w);
00092 glEnd();
00093
00094 glColor3fv(bordersColor);
00095 glBegin(GL_LINE_LOOP);
00096 glVertex2i(windowBounds.x, windowBounds.y);
00097 glVertex2i(windowBounds.x, windowBounds.w);
00098 glVertex2i(windowBounds.z + padding.x, windowBounds.w);
00099 glVertex2i(windowBounds.z + padding.x, windowBounds.y);
00100 glEnd();
00101 glDisable(GL_BLEND);
00102
00103 label.print(windowBounds.x + padding.x, windowBounds.y, int(textStartIndex), int(textEndIndex));
00104
00105 if(blinkerOn && (blinkerTimer > 0.5f))
00106 {
00107 glColor3fv(label.getColor());
00108 glBegin(GL_LINES);
00109 glVertex2i((int)realBlinkerPosition, windowBounds.y + padding.y/2);
00110 glVertex2i((int)realBlinkerPosition, windowBounds.w - padding.y);
00111 glEnd();
00112 glColor3f(1,1,1);
00113 }
00114 }
00115
00116 void GUITextBox::checkMouseEvents(MouseEvent &newEvent, int extraInfo, bool reservedBits)
00117 {
00118 bool nRelease = pressed;
00119
00120 GUIRectangle::checkMouseEvents(newEvent, extraInfo, true);
00121
00122 if(mouseOver && (clicked || pressed))
00123 setupBlinker(newEvent.getX());
00124
00125 clicked = false;
00126 released = false;
00127 blinkerOn = focused ? blinkerOn : false;
00128 }
00129
00130 void GUITextBox::checkKeyboardEvents(KeyEvent &evt, int extraInfo)
00131 {
00132 if(!focused || !active)
00133 return;
00134
00135 if((evt.getKeyID() >= 32 && evt.getKeyID() <= 127) ||
00136 (evt.getKeyID() == 8));
00137 else
00138 extraInfo = 0;
00139
00140 if(extraInfo == KE_PRESSED)
00141 {
00142 size_t length = label.getString().size();
00143
00144
00145 if(evt.displayable())
00146 setupText(TE_INSERT_CHAR, evt.getKeyChar());
00147
00148 if(length)
00149 {
00150 switch(evt.getKeyID())
00151 {
00152 case 8: setupText(TE_BACKSPACE_DELETE); break;
00153 case 127: setupText(TE_SIMPLE_DELETE); break;
00154 }
00155 }
00156
00157
00158
00159
00160 evt.setUsed(true);
00161
00162 }
00163
00164 label.forceUpdate(true);
00165 update = true;
00166 }
00167
00168 void GUITextBox::setupBlinker(size_t x)
00169 {
00170 if(!focused || !active)
00171 return;
00172
00173 GUIFont *font = GUIFontManager::getFont(label.getFontIndex());
00174 const std::string &string = label.getString();
00175 const int *spaces = NULL;
00176 blinkerPosition = getWindowBounds().x + padding.x;
00177 x -= 1;
00178
00179 if(font)
00180 {
00181 spaces = font->getFontObject()->getCharHorizontalGlyphs();
00182
00183 for(size_t i = 0; i < string.size(); i++)
00184 if(blinkerPosition < x)
00185 blinkerPosition += spaces[int(string[i])];
00186 }
00187
00188 blinkerOn = true;
00189 }
00190
00191 void GUITextBox::setupText(int type, char Char)
00192 {
00193 GUIFont *font = GUIFontManager::getFont(label.getFontIndex());
00194 const int *spaces = font ? font->getFontObject()->getCharHorizontalGlyphs() : NULL;
00195 std::string temp;
00196 size_t length = label.getString().size(),
00197 start = windowBounds.x + padding.x,
00198 index = 0;
00199
00200 if(!spaces)
00201 return;
00202
00203 for(size_t t = 0; t < length; t++)
00204 {
00205 if(blinkerPosition > start)
00206 {
00207 index++;
00208 start += spaces[label.getString()[t]];
00209 }
00210 }
00211
00212 if(type == TE_INSERT_CHAR)
00213 {
00214 if(index != length && length)
00215 {
00216 std::string leftSide;
00217 leftSide = label.getString().substr(0, index);
00218 leftSide += Char;
00219
00220 temp = label.getString().substr(index, length - index);
00221 label.setString(leftSide + temp);
00222 }
00223 else
00224 {
00225 temp = label.getString();
00226 temp += Char;
00227 label.setString(temp);
00228 }
00229 blinkerPosition = blinkerPosition + GUIFontManager::getCharacterWidth(Char, font);
00230 }
00231
00232 if(type == TE_BACKSPACE_DELETE && (blinkerPosition != windowBounds.x + padding.x))
00233 {
00234 if(index != length)
00235 {
00236 std::string leftSide;
00237 setupBlinker(blinkerPosition - GUIFontManager::getCharacterWidth(label.getString()[index -1],
00238 label.getFontIndex()));
00239
00240 leftSide = label.getString().substr(0, index - 1);
00241 temp = label.getString().substr(index, length - index);
00242 label.setString(leftSide + temp);
00243 return;
00244 }
00245
00246 setupBlinker(blinkerPosition - GUIFontManager::getCharacterWidth(label.getString()[length -1],
00247 font));
00248
00249 temp = label.getString().substr(0, length - 1);
00250
00251 if(temp.size())
00252 label.setString(temp);
00253 else
00254 {
00255 label.clear();
00256 blinkerPosition = windowBounds.x + padding.x;
00257 }
00258 }
00259
00260 if(type == TE_SIMPLE_DELETE && length)
00261 {
00262 if((blinkerPosition == windowBounds.x + padding.x) && (length == 1))
00263 {
00264 label.clear();
00265 return;
00266 }
00267
00268 if(index < length)
00269 {
00270 std::string leftSide;
00271 leftSide = label.getString().substr(0, index);
00272 temp = label.getString().substr(index + 1, length - index - 1);
00273 label.setString(leftSide + temp);
00274 }
00275 }
00276 if(type == TE_PARSE_VISIBLE)
00277 textEndIndex = font->getFontObject()->getMaxFittingLength(label.getString(), getWidth());
00278 }
00279
00280 const Tuple4i &GUITextBox::getWindowBounds()
00281 {
00282 if(parent && update)
00283 {
00284 label.computeDimensions();
00285 dimensions.y = label.getHeight() ? label.getHeight() + padding.y : dimensions.y;
00286
00287 GUIRectangle::computeWindowBounds();
00288 blinkerPosition = !blinkerPosition ? windowBounds.x + padding.x : blinkerPosition;
00289 setupText(TE_PARSE_VISIBLE);
00290 }
00291 return windowBounds;
00292 }