00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004
00005 #include "CSTextarea.h"
00006 #include "CSBorder.h"
00007 #include "CSFont.h"
00008 #include "CSDesktop.h"
00009 #include "CSLAF.h"
00010
00011 const char *CSTextarea::CLASS = "CSTextarea";
00012
00013 CSTextarea::CSTextarea(int height, int width) : CSGrafikElement(height, width)
00014 {
00015 static char *functionName="CSTextarea";
00016 LOG_ENTER
00017 init("");
00018 LOG_EXIT
00019 }
00020
00021 CSTextarea::init(const std::string &text)
00022 {
00023 static char *functionName="init";
00024 LOG_ENTER
00025 CSLAF *laf = CSLAF::getCurrentLAF();
00026 mCursorRate = laf->getCursorRate();
00027
00028 mString = text;
00029 buildLines();
00030 mTickTimeNext = 0;
00031
00032 mCursorX = 0;
00033 mCursorY = 0;
00034 mVerticalDisplayStart = 0;
00035 mVerticalDisplayEnd = 0;
00036 mVerticalDisplayLengthChar = 0;
00037 mHorizontalDisplayStart = 0;
00038 mHorizontalDisplayEnd = 0;
00039 mHorizontalDisplayLengthChar = 0;
00040 mExactCursorX = 0;
00041 mExactCursorY = 0;
00042 mIsEditable = true;
00043 mCursorShown = false;
00044 setEnabled(false);
00045
00046 layoutSetup();
00047 LOG_EXIT
00048 }
00049
00050 void CSTextarea::setText(const std::string text)
00051 {
00052 static char *functionName="setText";
00053 mString = text;
00054 buildLines();
00055 }
00056
00057 void CSTextarea::buildLines()
00058 {
00059 static char *functionName="buildLines";
00060 mLines.add(mString);
00061 }
00062
00063 void CSTextarea::buildString()
00064 {
00065 static char *functionName="buildString";
00066 }
00067
00068
00069
00070 void CSTextarea::setGrafikCursor(int x, int y)
00071 {
00072 static char *functionName="setCursor";
00073 if (mCursorY>=0)
00074 {
00075 mLines.set(mCursorY, mWorkingString);
00076 }
00077
00078
00079 int yAdd = getFont()->getHeight() + getVerticalElementSpacing();
00080
00081
00082
00083
00084 mCursorY = y/yAdd + mVerticalDisplayStart;
00085 mExactCursorY = (mCursorY-mVerticalDisplayStart)*yAdd;
00086 mWorkingString = mLines.getString(mCursorY);
00087
00088 const char *s=mWorkingString.c_str();
00089 char test[2];
00090 test[1]=0;
00091 mExactCursorX = getHorizontalElementSpacing();
00092 mCursorX = mHorizontalDisplayStart;
00093 if (mCursorX > mWorkingString.size())
00094 {
00095 mCursorX = mWorkingString.size();
00096 if (mCursorX > 0)
00097 {
00098 mHorizontalDisplayStart = mCursorX-1;
00099 mExactCursorX += getFont()->getWidth(" ");
00100 }
00101 }
00102 int horizontalDisplayLengthPixel = getViewportWidth()-(getHorizontalElementSpacing());
00103 while (mCursorX < mWorkingString.length())
00104 {
00105 test[0] = s[mCursorX];
00106 int size = getFont()->getWidth(test);
00107 if ((mExactCursorX + size > x) || (mExactCursorX + size > horizontalDisplayLengthPixel))
00108 {
00109 break;
00110 }
00111 mExactCursorX += size;
00112 mCursorX++;
00113 }
00114 if (mCursorX <0)
00115 {
00116 mCursorX = 0;
00117 }
00118 }
00119
00120
00121 void CSTextarea::setTextCursor(int x, int y)
00122 {
00123 static char *functionName="setCursor";
00124 if (mCursorY>=0)
00125 {
00126 mLines.set(mCursorY, mWorkingString);
00127 }
00128
00129 int yAdd = getFont()->getHeight() + getVerticalElementSpacing();
00130 int xAdd = getFont()->getWidth(" ");
00131 mCursorY = y;
00132
00133
00134 mVerticalDisplayLengthChar = getViewportHeight() / yAdd;
00135 if (mCursorY < mVerticalDisplayStart)
00136 {
00137 mVerticalDisplayStart = mCursorY;
00138 mVerticalDisplayEnd = mVerticalDisplayStart + mVerticalDisplayLengthChar;
00139 if (mVerticalDisplayEnd > mLines.getSize())
00140 {
00141 mVerticalDisplayEnd = mLines.getSize();
00142 }
00143 }
00144 mVerticalDisplayEnd = mVerticalDisplayStart + mVerticalDisplayLengthChar;
00145 if (mCursorY > mVerticalDisplayEnd-1)
00146 {
00147 mVerticalDisplayEnd = mCursorY+1;
00148 mVerticalDisplayStart = mVerticalDisplayEnd - (mVerticalDisplayLengthChar);
00149 if (mVerticalDisplayStart < 0)
00150 {
00151 mVerticalDisplayStart = 0;
00152 }
00153 }
00154
00155
00156 mExactCursorY = (mCursorY-mVerticalDisplayStart)*yAdd;
00157 mWorkingString = mLines.getString(mCursorY);
00158 const char *s=mWorkingString.c_str();
00159 char test[2];
00160 test[1]=0;
00161 mExactCursorX = getHorizontalElementSpacing();
00162 int pos = 0;
00163 while ((pos < x) && (pos < mWorkingString.length()))
00164 {
00165 test[0] = s[pos];
00166 int size = getFont()->getWidth(test);
00167 mExactCursorX += size;
00168 pos++;
00169 }
00170 mCursorX = pos--;
00171
00172
00173 mHorizontalDisplayLengthChar = (getViewportWidth()-(2*getHorizontalElementSpacing())) / xAdd;
00174 if (mCursorX < mHorizontalDisplayStart)
00175 {
00176 mHorizontalDisplayStart = mCursorX;
00177 }
00178 mHorizontalDisplayEnd = mHorizontalDisplayStart + mHorizontalDisplayLengthChar;
00179 if (mCursorX > mHorizontalDisplayEnd-1)
00180 {
00181 mHorizontalDisplayEnd = mCursorX+1;
00182 mHorizontalDisplayStart = mHorizontalDisplayEnd - (mHorizontalDisplayLengthChar);
00183 if (mHorizontalDisplayStart < 0)
00184 {
00185 mHorizontalDisplayStart = 0;
00186 }
00187 }
00188
00189 mExactCursorX = (mCursorX-mHorizontalDisplayStart)*xAdd + getHorizontalElementSpacing();
00190 }
00191
00192 void CSTextarea::putString(SDL_Surface *destination, SDL_Rect *viewport, int x, int y, const std::string &string)
00193 {
00194 static char *functionName="putString";
00195 x += viewport->x;
00196 y += viewport->y;
00197 getFont()->putString(destination,x,y,getTextColor(), string);
00198 }
00199
00200 void CSTextarea::paint(SDL_Surface *destination, SDL_Rect *parentViewport)
00201 {
00202 static char *functionName="paint";
00203 CSLAF *laf = CSLAF::getCurrentLAF();
00204 float currentTick = SDL_GetTicks() + mCursorRate;
00205 if (currentTick > mTickTimeNext)
00206 {
00207 mTickTimeNext = currentTick + mCursorRate;
00208 mCursorShown = !mCursorShown;
00209 }
00210
00211 SDL_Rect thisViewportArea;
00212 thisViewportArea.x = parentViewport->x + getViewportX() + getX();
00213 thisViewportArea.y = parentViewport->y + getViewportY() + getY();
00214 thisViewportArea.h = getViewportHeight();
00215 thisViewportArea.w = getViewportWidth();
00216
00217 int x = getHorizontalElementSpacing();
00218 int y = 0;
00219
00220 int yAdd = getFont()->getHeight() + getVerticalElementSpacing();
00221 int xAdd = getFont()->getWidth(" ");
00222
00223 mVerticalDisplayLengthChar = getViewportHeight() / yAdd;
00224
00225 if (mCursorY < mVerticalDisplayStart)
00226 {
00227 mVerticalDisplayStart = mCursorY;
00228 mVerticalDisplayEnd = mVerticalDisplayStart + mVerticalDisplayLengthChar;
00229 if (mVerticalDisplayEnd > mLines.getSize())
00230 {
00231 mVerticalDisplayEnd = mLines.getSize();
00232 }
00233 }
00234 mVerticalDisplayEnd = mVerticalDisplayStart + mVerticalDisplayLengthChar;
00235 if (mCursorY > mVerticalDisplayEnd-1)
00236 {
00237 mVerticalDisplayEnd = mCursorY+1;
00238 mVerticalDisplayStart = mVerticalDisplayEnd - (mVerticalDisplayLengthChar);
00239 if (mVerticalDisplayStart < 0)
00240 {
00241 mVerticalDisplayStart = 0;
00242 }
00243 }
00244
00245
00246 mHorizontalDisplayLengthChar = (getViewportWidth()-(2*(getHorizontalElementSpacing()))) / xAdd;
00247 if (mCursorX < mHorizontalDisplayStart)
00248 {
00249 mHorizontalDisplayStart = mCursorX;
00250 mHorizontalDisplayEnd = mHorizontalDisplayStart + mHorizontalDisplayLengthChar;
00251 }
00252 mHorizontalDisplayEnd = mHorizontalDisplayStart + mHorizontalDisplayLengthChar;
00253 if (mCursorX > mHorizontalDisplayEnd-1)
00254 {
00255 mHorizontalDisplayEnd = mCursorX+1;
00256 mHorizontalDisplayStart = mHorizontalDisplayEnd - (mHorizontalDisplayLengthChar);
00257 if (mHorizontalDisplayStart < 0)
00258 {
00259 mHorizontalDisplayStart = 0;
00260 }
00261 }
00262
00263
00264 for (int i = mVerticalDisplayStart; i < mVerticalDisplayEnd; i++)
00265 {
00266 if (((i!= mCursorY) || (!getFocused())) || (!mIsEditable))
00267 {
00268 if (mLines.getString(i).size() >=mHorizontalDisplayStart)
00269 {
00270 std::string t = mLines.getString(i).substr(mHorizontalDisplayStart, mHorizontalDisplayLengthChar);
00271 putString(destination, &thisViewportArea, x, y, t);
00272
00273 }
00274 }
00275 else
00276 {
00277 if (mWorkingString.size() >=mHorizontalDisplayStart)
00278 {
00279 std::string t = mWorkingString.substr(mHorizontalDisplayStart, mHorizontalDisplayLengthChar);
00280 putString(destination, &thisViewportArea, x, y, t);
00281 }
00282 }
00283 y += yAdd;
00284 }
00285
00286 if ((getFocused() && (mCursorShown)) && (mIsEditable))
00287 {
00288 line(destination, &thisViewportArea,
00289 mExactCursorX, mExactCursorY,
00290 mExactCursorX, mExactCursorY+getFont()->getHeight(),
00291 laf->getTextAreaCursorColor());
00292 }
00293 }
00294
00295 void CSTextarea::deleteCharAtPos(int p)
00296 {
00297 std::string t1 = mWorkingString.substr(0, p);
00298 std::string t2 = mWorkingString.substr(p+1, mWorkingString.length());
00299 mWorkingString = t1+t2;
00300 }
00301
00302 void CSTextarea::insertCharAtPos(int p, char ch)
00303 {
00304 std::string t1 = mWorkingString.substr(0, p);
00305 std::string t2 = mWorkingString.substr(p, mWorkingString.length());
00306 mWorkingString = t1+ch+t2;
00307 }
00308
00309 void CSTextarea::reactOnMessage(CSMessage *message)
00310 {
00311 reactOnMessageTextarea(message);
00312 }
00313
00314 void CSTextarea::reactOnMessageTextarea(CSMessage *message)
00315 {
00316 static char *functionName="reactOnMessage";
00317 if (message->mIsHandled)
00318 {
00319 reactOnMessageGrafikElement(message);
00320 return;
00321 }
00322 switch (message->getType())
00323 {
00324 case GUI_MESSAGE:
00325 {
00326 GuiMessage *gm = (GuiMessage *) message;
00327 if (gm->receiver != this)
00328 {
00329 break;
00330 }
00331 else
00332 {
00333 switch (message->getSubtype())
00334 {
00335 case MOUSE_BUTTON_RELEASED_MESSAGE:
00336 {
00337 int x,y;
00338 if (mIsEditable)
00339 {
00340 x = gm->receiverX;
00341 y = gm->receiverY;
00342 setGrafikCursor(x,y);
00343 gm->mIsHandled = true;
00344 }
00345 break;
00346 }
00347
00348 case FOCUS_GAINED_MESSAGE:
00349 {
00350 if (mIsEditable)
00351 {
00352 setEnabled(true);
00353 if (mCursorY>=0)
00354 {
00355 mLines.set(mCursorY, mWorkingString);
00356 }
00357 gm->mIsHandled = true;
00358 }
00359 break;
00360 }
00361
00362 case FOCUS_LOST_MESSAGE:
00363 {
00364 if (mIsEditable)
00365 {
00366 setEnabled(false);
00367 }
00368
00369 mWorkingString = mLines.getString(mCursorY);
00370 gm->mIsHandled = true;
00371 break;
00372 }
00373
00374 case KEY_RELEASED_MESSAGE:
00375 {
00376 gm->mIsHandled = false;
00377 break;
00378 }
00379
00380 case KEY_PRESSED_MESSAGE:
00381 {
00382 int ch=gm->keyUnicodeChar;
00383 if (gm->keySymbolic == SDLK_TAB)
00384 {
00385 getDesktop()->focusedNextComponent();
00386 gm->mIsHandled = true;
00387 break;
00388 }
00389 if (gm->keySymbolic == SDLK_DELETE)
00390 {
00391 if (mCursorX<mWorkingString.length())
00392 {
00393 deleteCharAtPos(mCursorX);
00394 setTextCursor(mCursorX, mCursorY);
00395 }
00396 else
00397 {
00398 if (mCursorY<mLines.getSize())
00399 {
00400 mWorkingString += mLines.getString(mCursorY+1);
00401 mLines.remove(mCursorY+1);
00402 setTextCursor(mCursorX, mCursorY);
00403 }
00404 }
00405 gm->mIsHandled = true;
00406 break;
00407 }
00408
00409 if (gm->keySymbolic == SDLK_BACKSPACE)
00410 {
00411 if (mCursorX>0)
00412 {
00413 deleteCharAtPos(mCursorX-1);
00414 setTextCursor(mCursorX-1, mCursorY);
00415 }
00416 else
00417 {
00418 if (mCursorY>0)
00419 {
00420 setTextCursor(mCursorX, mCursorY-1);
00421 mCursorX = mWorkingString.length();
00422
00423 mWorkingString += mLines.getString(mCursorY+1);
00424 mLines.remove(mCursorY+1);
00425 setTextCursor(mCursorX, mCursorY);
00426 }
00427 }
00428 gm->mIsHandled = true;
00429 break;
00430 }
00431 if ((gm->keySymbolic == SDLK_RETURN) || (gm->keySymbolic == SDLK_KP_ENTER))
00432 {
00433 std::string t1 = mWorkingString.substr(0, mCursorX);
00434 std::string t2 = mWorkingString.substr(mCursorX, mWorkingString.length()-t1.length());
00435 mWorkingString = t1;
00436 mLines.insert(mCursorY+1,t2);
00437 mCursorX=0;
00438 setTextCursor(mCursorX, mCursorY+1);
00439 gm->mIsHandled = true;
00440 break;
00441 }
00442
00443 if (gm->keySymbolic == SDLK_UP)
00444 {
00445 if (mCursorY>0)
00446 {
00447 setTextCursor(mCursorX, mCursorY-1);
00448 }
00449 gm->mIsHandled = true;
00450 break;
00451 }
00452
00453 if (gm->keySymbolic == SDLK_DOWN)
00454 {
00455 if (mCursorY+1<mLines.getSize())
00456 {
00457 setTextCursor(mCursorX, mCursorY+1);
00458 }
00459 gm->mIsHandled = true;
00460 break;
00461 }
00462
00463 if (gm->keySymbolic == SDLK_LEFT)
00464 {
00465 if (mCursorX>0)
00466 {
00467 setTextCursor(mCursorX-1, mCursorY);
00468 }
00469 gm->mIsHandled = true;
00470 break;
00471 }
00472
00473 if (gm->keySymbolic == SDLK_RIGHT)
00474 {
00475 if (mCursorX<mWorkingString.length())
00476 {
00477 setTextCursor(mCursorX+1, mCursorY);
00478 }
00479 gm->mIsHandled = true;
00480 break;
00481 }
00482
00483 if (gm->keySymbolic == SDLK_HOME)
00484 {
00485 setTextCursor(0, mCursorY);
00486 gm->mIsHandled = true;
00487 break;
00488 }
00489
00490 if (gm->keySymbolic == SDLK_END)
00491 {
00492 setTextCursor(mWorkingString.length(), mCursorY);
00493 gm->mIsHandled = true;
00494 break;
00495 }
00496 if ((ch>31) && (ch<128))
00497 {
00498 int len = mWorkingString.length();
00499 insertCharAtPos(mCursorX, ch);
00500 setTextCursor(mCursorX+1, mCursorY);
00501 gm->mIsHandled = true;
00502 break;
00503 }
00504
00505 break;
00506 }
00507
00508 }
00509 }
00510 }
00511 }
00512 reactOnMessageGrafikElement(message);
00513 }
00514
00515 void CSTextarea::layoutSetupTextarea()
00516 {
00517 static char *functionName="layoutSetupTextarea";
00518 LOG_ENTER
00519 CSLAF *laf = CSLAF::getCurrentLAF();
00520 mMinHeight = mHeight - getBorder()->getTotalHeight() - getInset().getTotalHeight();
00521 mMinWidth = mWidth - getBorder()->getTotalWidth() - getInset().getTotalWidth();
00522
00523 LOG_EXIT
00524 }
00525
00526