src/GUIPanel.cpp

Go to the documentation of this file.
00001 #include "glwx.h"
00002 
00003 GUIPanel::GUIPanel(const std::string &cbs) : GUIRectangle(cbs), GUIClippedRectangle()
00004 {
00005   setInterval(4, 4);
00006   widgetType = WT_PANEL;
00007   layout     = PL_FREE_LAYOUT;
00008 }
00009 
00010 bool GUIPanel::loadXMLSettings(const char *stackPath)
00011 {
00012   std::string xmlFile = MediaPathManager::lookUpMediaPath(stackPath);
00013   bool        result = false;
00014 
00015   if(!xmlFile.size())
00016     return Logger::writeErrorLog("Failed to locate the XML GUI file");
00017 
00018   TiXmlDocument cfgStack(xmlFile);
00019 
00020   if(!cfgStack.LoadFile())
00021     return  Logger::writeErrorLog("Invalid XML GUI description file");
00022 
00023   result = loadXMLSettings(cfgStack.FirstChildElement());
00024   forceUpdate(true);
00025   return result;
00026 }
00027 
00028 bool GUIPanel::loadXMLSettings(const TiXmlElement *element)
00029 {
00030   if(!XMLArbiter::inspectElementInfo(element, "Panel"))
00031     return Logger::writeErrorLog("Need a Panel node in the xml file");
00032 
00033   const char  *description = element->Attribute("description");
00034   std::string  type        = element->Attribute("layout") ? element->Attribute("layout") : "UNKNOWN";
00035 
00036   if(description)
00037     return  loadXMLSettings(description);
00038 
00039   layout = (type == "CEN_YAXIS") ? PL_YAXIS_CEN_LAYOUT :
00040            (type == "YAXIS"    ) ? PL_YAXIS_LAYOUT     :
00041            (type == "XAXIS"    ) ? PL_XAXIS_LAYOUT     :
00042            (type == "GRID"     ) ? PL_GRID_LAYOUT      : PL_FREE_LAYOUT;
00043 
00044   for(const TiXmlElement *child = element->FirstChildElement();
00045       child;
00046           child = child->NextSiblingElement() )
00047   {
00048     std::string childName  = child->Value();
00049  
00050     if(!childName.size())
00051       continue;
00052 
00053     if(childName == "CheckBox")
00054     {
00055       GUICheckBox *newCheckBox = new GUICheckBox();
00056       if(!newCheckBox->loadXMLSettings(child) || !addWidget(newCheckBox))
00057         deleteObject(newCheckBox);
00058       continue;
00059     }
00060 
00061     if(childName == "TabbedPanel")
00062     {
00063       GUITabbedPanel *newTabbedPanel = new GUITabbedPanel();
00064       if(!newTabbedPanel->loadXMLSettings(child) || !addWidget(newTabbedPanel))
00065         deleteObject(newTabbedPanel);
00066       continue;
00067     }
00068 
00069     if(childName == "RadioButton")
00070     {
00071       GUIRadioButton *newRadioButton = new GUIRadioButton();
00072       if(!newRadioButton->loadXMLSettings(child) || !addWidget(newRadioButton))
00073       {
00074         deleteObject(newRadioButton);
00075       }
00076       else
00077       {
00078         if(newRadioButton->isChecked())
00079           notify(newRadioButton);
00080       }
00081       continue;
00082     }
00083 
00084     if(childName == "ComboBox")
00085     {
00086       GUIComboBox *newComboBox = new GUIComboBox();
00087       if(!newComboBox->loadXMLSettings(child) || !addWidget(newComboBox))
00088         deleteObject(newComboBox);
00089       continue;
00090     }
00091 
00092     if(childName == "TextBox")
00093     {
00094       GUITextBox *newTextBox = new GUITextBox();
00095       if(!newTextBox->loadXMLSettings(child) || !addWidget(newTextBox))
00096         deleteObject(newTextBox);
00097       continue;
00098     }
00099 
00100     if(childName == "Slider")
00101     {
00102       GUISlider *newSlider = new GUISlider();
00103       if(!newSlider->loadXMLSettings(child) || !addWidget(newSlider))
00104         deleteObject(newSlider);
00105       continue;
00106     }
00107 
00108     if(childName == "Separator")
00109     {
00110       GUISeparator *newSeparator = new GUISeparator();
00111       if((layout != PL_YAXIS_LAYOUT &&
00112           layout != PL_XAXIS_LAYOUT &&
00113           layout != PL_YAXIS_CEN_LAYOUT) ||
00114          (!newSeparator->loadXMLSettings(child)))
00115       {
00116         deleteObject(newSeparator);
00117       }
00118       else
00119       {
00120         newSeparator->setParent(this);
00121         newSeparator->setOrientation((layout != PL_YAXIS_LAYOUT && layout != PL_YAXIS_CEN_LAYOUT));
00122         elements.push_back(newSeparator);
00123       }
00124       continue;
00125     }
00126 
00127     if(childName == "Button")
00128     {
00129       GUIButton *newButton = new GUIButton();
00130       if(!newButton->loadXMLSettings(child) || !addWidget(newButton))
00131         deleteObject(newButton);
00132       continue;
00133     }
00134 
00135     if(childName == "Label")
00136     {
00137       GUILabel *newLabel = new GUILabel();
00138       if(!newLabel->loadXMLSettings(child) || !addWidget(newLabel))
00139         deleteObject(newLabel);
00140       continue;
00141     }
00142 
00143 
00144     if(childName == "Interval")
00145       setInterval(XMLArbiter::fillComponents2i(child, interval));
00146 
00147     if(childName == "Panel")
00148     {
00149       GUIPanel *panel = new GUIPanel();
00150       if(!panel->loadXMLSettings(child) || !addWidget(panel))
00151         deleteObject(panel);
00152       continue;
00153     }
00154   }
00155 
00156   return  GUIRectangle::loadXMLSettings(element)  &&
00157           GUIClippedRectangle::loadXMLClippedRectangleInfo(element);
00158 }
00159 
00160 GUIRectangle *GUIPanel::getWidgetByCallbackString(const std::string &callbackString)
00161 {
00162   if(!callbackString.size())
00163     return NULL;
00164 
00165   GUIRectangle *element = NULL,
00166                *tPanel  = NULL;
00167 
00168   size_t t = 0;
00169 
00170   for(t = 0; t < elements.size(); t++)
00171   {
00172     if(elements[t]->getCallbackString() == callbackString)
00173       return elements[t];
00174   }
00175 
00176   for(t = 0; t < elements.size(); t++)
00177   {
00178     if(elements[t]->getWidgetType() == WT_PANEL)
00179     if(element = ((GUIPanel*)elements[t])->getWidgetByCallbackString(callbackString))
00180       break;
00181 
00182     if(elements[t]->getWidgetType() == WT_TABBED_PANEL)
00183     if(element = ((GUITabbedPanel*)elements[t])->getLowerPanel()->getWidgetByCallbackString(callbackString))
00184       break;
00185   }
00186   return element;
00187 }
00188 
00189 void GUIPanel::checkMouseEvents(MouseEvent &evt, int extraInfo, bool infoBits)
00190 {
00191   if(visible && active)
00192   {
00193     GUIRectangle::checkMouseEvents(evt, extraInfo, infoBits);
00194     for(size_t t = 0; t < elements.size(); t++)
00195     {
00196       if(elements[t]->isActive())
00197         elements[t]->checkMouseEvents(evt, extraInfo, infoBits);
00198     }
00199   }
00200 }
00201 void GUIPanel::checkKeyboardEvents(KeyEvent &evt, int extraInfo)
00202 {
00203   if(visible && active)
00204   {
00205     GUIRectangle::checkKeyboardEvents(evt, extraInfo);
00206     for(size_t t = 0; t < elements.size(); t++)
00207     if(elements[t]->isActive())
00208       elements[t]->checkKeyboardEvents(evt, extraInfo);
00209   }
00210 }
00211 
00212 void  GUIPanel::render(float tick)
00213 {
00214   if(!isAttached() || !parent)
00215     return;
00216 
00217   Widgets comboBoxes;
00218   GUIComboBox *cbPTR;
00219 
00220   if(visible)
00221   {
00222     renderClippedBounds();
00223     for(size_t t = 0; t < elements.size(); t++)
00224       if(elements[t]->getWidgetType() != WT_COMBO_BOX)
00225         elements[t]->render(tick);
00226       else
00227       {
00228         cbPTR = (GUIComboBox*)elements[t];
00229         if(!cbPTR->isDeployed())
00230           cbPTR->render(tick);
00231         else
00232           comboBoxes.push_back(elements[t]);
00233       }
00234 
00235     for(size_t t = 0; t < comboBoxes.size(); t++)
00236       comboBoxes[t]->render(tick);
00237   }
00238 }
00239 
00240 void  GUIPanel::collectZWidgets(ZWidgets &container)
00241 {
00242   if(visible)
00243   {
00244     for(size_t t = 0; t < elements.size(); t++)
00245       if(elements[t]->getWidgetType() != WT_PANEL)
00246       {
00247         ZWidget zWidget(elements[t]);
00248         zWidget.setDistance(float(elements[t]->getZCoordinate()));
00249         container.push_back(zWidget);
00250       }
00251       else
00252       {
00253          ((GUIPanel*)elements[t])->collectZWidgets(container);
00254       }
00255 
00256     ZWidget zWidget(this);
00257     zWidget.setDistance(float(getZCoordinate()));
00258 
00259     container.push_back(zWidget);
00260   }
00261 }
00262 
00263 void GUIPanel::pack()
00264 {
00265   if(!update)
00266     return;
00267 
00268   size_t t = 0;
00269 
00270   for(t = 0; t < elements.size(); t++)
00271     elements[t]->forceUpdate(update);
00272 
00273   if(!t)
00274   {
00275     correctPosition();
00276     return;
00277   }
00278 
00279   switch(layout)
00280   {
00281     case PL_YAXIS_LAYOUT:
00282     case PL_YAXIS_CEN_LAYOUT:
00283       packYAxisLayout();
00284     break;
00285     case PL_XAXIS_LAYOUT: 
00286       packXAxisLayout(); 
00287     break;
00288     default: packFreeLayout();
00289   }
00290 
00291   for(t = 0; t < elements.size(); t++)
00292     elements[t]->forceUpdate(update);
00293 }
00294 
00295 void GUIPanel::forceUpdate(bool updateArg)
00296 {
00297   update = updateArg;
00298   pack();
00299 }
00300 
00301 void GUIPanel::packYAxisLayout()
00302 {
00303   computeWindowBounds();
00304 
00305   std::vector<int> childrenHeights,
00306               childrenWidths;
00307 
00308   size_t      t          = 0;
00309   int         height     = 0,
00310               xOffset    = 0,
00311               panelWidth = getWidth();
00312 
00313   for(t = 0; t < elements.size(); t++)
00314   {
00315     const Tuple4i &childBounds = elements[t]->getWindowBounds();
00316     childrenHeights.push_back(childBounds.w - childBounds.y + interval.y);
00317     childrenWidths.push_back(childBounds.z - childBounds.x);
00318     height       += childrenHeights[t];
00319     panelWidth    = childrenWidths[t] > panelWidth ? childrenWidths[t] : panelWidth;
00320   }
00321 
00322   dimensions.set(float(panelWidth), float(height));
00323   GUIRectangle::computeWindowBounds();
00324 
00325   windowBounds.z += interval.x*2;
00326   windowBounds.w += interval.y;
00327 
00328   update = false;
00329   height = interval.y;
00330 
00331   correctPosition();
00332   computeClippedBounds(windowBounds);
00333 
00334   for(t = 0; t < elements.size(); t++)
00335   {
00336     xOffset = (layout == PL_YAXIS_CEN_LAYOUT) * (panelWidth - childrenWidths[t])/2;
00337 
00338     elements[t]->setAnchorPoint(AT_CORNERLU);
00339     elements[t]->setPosition(float(interval.x + xOffset), float(height));
00340     elements[t]->computeWindowBounds();
00341     height += childrenHeights[t];
00342   }
00343 }
00344 
00345 void GUIPanel::packXAxisLayout()
00346 {
00347   computeWindowBounds();
00348 
00349   std::vector<int> childrenWidths,
00350               childrenHeights;
00351   float       offset      = 0;
00352   size_t      t           = 0;
00353   int         height      = 0,
00354               width       = 0,
00355               panelHeight = windowBounds.w - windowBounds.y;
00356 
00357   for(t = 0; t < elements.size(); t++)
00358   {
00359     const Tuple4i &childBounds = elements[t]->getWindowBounds();
00360     childrenHeights.push_back(childBounds.w - childBounds.y);
00361     childrenWidths.push_back (childBounds.z - childBounds.x + interval.x);
00362 
00363     width       += childrenWidths[t];
00364     height       = childBounds.w - childBounds.y;
00365     panelHeight  = height > panelHeight ? height : panelHeight;
00366   }
00367 
00368   dimensions.set(float(width), float(panelHeight));
00369   GUIRectangle::computeWindowBounds();
00370 
00371   windowBounds.z += interval.x;
00372   windowBounds.w += interval.y*2;
00373 
00374   update = false;
00375   width  = interval.x;
00376 
00377   correctPosition();
00378   computeClippedBounds(windowBounds);
00379 
00380   for(t = 0; t < elements.size(); t++)
00381   {
00382     offset = clamp(float(panelHeight - childrenHeights[t])/2.0f + interval.y, 0.0f, 1000.0f);
00383     elements[t]->setAnchorPoint(AT_CORNERLU);
00384     elements[t]->setPosition(float(width), offset);
00385     elements[t]->computeWindowBounds();
00386     width += childrenWidths[t];
00387   }
00388 }
00389 
00390 void GUIPanel::packFreeLayout()
00391 {
00392   if(!update || !parent)
00393     return;
00394 
00395   Tuple4i newBounds = getWindowBounds();
00396   size_t  t         = 0;
00397   int     temp1     = 0,
00398           temp2     = 0;
00399 
00400   for(t = 0; t < elements.size(); t++)
00401   {
00402     elements[t]->forceUpdate(update);
00403     const Tuple4i &childBounds = elements[t]->getWindowBounds();
00404 
00405     newBounds.x = (childBounds.x - clipSize) < newBounds.x ?
00406                    childBounds.x - clipSize : newBounds.x;
00407     newBounds.y = (childBounds.y - clipSize) < newBounds.y ?
00408                    childBounds.y - clipSize : newBounds.y;
00409     newBounds.z = (childBounds.z + clipSize) > newBounds.z ?
00410                    childBounds.z + clipSize: newBounds.z;
00411     newBounds.w = (childBounds.w + clipSize) > newBounds.w ?
00412                    childBounds.w + clipSize : newBounds.w;
00413   }
00414 
00415   windowBounds = newBounds;
00416   update       = false;
00417 
00418   correctPosition();
00419   computeClippedBounds(windowBounds);
00420 
00421   for(t = 0; t < elements.size(); t++)
00422     elements[t]->computeWindowBounds();
00423 }
00424 
00425 void GUIPanel::correctPosition()
00426 {
00427   if(!parent)
00428     return;
00429 
00430   const Tuple4i&  parentBounds = parent->getWindowBounds();
00431   bool            update       = false;
00432   int             temp         = windowBounds.z - windowBounds.x;
00433 
00434   if(position.x < 0)
00435   if(parentBounds.z - windowBounds.z < abs(position.x))
00436   {
00437     windowBounds.z  = parentBounds.z + int(position.x);
00438     windowBounds.x  = windowBounds.z - temp;
00439     update          = true;
00440   }
00441 
00442   if(position.x > 1)
00443   if(windowBounds.x <  position.x + parentBounds.x)
00444   {
00445     windowBounds.x  = parentBounds.x + int(position.x);
00446     windowBounds.z  = windowBounds.x + temp;
00447     update          = true;
00448   }
00449 
00450   if(position.y < 0)
00451   if(parentBounds.w - windowBounds.w < abs(position.y))
00452   {
00453     temp            = windowBounds.w - windowBounds.y;
00454     windowBounds.w  = parentBounds.w + int(position.y);
00455     windowBounds.y  = windowBounds.w - temp;
00456     update          = true;
00457   }
00458 
00459   if(update)
00460     for(size_t t = 0; t < elements.size(); t++)
00461     {
00462       elements[t]->forceUpdate(true);
00463       elements[t]->computeWindowBounds();
00464     }
00465 }
00466 
00467 bool  GUIPanel::addWidget(GUIRectangle *element)
00468 {
00469   if(element)
00470   {
00471     for(size_t t = 0; t < elements.size(); t++)
00472       if(elements[t]->getCallbackString() == element->getCallbackString())
00473         return Logger::writeErrorLog(std::string("Panel already has a child with CBS -> ")
00474                                      + element->getCallbackString());
00475     elements.push_back(element);
00476     element->setParent(this);
00477     return true;
00478   }
00479   return false;
00480 }
00481 
00482 void GUIPanel::clear()
00483 {
00484   parent        = NULL;
00485 
00486   for(size_t t = 0; t < elements.size(); t++)
00487     deleteObject(elements[t]);
00488 
00489   elements.clear();
00490 }
00491 
00492 void GUIPanel::notify(GUIRectangle *element)
00493 {
00494   if(!element)
00495     return;
00496 
00497   switch(element->getWidgetType())
00498   {
00499     case WT_RADIO_BUTTON:
00500       for(size_t t = 0; t < elements.size(); t++)
00501         if(elements[t]->getWidgetType() == WT_RADIO_BUTTON &&
00502            elements[t]!= element)
00503         {
00504           GUIRadioButton *rButton = (GUIRadioButton*)elements[t];
00505           rButton->setChecked(false);
00506         }
00507     break;
00508   }
00509 }
00510 
00511 int  GUIPanel::getWidgetCountByType(int type)
00512 {
00513   int  counter =  0;
00514 
00515   for(size_t t = 0; t < elements.size(); t++)
00516     if(elements[t]->getWidgetType() == type)
00517       counter++;
00518 
00519   return counter;
00520 }
00521 
00522 int  GUIPanel::getTreeHeight()
00523 {
00524   int height = 1;
00525 
00526   for(size_t t = 0; t < elements.size(); t++)
00527    if(elements[t]->getWidgetType() == WT_PANEL)
00528      height += ((GUIPanel*)elements[t])->getTreeHeight();
00529   return height;
00530 }
00531 
00532 void  GUIPanel::setInterval(const Tuple2i &dimensions)
00533 {
00534   setInterval(dimensions.x, dimensions.y);
00535 }
00536 
00537 void  GUIPanel::setInterval(int width, int height)
00538 {
00539   interval.set(clamp(width , 0, 2500),
00540                clamp(height, 0, 2500));
00541 }
00542 
00543 const Tuple2i &GUIPanel::getInterval()
00544 {
00545   return interval;
00546 }
00547 
00548 void  GUIPanel::setLayout(int layoutArg)
00549 {
00550   switch(layoutArg)
00551   {
00552     case PL_GRID_LAYOUT:
00553     case PL_YAXIS_CEN_LAYOUT:
00554     case PL_YAXIS_LAYOUT:
00555     case PL_XAXIS_LAYOUT:
00556       layout = layoutArg;
00557     break;
00558     default: layout = PL_FREE_LAYOUT;
00559   }
00560 }
00561 
00562 int   GUIPanel::getLayout()
00563 {
00564   return layout;
00565 }
00566 
00567 Widgets &GUIPanel::getWidgets()
00568 {
00569   return elements;
00570 }
00571 
00572 GUIPanel::~GUIPanel()
00573 {
00574   clear();
00575 }
00576 

Generated on Wed Dec 5 20:32:03 2007 for GLWX by  doxygen 1.5.3