GLWPanel.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <GLEXT/GLState.h>
00022 #include <XML/XMLParser.h>
00023 #include <common/Defines.h>
00024 #include <GLW/GLWTranslate.h>
00025 #include <GLW/GLWPanel.h>
00026 #include <GLW/GLWTab.h>
00027 
00028 GLWPanel::GLWPanelEntry::GLWPanelEntry(GLWidget *w, GLWCondition *c,
00029         unsigned int f, float wi) :
00030         widget(w), condition(c), flags(f),
00031         leftSpace(0.0f), rightSpace(0.0f),
00032         topSpace(0.0f), bottomSpace(0.0f)
00033 {
00034         if (! (f & GLWPanel::AlignLeft) &&
00035                 ! (f & GLWPanel::AlignRight) &&
00036                 ! (f & GLWPanel::AlignCenterLeftRight)) flags |= GLWPanel::AlignLeft;
00037 
00038         if (! (f & GLWPanel::AlignTop) &&
00039                 ! (f & GLWPanel::AlignCenterTopBottom) &&
00040                 ! (f & GLWPanel::AlignBottom)) flags |= GLWPanel::AlignBottom;
00041 
00042         if ((f & GLWPanel::SpaceRight) || (f & GLWPanel::SpaceAll)) rightSpace = wi;
00043         if ((f & GLWPanel::SpaceLeft) || (f & GLWPanel::SpaceAll)) leftSpace = wi;
00044         if ((f & GLWPanel::SpaceTop) || (f & GLWPanel::SpaceAll)) topSpace = wi;
00045         if ((f & GLWPanel::SpaceBottom) || (f & GLWPanel::SpaceAll)) bottomSpace = wi;
00046 }
00047 
00048 REGISTER_CLASS_SOURCE(GLWPanel);
00049 
00050 GLWPanel::GLWPanel(float x, float y, float w, float h, 
00051         bool depressed, bool visible, bool ridge) : 
00052         GLWidget(x, y, w, h), depressed_(depressed), 
00053         drawPanel_(visible), layout_(LayoutNone),
00054         gridWidth_(0), ridge_(ridge)
00055 {
00056 
00057 }
00058 
00059 GLWPanel::~GLWPanel()
00060 {
00061         clear();
00062 }
00063 
00064 GLWidget *GLWPanel::addWidget(GLWidget *widget, GLWCondition *condition, 
00065         unsigned int flags, float width)
00066 {
00067         std::list<GLWPanelEntry>::iterator itor;
00068         for (itor = widgets_.begin();
00069                 itor != widgets_.end();
00070                 itor++)
00071         {
00072                 GLWPanelEntry &entry = *itor;
00073                 DIALOG_ASSERT(entry.widget != widget);
00074         }
00075 
00076         GLWPanelEntry entry(widget, condition, flags, width);
00077         widgets_.push_back(entry);
00078         widget->setParent(this);
00079         return widget;
00080 }
00081 
00082 GLWidget *GLWPanel::getWidgetByName(const char *name)
00083 {
00084         std::list<GLWPanelEntry>::iterator itor;
00085         for (itor = widgets_.begin();
00086                 itor != widgets_.end();
00087                 itor++)
00088         {
00089                 GLWPanelEntry &entry = *itor;
00090                 if ((*itor).widget->getVisible() &&
00091                         (!entry.condition || 
00092                         entry.condition->getResult(entry.widget)))
00093                 {
00094                         if (0 == strcmp(name, entry.widget->getName())) 
00095                         {
00096                                 return entry.widget;
00097                         }
00098                         if (0 == strcmp(entry.widget->getClassName(), "GLWPanel"))
00099                         {
00100                                 GLWPanel *panel = (GLWPanel *) entry.widget;
00101                                 GLWidget *widget = panel->getWidgetByName(name);
00102                                 if (widget) return widget;
00103                         }
00104                 }
00105         }
00106         return 0;
00107 }
00108 
00109 void GLWPanel::clear()
00110 {
00111         std::list<GLWPanelEntry>::iterator itor;
00112         for (itor = widgets_.begin();
00113                 itor != widgets_.end();
00114                 itor++)
00115         {
00116                 delete (*itor).widget;
00117                 delete (*itor).condition;
00118         }
00119         widgets_.clear();
00120 }
00121 
00122 void GLWPanel::simulate(float frameTime)
00123 {
00124         std::list<GLWPanelEntry>::iterator itor;
00125         for (itor = widgets_.begin();
00126                 itor != widgets_.end();
00127                 itor++)
00128         {
00129                 GLWPanelEntry &entry = *itor;
00130                 if ((*itor).widget->getVisible() &&
00131                         (!entry.condition || 
00132                         entry.condition->getResult(entry.widget)))
00133                 {
00134                         entry.widget->simulate(frameTime);
00135                 }
00136         }
00137 }
00138 
00139 void GLWPanel::draw()
00140 {
00141         GLState currentState(GLState::DEPTH_OFF | GLState::TEXTURE_OFF);
00142 
00143         GLWidget::draw();
00144 
00145         glPushMatrix();
00146                 if (drawPanel_)
00147                 {
00148                         glColor3f(0.8f, 0.8f, 1.0f);
00149                         glBegin(GL_QUADS);
00150                                 glVertex2f(x_, y_);
00151                                 glVertex2f(x_ + w_, y_);
00152                                 glVertex2f(x_ + w_, y_ + h_);
00153                                 glVertex2f(x_, y_ + h_);
00154                         glEnd();
00155 
00156                         glBegin(GL_LINE_LOOP);
00157                                 drawShadedRoundBox(x_, y_, w_, h_, 10.0f, !depressed_);
00158                         glEnd();
00159 
00160                         if (ridge_)
00161                         {
00162                                 glBegin(GL_LINE_LOOP);
00163                                         drawShadedRoundBox(x_-2.0f, y_-2.0f, w_+4.0f, h_+4.0f, 10.0f, depressed_);
00164                                 glEnd();
00165                         }
00166                 }
00167 
00168                 {
00169                         GLWTranslate trans(x_, y_);
00170                         glTranslatef(x_, y_, 0.0f);
00171 
00172                         std::list<GLWPanelEntry>::iterator itor;
00173                         for (itor = widgets_.begin();
00174                                 itor != widgets_.end();
00175                                 itor++)
00176                         {
00177                                 GLWPanelEntry &entry = *itor;
00178                                 if ((*itor).widget->getVisible() &&
00179                                         (!entry.condition || 
00180                                         entry.condition->getResult(entry.widget)))
00181                                 {
00182                                         glPushMatrix();
00183                                                 (*itor).widget->draw();
00184                                         glPopMatrix();
00185                                 }
00186                         }
00187                 }
00188         glPopMatrix();
00189 }
00190 
00191 void GLWPanel::mouseWheel(float x, float y, float z, bool &skipRest)
00192 {
00193         if (!inBox(x, y, x_, y_, w_, h_)) return;
00194 
00195         x -= x_;
00196         y -= y_;
00197 
00198         GLWTranslate trans(x_, y_);
00199 
00200         std::list<GLWPanelEntry>::reverse_iterator itor;
00201         for (itor = widgets_.rbegin();
00202                 itor != widgets_.rend();
00203                 itor++)
00204         {
00205                 GLWPanelEntry &entry = *itor;
00206                 if ((*itor).widget->getVisible() &&
00207                         (!entry.condition || 
00208                         entry.condition->getResult(entry.widget)))
00209                 {
00210                         (*itor).widget->mouseWheel(x, y, z, skipRest);
00211                         if (skipRest) break;
00212                 }
00213         }
00214 }
00215 
00216 void GLWPanel::mouseDown(int button, float x, float y, bool &skipRest)
00217 {
00218         x -= x_;
00219         y -= y_;
00220 
00221         GLWTranslate trans(x_, y_);
00222 
00223         std::list<GLWPanelEntry>::reverse_iterator itor;
00224         for (itor = widgets_.rbegin();
00225                 itor != widgets_.rend();
00226                 itor++)
00227         {
00228                 GLWPanelEntry &entry = *itor;
00229                 if ((*itor).widget->getVisible() &&
00230                         (!entry.condition || 
00231                         entry.condition->getResult(entry.widget)))
00232                 {
00233                         (*itor).widget->mouseDown(button, x, y, skipRest);
00234                         if (skipRest) break;
00235                 }
00236         }
00237 }
00238 
00239 void GLWPanel::mouseUp(int button, float x, float y, bool &skipRest)
00240 {
00241         x -= x_;
00242         y -= y_;
00243 
00244         GLWTranslate trans(x_, y_);
00245 
00246         std::list<GLWPanelEntry>::reverse_iterator itor;
00247         for (itor = widgets_.rbegin();
00248                 itor != widgets_.rend();
00249                 itor++)
00250         {
00251                 GLWPanelEntry &entry = *itor;
00252                 if ((*itor).widget->getVisible() &&
00253                         (!entry.condition || 
00254                         entry.condition->getResult(entry.widget)))
00255                 (*itor).widget->mouseUp(button, x, y, skipRest);
00256                 if (skipRest) break;
00257         }
00258 }
00259 
00260 void GLWPanel::mouseDrag(int button, float mx, float my, float x, float y, bool &skipRest)
00261 {
00262         mx -= x_;
00263         my -= y_;
00264 
00265         if (mx < 0.0f || mx > w_ ||
00266                 my < 0.0f || my > h_)
00267         {
00268                 return;
00269         }
00270         
00271         std::list<GLWPanelEntry>::reverse_iterator itor;
00272         for (itor = widgets_.rbegin();
00273                 itor != widgets_.rend();
00274                 itor++)
00275         {
00276                 GLWPanelEntry &entry = *itor;
00277                 if ((*itor).widget->getVisible() &&
00278                         (!entry.condition || 
00279                         entry.condition->getResult(entry.widget)))
00280                 {
00281                         (*itor).widget->mouseDrag(button, mx, my, x, y, skipRest);
00282                         if (skipRest) break;
00283                 }
00284         }
00285         skipRest = true;
00286 }
00287 
00288 void GLWPanel::keyDown(char *buffer, unsigned int keyState, 
00289                 KeyboardHistory::HistoryElement *history, int hisCount, 
00290                 bool &skipRest)
00291 {
00292         std::list<GLWPanelEntry>::reverse_iterator itor;
00293         for (itor = widgets_.rbegin();
00294                 itor != widgets_.rend();
00295                 itor++)
00296         {
00297                 GLWPanelEntry &entry = *itor;
00298                 if ((*itor).widget->getVisible() &&
00299                         (!entry.condition || 
00300                         entry.condition->getResult(entry.widget)))
00301                 {
00302                         (*itor).widget->keyDown(buffer, keyState, history, hisCount, skipRest);
00303                         if (skipRest) break;
00304                 }
00305         }
00306 }
00307 
00308 void GLWPanel::display()
00309 {
00310         std::list<GLWPanelEntry>::reverse_iterator itor;
00311         for (itor = widgets_.rbegin();
00312                 itor != widgets_.rend();
00313                 itor++)
00314         {
00315                 GLWPanelEntry &entry = *itor;
00316                 if ((*itor).widget->getVisible() &&
00317                         (!entry.condition || 
00318                         entry.condition->getResult(entry.widget)))
00319                 {
00320                         (*itor).widget->display();
00321                 }
00322         }
00323 }
00324 
00325 void GLWPanel::hide()
00326 {
00327         std::list<GLWPanelEntry>::reverse_iterator itor;
00328         for (itor = widgets_.rbegin();
00329                 itor != widgets_.rend();
00330                 itor++)
00331         {
00332                 GLWPanelEntry &entry = *itor;
00333                 if ((*itor).widget->getVisible() &&
00334                         (!entry.condition || 
00335                         entry.condition->getResult(entry.widget)))
00336                 {
00337                         (*itor).widget->hide();
00338                 }
00339         }
00340 }
00341 
00342 bool GLWPanel::initFromXML(XMLNode *node)
00343 {
00344         if (!GLWidget::initFromXML(node)) return false;
00345         drawPanel_ = false;
00346 
00347         // Items
00348         XMLNode *itemsNode;
00349         if (!node->getNamedChild("items", itemsNode)) return false;
00350 
00351         // Itterate all of the items in the file
00352         std::list<XMLNode *>::iterator childrenItor;
00353                 std::list<XMLNode *> &children = itemsNode->getChildren();
00354         for (childrenItor = children.begin();
00355                 childrenItor != children.end();
00356                 childrenItor++)
00357         {
00358                 // For each node named items
00359                 XMLNode *currentNode = (*childrenItor);
00360 
00361                 // The Widget
00362                 XMLNode *widgetNode, *widgetTypeNode;
00363                 if (!currentNode->getNamedChild("widget", widgetNode)) return false;
00364                 if (!widgetNode->getNamedParameter("type", widgetTypeNode)) return false;
00365 
00366                 // Create new type
00367                 GLWidget *widget = (GLWidget *)
00368                         MetaClassRegistration::getNewClass(widgetTypeNode->getContent());
00369                 if (!widget) 
00370                 {
00371                         S3D::dialogMessage("GLWPanel", S3D::formatStringBuffer(
00372                                 "Unknown widget type \"%s\"",
00373                                 widgetTypeNode->getContent()));
00374                         return false;
00375                 }
00376                 if (!widget->initFromXML(widgetNode))
00377                 {
00378                         S3D::dialogMessage("GLWPanel", S3D::formatStringBuffer(
00379                                 "Failed to parse \"%s\" widget type",
00380                                 widgetTypeNode->getContent()));
00381                         return false;                   
00382                 }
00383                 if (!widgetNode->failChildren()) return false;
00384 
00385                 // The condition (if any)
00386                 GLWCondition *condition = 0;
00387                 XMLNode *conditionNode = 0;
00388                 if (currentNode->getNamedChild("condition", conditionNode, false))
00389                 {
00390                         // Get the type of this condition
00391                         XMLNode *conditionTypeNode;
00392                         if (!conditionNode->getNamedParameter("type", conditionTypeNode)) return false;
00393 
00394                         // Create type
00395                         condition = (GLWCondition *)
00396                                 MetaClassRegistration::getNewClass(conditionTypeNode->getContent());
00397                         if (!condition)
00398                         {
00399                                 S3D::dialogMessage("GLWPanel", S3D::formatStringBuffer(
00400                                         "Unknown condition type \"%s\"",
00401                                         conditionTypeNode->getContent()));
00402                                 return false;
00403                         }
00404                         if (!condition->initFromXML(conditionNode))
00405                         {
00406                                 S3D::dialogMessage("GLWPanel", S3D::formatStringBuffer(
00407                                         "Failed to parse \"%s\" condition type",
00408                                         conditionTypeNode->getContent()));
00409                                 return false;
00410                         }
00411                 }
00412 
00413                 addWidget(widget, condition);
00414         }
00415         return true;
00416 }
00417 
00418 void GLWPanel::layout()
00419 {
00420         if (layout_ == LayoutNone) return;
00421         
00422         float w = 0.0f;
00423         float h = 0.0f;
00424         float *gridW = 0;
00425         if (gridWidth_ > 0) gridW = new float[gridWidth_];
00426         for (unsigned int i=0; i<gridWidth_; i++) gridW[i] = 0.0f;
00427         
00428         // Figure out how wide and high this frame should be
00429         int wid = 0;
00430         std::list<GLWPanelEntry>::iterator itor;
00431         for (itor = widgets_.begin();
00432                 itor != widgets_.end();
00433                 itor++, wid++)
00434         {
00435                 GLWPanelEntry &entry = *itor;
00436                 
00437                 // Size this widget
00438                 entry.widget->layout();
00439                 
00440                 // Get the size
00441                 float width = entry.widget->getW() +
00442                         entry.leftSpace + entry.rightSpace;
00443                 float height = entry.widget->getH() +
00444                         entry.topSpace + entry.bottomSpace;             
00445                 if (layout_ == LayoutHorizontal)
00446                 {
00447                         w += width;
00448                         h = MAX(h, height);
00449                 }
00450                 else if (layout_ == LayoutVerticle)
00451                 {
00452                         w = MAX(w, width);
00453                         h += height;
00454                 }
00455                 else if (layout_ == LayoutGrid)
00456                 {
00457                         gridW[wid % gridWidth_] = MAX(gridW[wid % gridWidth_], width);
00458                         h = MAX(h, height);
00459                 }
00460                 else DIALOG_ASSERT(0);
00461         }
00462         
00463         float prevh = h;
00464         float prevw = w;
00465         if (layout_ == LayoutGrid)
00466         {
00467                 DIALOG_ASSERT(gridWidth_ != 0);
00468 
00469                 w = 0.0f;
00470                 for (unsigned int i=0; i<gridWidth_; i++) w += gridW[i];
00471                 int rows = widgets_.size() / gridWidth_;
00472                 if (widgets_.size() % gridWidth_ > 0) rows ++;
00473                 h *= rows;
00474         }
00475         
00476         // Set the width and height
00477         setW(w);
00478         setH(h);
00479         
00480         // Set the position of all the widgets
00481         if (layout_ == LayoutHorizontal)
00482         {
00483                 float width = 0.0f;
00484                 for (itor = widgets_.begin();
00485                         itor != widgets_.end();
00486                         itor++)
00487                 {
00488                         GLWPanelEntry &entry = *itor;
00489                         width += entry.leftSpace;
00490                         entry.widget->setX(width);
00491                         
00492                         if (entry.flags & AlignBottom)
00493                         {
00494                                 entry.widget->setY(entry.bottomSpace);
00495                         }
00496                         else if (entry.flags & AlignCenterTopBottom)
00497                         {
00498                                 entry.widget->setY(prevh / 2 - 
00499                                         entry.widget->getH() / 2);
00500                         }
00501                         else if (entry.flags & AlignTop)
00502                         {
00503                                 entry.widget->setY(prevh - entry.topSpace -
00504                                         entry.widget->getH());
00505                         }
00506                         else DIALOG_ASSERT(0);
00507                         
00508                         width += entry.widget->getW();
00509                         width += entry.rightSpace;
00510                 }
00511         }
00512         else if (layout_ == LayoutVerticle)
00513         {
00514                 float height = getH();
00515                 for (itor = widgets_.begin();
00516                         itor != widgets_.end();
00517                         itor++)
00518                 {
00519                         GLWPanelEntry &entry = *itor;
00520                         height -= entry.topSpace;
00521                         entry.widget->setY(height - entry.widget->getH());
00522                         
00523                         if (entry.flags & AlignLeft)
00524                         {
00525                                 entry.widget->setX(entry.leftSpace);
00526                         }
00527                         else if (entry.flags & AlignCenterLeftRight)
00528                         {
00529                                 entry.widget->setX(prevw / 2 - 
00530                                         entry.widget->getW() / 2);
00531                         }
00532                         else if (entry.flags & AlignRight)
00533                         {
00534                                 entry.widget->setX(prevw - entry.rightSpace -
00535                                         entry.widget->getW());
00536                         }
00537                         else DIALOG_ASSERT(0);
00538                         
00539                         height -= entry.widget->getH();
00540                         height -= entry.bottomSpace;
00541                 }
00542         }
00543         else if (layout_ == LayoutGrid)
00544         {
00545                 unsigned int cell = 0;
00546                 float width = 0.0f;
00547                 float height = getH();
00548                 for (itor = widgets_.begin();
00549                         itor != widgets_.end();
00550                         itor++)
00551                 {
00552                         GLWPanelEntry &entry = *itor;
00553 
00554                         float prevw = gridW[cell];
00555 
00556                         if (entry.flags & AlignLeft)
00557                         {
00558                                 entry.widget->setX(width + entry.leftSpace);
00559                         }
00560                         else if (entry.flags & AlignCenterLeftRight)
00561                         {
00562                                 entry.widget->setX(width + prevw / 2 - 
00563                                         entry.widget->getW() / 2);
00564                         }
00565                         else if (entry.flags & AlignRight)
00566                         {
00567                                 entry.widget->setX(width + prevw - entry.rightSpace -
00568                                         entry.widget->getW());
00569                         }
00570                         else DIALOG_ASSERT(0);
00571                         
00572                         if (entry.flags & AlignBottom)
00573                         {
00574                                 entry.widget->setY(height - prevh + entry.bottomSpace);
00575                         }
00576                         else if (entry.flags & AlignCenterTopBottom)
00577                         {
00578                                 entry.widget->setY(height - prevh / 2 - 
00579                                         entry.widget->getH() / 2);
00580                         }
00581                         else if (entry.flags & AlignTop)
00582                         {
00583                                 entry.widget->setY(height - entry.topSpace -
00584                                         entry.widget->getH());
00585                         }
00586                         else DIALOG_ASSERT(0);  
00587                 
00588                         if (++cell >= gridWidth_)
00589                         {
00590                                 cell = 0;       
00591                                 width = 0.0f;
00592                                 height -= prevh;
00593                         }
00594                         else
00595                         {
00596                                 width += prevw;
00597                         }
00598                 }               
00599         }
00600         else DIALOG_ASSERT(0);
00601         
00602         delete [] gridW;
00603 }
00604 
00605 void GLWPanel::setLayout(unsigned int layout)
00606 {
00607         layout_ = layout;
00608 }
00609 
00610 unsigned int GLWPanel::getLayout()
00611 {
00612         return layout_;
00613 }
00614 
00615 void GLWPanel::setGridWidth(unsigned int width)
00616 {
00617         gridWidth_ = width;
00618 }
00619 
00620 unsigned int GLWPanel::getGridWidth()
00621 {
00622         return gridWidth_;
00623 }
00624 

Generated on Mon Feb 16 15:14:45 2009 for Scorched3D by  doxygen 1.5.3