00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <GLW/GLWListView.h>
00022 #include <GLW/GLWFont.h>
00023 #include <GLW/GLWTranslate.h>
00024 #include <common/Defines.h>
00025 #include <client/ScorchedClient.h>
00026 #include <engine/GameState.h>
00027 #include <stdio.h>
00028
00029 static const float BorderWidth = 20.0f;
00030
00031 REGISTER_CLASS_SOURCE(GLWListView);
00032
00033 unsigned GLWListView::WordEntry::wordRefCount_ = 1;
00034
00035 GLWListView::GLWListView(float x, float y, float w, float h,
00036 int maxLen, float textSize, float scrollSpeed) :
00037 GLWidget(x, y, w, h),
00038 scroll_(x + w - 17, y, h - 1, 0, 1),
00039 maxLen_(maxLen), textSize_(textSize),
00040 scrollSpeed_(scrollSpeed),
00041 handler_(0), currentPosition_(0.0f)
00042 {
00043 color_ = GLWFont::widgetFontColor;
00044 scroll_.setMax((int) lines_.size());
00045 scroll_.setSee((int) (h_ / 12.0f));
00046 scroll_.setCurrent(scroll_.getMax());
00047 }
00048
00049 GLWListView::~GLWListView()
00050 {
00051 }
00052
00053 void GLWListView::draw()
00054 {
00055 glBegin(GL_LINE_LOOP);
00056 drawShadedRoundBox(x_, y_, w_, h_, 6.0f, false);
00057 glEnd();
00058
00059 {
00060
00061 GLState currentState(GLState::TEXTURE_ON | GLState::BLEND_ON);
00062 GLFont2d *font = GLWFont::instance()->getGameFont();
00063
00064
00065 urls_.clear();
00066
00067
00068 float posY = y_ + h_ - (textSize_ + 4.0f);
00069 int pos = (scroll_.getMax() - scroll_.getSee()) - scroll_.getCurrent();
00070
00071
00072
00073 int charCount = 0;
00074 for (int i=0; i<pos; i++)
00075 {
00076 LineEntry &lineEntry = lines_[i];
00077
00078 for (int j=0; j<(int) lineEntry.words_.size(); j++)
00079 {
00080 WordEntry &wordEntry = lineEntry.words_[j];
00081 charCount += (int) wordEntry.word_.size();
00082 }
00083 }
00084
00085
00086 bool newWords = false;
00087 for (int i=pos; i<(int) scroll_.getMax(); i++)
00088 {
00089
00090 if (i >= 0 && i < (int) lines_.size())
00091 {
00092 float width = w_ - BorderWidth;
00093 float widthUsed = 0.0f;
00094
00095
00096 LineEntry &lineEntry = lines_[i];
00097 for (int j=0; j<(int) lineEntry.words_.size(); j++)
00098 {
00099 WordEntry &wordEntry = lineEntry.words_[j];
00100
00101
00102 int possibleChars = font->getChars(textSize_, wordEntry.word_.c_str(), width - widthUsed);
00103 int drawChars = possibleChars;
00104 if (scrollSpeed_ > 0.0f)
00105 {
00106 if (possibleChars + charCount > (int) currentPosition_)
00107 {
00108 drawChars = int(currentPosition_) - charCount;
00109 }
00110 }
00111
00112 if (drawChars > 0)
00113 {
00114
00115 font->drawSubStr(0, drawChars,
00116 wordEntry.color_,
00117 textSize_,
00118 x_ + 5.0f + widthUsed, posY, 0.0f,
00119 S3D::formatStringBuffer("%s", wordEntry.word_.c_str()));
00120
00121
00122 if (wordEntry.wordRef_ != wordEntry.wordRefCount_)
00123 {
00124 newWords = true;
00125 wordEntry.wordRef_ = wordEntry.wordRefCount_;
00126 if (!wordEntry.event_.empty() && handler_)
00127 {
00128 handler_->event(wordEntry.event_);
00129 }
00130 }
00131
00132
00133 if (wordEntry.href_.size() > 0)
00134 {
00135 drawUrl(wordEntry, drawChars, widthUsed, posY);
00136 }
00137 }
00138
00139
00140 float wordWidth = font->getWidth(
00141 textSize_, wordEntry.word_.c_str());
00142 widthUsed += wordWidth;
00143 charCount += (int) wordEntry.word_.size();
00144 }
00145
00146
00147 posY -= (textSize_ + 2.0f);
00148 }
00149
00150
00151 if (posY < y_)
00152 {
00153 if (scrollSpeed_ > 0.0f && newWords)
00154 {
00155 scroll_.setCurrent(scroll_.getCurrent() - 1);
00156 }
00157 break;
00158 }
00159
00160
00161 if ((scrollSpeed_ > 0.0f) && (charCount > int(currentPosition_))) break;
00162 }
00163 }
00164
00165 scroll_.draw();
00166 }
00167
00168 void GLWListView::simulate(float frameTime)
00169 {
00170 currentPosition_ += (frameTime * scrollSpeed_);
00171 scroll_.simulate(frameTime);
00172 }
00173
00174 void GLWListView::mouseDown(int button, float x, float y, bool &skipRest)
00175 {
00176 std::vector<UrlEntry>::iterator itor;
00177 for (itor = urls_.begin();
00178 itor != urls_.end();
00179 itor++)
00180 {
00181 UrlEntry &entry = *itor;
00182 if (inBox(x, y, entry.x_, entry.y_, entry.w_, entry.h_))
00183 {
00184 if (handler_)
00185 {
00186 const char *url = entry.entry_->href_.c_str();
00187 handler_->url(url);
00188 }
00189 skipRest = true;
00190 return;
00191 }
00192 }
00193
00194 scroll_.mouseDown(button, x, y, skipRest);
00195 }
00196
00197 void GLWListView::mouseUp(int button, float x, float y, bool &skipRest)
00198 {
00199 scroll_.mouseUp(button, x, y, skipRest);
00200 }
00201
00202 void GLWListView::mouseDrag(int button, float mx, float my, float x, float y, bool &skipRest)
00203 {
00204 scroll_.mouseDrag(button, mx, my, x, y, skipRest);
00205 }
00206
00207 void GLWListView::mouseWheel(float x, float y, float z, bool &skipRest)
00208 {
00209 if (inBox(x, y, x_, y_, w_, h_))
00210 {
00211 skipRest = true;
00212
00213 if (z < 0.0f) scroll_.setCurrent(scroll_.getCurrent() + 1);
00214 else scroll_.setCurrent(scroll_.getCurrent() - 1);
00215 }
00216 }
00217
00218 void GLWListView::clear()
00219 {
00220 lines_.clear();
00221 scroll_.setCurrent(0);
00222 resetPosition();
00223 }
00224
00225 void GLWListView::endPosition()
00226 {
00227 scroll_.setCurrent(scroll_.getMin());
00228 }
00229
00230 void GLWListView::resetPosition()
00231 {
00232 GLWListView::WordEntry::wordRefCount_++;
00233 currentPosition_ = 0.0f;
00234 }
00235
00236 bool GLWListView::addWordEntry(std::list<WordEntry> &words,
00237 std::string &word, XMLNode *parentNode)
00238 {
00239 WordEntry wordEntry(word.c_str(), color_);
00240 word = "";
00241
00242 if (0 == strcmp("event", parentNode->getName()))
00243 {
00244 wordEntry.color_ = Vector(0.4f, 0.0f, 0.0f);
00245
00246 std::list<XMLNode *> ¶meters = parentNode->getParameters();
00247 std::list<XMLNode *>::iterator itor;
00248 for (itor = parameters.begin();
00249 itor != parameters.end();
00250 itor++)
00251 {
00252 XMLNode *node = *itor;
00253 wordEntry.event_[node->getName()] = node->getContent();
00254 }
00255 }
00256 else if (0 == strcmp("a", parentNode->getName()))
00257 {
00258 wordEntry.color_ = Vector(0.4f, 0.0f, 0.0f);
00259 if (!parentNode->getNamedParameter("href", wordEntry.href_, true, false))
00260 {
00261 return false;
00262 }
00263 }
00264
00265 words.push_back(wordEntry);
00266 return true;
00267 }
00268
00269 bool GLWListView::getLines(std::list<WordEntry> &words, float &lineLen)
00270 {
00271 std::list<WordEntry>::iterator itor;
00272 for (itor = words.begin();
00273 itor != words.end();
00274 itor++)
00275 {
00276 WordEntry &wordEntry = *itor;
00277
00278 if (wordEntry.word_.c_str()[0] == '\n')
00279 {
00280
00281 LineEntry lineEntry;
00282 lines_.push_back(lineEntry);
00283 lineLen = 0.0f;
00284 }
00285 else
00286 {
00287
00288 float wordLen =
00289 GLWFont::instance()->getGameFont()->
00290 getWidth(textSize_, wordEntry.word_.c_str());
00291 if (wordLen + lineLen >= w_ - BorderWidth)
00292 {
00293
00294 LineEntry lineEntry;
00295 lines_.push_back(lineEntry);
00296 lineLen = 0.0f;
00297 }
00298
00299 lines_.back().words_.push_back(wordEntry);
00300 lineLen += wordLen;
00301 }
00302 }
00303
00304 return true;
00305 }
00306
00307 bool GLWListView::getWords(XMLNode *node, std::list<WordEntry> &words)
00308 {
00309
00310 std::list<XMLNode *>::iterator childrenItor;
00311 std::list<XMLNode *> children = node->getChildren();
00312 for (childrenItor = children.begin();
00313 childrenItor != children.end();
00314 childrenItor++)
00315 {
00316 XMLNode *child = (*childrenItor);
00317
00318
00319 if (child->getType() == XMLNode::XMLNodeType)
00320 {
00321
00322 if (!getWords(child, words)) return false;
00323 }
00324 else
00325 {
00326
00327 std::string word;
00328 for (const char *t=child->getContent(); *t; t++)
00329 {
00330 if (*t == '\n')
00331 {
00332
00333 if (!addWordEntry(words, word, node)) return false;
00334
00335 word = "\n";
00336 if (!addWordEntry(words, word, node)) return false;
00337 }
00338 else
00339 {
00340 word += *t;
00341
00342
00343 if (*t == ' ')
00344 {
00345
00346 if (!addWordEntry(words, word, node)) return false;
00347 }
00348 }
00349 }
00350
00351
00352 if (!addWordEntry(words, word, node)) return false;
00353 }
00354 }
00355
00356 return true;
00357 }
00358
00359 bool GLWListView::addXML(XMLNode *node)
00360 {
00361
00362 std::list<WordEntry> words;
00363 if (!getWords(node, words)) return false;
00364
00365
00366 LineEntry lineEntry;
00367 lines_.push_back(lineEntry);
00368 float lineLen = 0.0f;
00369 getLines(words, lineLen);
00370
00371
00372 setScroll();
00373
00374 return true;
00375 }
00376
00377 void GLWListView::addLine(const std::string &text)
00378 {
00379
00380 if (maxLen_ > 0)
00381 {
00382 if (lines_.size() > (unsigned int) maxLen_) lines_.clear();
00383 }
00384
00385
00386 WordEntry wordEntry(text.c_str(), color_);
00387 LineEntry lineEntry;
00388 lineEntry.words_.push_back(wordEntry);
00389 lines_.push_back(lineEntry);
00390
00391
00392 setScroll();
00393 }
00394
00395 void GLWListView::setScroll()
00396 {
00397 int view = (int) (h_ / (textSize_ + 2.0f));
00398 scroll_.setMax((int) lines_.size());
00399 scroll_.setSee(view);
00400 scroll_.setCurrent(scroll_.getMax() - scroll_.getSee());
00401 }
00402
00403 void GLWListView::drawUrl(WordEntry &wordEntry, int drawChars, float x, float y)
00404 {
00405 GLFont2d *font = GLWFont::instance()->getGameFont();
00406 float partWordWidth = font->getWidth(
00407 textSize_, wordEntry.word_.c_str(), drawChars);
00408
00409
00410 UrlEntry urlEntry;
00411 urlEntry.x_ = x_ + 5.0f + x;
00412 urlEntry.y_ = y - 2.0f;
00413 urlEntry.w_ = partWordWidth;
00414 urlEntry.h_ = textSize_ + 2.0f;
00415 urlEntry.entry_ = &wordEntry;
00416 urls_.push_back(urlEntry);
00417
00418
00419 GLState noTexState(GLState::TEXTURE_OFF);
00420 glLineWidth(2.0f);
00421 glColor3fv(wordEntry.color_);
00422 glBegin(GL_LINES);
00423 glVertex2f(x_ + 5.0f + x, y - 2.0f);
00424 glVertex2f(x_ + 5.0f + x + partWordWidth, y - 2.0f);
00425 glEnd();
00426 glLineWidth(1.0f);
00427 }