src/GUIComboBox.cpp

Go to the documentation of this file.
00001 #include "glwx.h"
00002 
00003 GUIComboBox::GUIComboBox(const std::string& cbs) : GUIRectangle(cbs)
00004 
00005 {
00006   setScrollingColor(0.2f, 0.75f, 0.35f, 1.0f);
00007   setFontScales(1.0f, 1.0f);
00008   setPosition(0.5, 0.5);
00009 
00010   currentSelection = new GUILabel("Unknown", "itemCBS_0");
00011   dropMenuButton   = new GUIButton("cbddb");
00012   upperPanel       = new GUIPanel("cbup");
00013   lowerPanel       = new GUIPanel("cblp");
00014 
00015   upperPanel->setLayout(PL_XAXIS_LAYOUT);
00016 
00017   upperPanel->setVisibleBounds(true);
00018   upperPanel->enableBGColor(true);
00019   upperPanel->setInterval(6, 3);
00020   upperPanel->addWidget(currentSelection);
00021   upperPanel->addWidget(dropMenuButton);
00022 
00023   lowerPanel->setLayout(PL_YAXIS_LAYOUT);
00024   lowerPanel->setInterval(6, 2);
00025   lowerPanel->setVisible(false);
00026   lowerPanel->enableBGColor(true);
00027   lowerPanel->setVisibleBounds(true);
00028   lowerPanel->setAnchorPoint(AT_CORNERLU);
00029   lowerPanel->setClipSize(0);
00030 
00031   displayScrollingRectangle =      true;
00032   selectionIndex            =        -1;
00033   widgetType                = WT_COMBO_BOX;
00034   fontIndex                 =         0;
00035   lockItems                 =     false;
00036   deployed                  =     false;
00037 }
00038 
00039 GUIComboBox::~GUIComboBox()
00040 {
00041   deleteObject(upperPanel);
00042   deleteObject(lowerPanel);  
00043 }
00044 
00045 GUIEventListener  *GUIComboBox::getEventsListener()
00046 {
00047   return this;
00048 }
00049 
00050 void  GUIComboBox::setFontScales(const Tuple2f &scales)
00051 {
00052   setFontScales(scales.x, scales.y);
00053 }
00054 
00055 void  GUIComboBox::setFontScales(float wScale, float hScale)
00056 {
00057   fontScales.x = clamp(hScale, 0.01f, 20.0f);
00058   fontScales.y = clamp(wScale, 0.01f, 20.0f);
00059 }
00060 
00061 const Tuple2f  &GUIComboBox::getFontScales()
00062 {
00063   return fontScales;
00064 }
00065 
00066 bool GUIComboBox::loadXMLSettings(const TiXmlElement *element)
00067 {
00068   if(!XMLArbiter::inspectElementInfo(element, "ComboBox"))
00069     return Logger::writeErrorLog("Need a ComboBox node in the xml file");
00070 
00071   const   TiXmlElement *child  = NULL;
00072   Tuple3f bordersColor         = upperPanel->getBordersColor();
00073   Tuple4f bgColor              = upperPanel->getBGColor();
00074   float   lowerPanelColorScale = 1.0f;
00075 
00076   if(child = XMLArbiter::getChildElementByName(element, "Button"))
00077   {
00078     dropMenuButton->loadXMLClippedRectangleInfo(child);
00079     dropMenuButton->loadXMLSettings(child);
00080     dropMenuButton->setCallbackString("cbddb");
00081     dropMenuButton->setLabelString("");
00082     dropMenuButton->setActive(true);
00083     dropMenuButton->setVisible(true);
00084   }
00085 
00086   displayScrollingRectangle = XMLArbiter::analyzeBooleanAttr(element, "displayScrollingRectangle", displayScrollingRectangle);
00087   lowerPanelColorScale      = XMLArbiter::fillComponents1f(element,   "lowerPanelColorScale", lowerPanelColorScale);
00088   fontScales.y              = XMLArbiter::fillComponents1f(element,   "hScale",    fontScales.y);
00089   fontScales.x              = XMLArbiter::fillComponents1f(element,   "wScale",    fontScales.x);
00090   fontIndex                 = XMLArbiter::fillComponents1i(element,   "fontIndex", fontIndex);
00091 
00092   for(child = element->FirstChildElement();     
00093       child;
00094           child = child->NextSiblingElement() )
00095   {
00096     const char *value = child->Value();
00097     if(!value)
00098       continue;
00099 
00100     if(!strcmp(value, "ScrollingColor"))
00101       setScrollingColor(XMLArbiter::fillComponents4f(child, scrollingColor));
00102 
00103     if(!strcmp(value, "BordersColor"))
00104       XMLArbiter::fillComponents3f(child, bordersColor);
00105 
00106     if(!strcmp(value, "BGColor"))
00107       XMLArbiter::fillComponents4f(child, bgColor);
00108 
00109     if(!strcmp(value, "Item"))
00110       addItem(child->Attribute("string"));
00111   }
00112 
00113   upperPanel->setBordersColor(bordersColor);
00114   lowerPanel->setBordersColor(bordersColor);
00115 
00116   upperPanel->setBGColor(bgColor);
00117   lowerPanel->setBGColor(bgColor.x*lowerPanelColorScale,
00118                          bgColor.y*lowerPanelColorScale,
00119                          bgColor.z*lowerPanelColorScale,
00120                          bgColor.w);
00121 
00122   setFontScales(fontScales);
00123 
00124   return GUIRectangle::loadXMLSettings(element) && (items.size() != 0);
00125 }
00126 
00127 void GUIComboBox::checkMouseEvents(MouseEvent &evt, int extraInfo, bool rBits)
00128 {
00129   upperPanel->checkMouseEvents(evt, extraInfo, rBits);
00130   scrollingRectangle.x = 1;
00131 
00132   if(lowerPanel->isVisible())
00133     lowerPanel->checkMouseEvents(evt, extraInfo, rBits);
00134 
00135   if(!currentSelection->isFocused() && !dropMenuButton->isFocused())
00136     deployed = false;
00137 
00138   if(deployed)
00139   {
00140     lowerPanel->setVisible(true);
00141     evt.consume();
00142   }
00143   else
00144     lowerPanel->setVisible(false);
00145 }
00146 
00147 void GUIComboBox::actionPerformed(GUIEvent &evt)
00148 {
00149   GUIEventListener  *eventsListener  = parent->getEventsListener();
00150   const std::string &cbs             = evt.getCallbackString();
00151   GUIRectangle      *sourceRectangle = evt.getEventSource();
00152   int                widgetType      = sourceRectangle->getWidgetType();
00153 
00154   if(currentSelection->isClicked() || dropMenuButton->isClicked())
00155     deployed = !deployed;
00156 
00157   if(widgetType == WT_LABEL && (sourceRectangle->getParent() == lowerPanel))
00158   {
00159     GUILabel *newSelection = (GUILabel*)sourceRectangle;
00160     if(newSelection->isMouseOver())
00161       scrollingRectangle = newSelection->getWindowBounds();
00162 
00163     if(newSelection->isClicked() && (newSelection->getLabelString() != currentSelection->getLabelString()))
00164     {
00165       currentSelection->setLabelString(newSelection->getLabelString());
00166       selectionIndex = getItemIndex(newSelection->getLabelString());
00167       update         = true;
00168       if(eventsListener)
00169                         {
00170                                 GUIEvent evt(this);
00171         eventsListener->actionPerformed(evt);
00172                         }
00173     }
00174   }
00175 }
00176 
00177 void GUIComboBox::render(float clockTick)
00178 {
00179   if(!parent || !visible)
00180     return;
00181 
00182   computeWindowBounds();
00183   upperPanel->render(clockTick);
00184 
00185   if(lowerPanel->isVisible())
00186   {
00187     lowerPanel->renderClippedBounds();
00188     lowerPanel->enableBGColor(false);
00189     lowerPanel->setVisibleBounds(false);
00190 
00191     if(scrollingRectangle.x >= lowerPanel->getWindowBounds().x && displayScrollingRectangle)
00192     {
00193 
00194       glEnable(GL_BLEND);
00195       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00196       glColor4fv(scrollingColor);
00197 
00198       glBegin(GL_TRIANGLE_STRIP);
00199       glVertex2i(scrollingRectangle.x - 2, scrollingRectangle.y);
00200       glVertex2i(scrollingRectangle.x - 2, scrollingRectangle.w);
00201       glVertex2i(scrollingRectangle.z + 1, scrollingRectangle.y);
00202       glVertex2i(scrollingRectangle.z + 1, scrollingRectangle.w);
00203       glEnd();
00204 
00205       glDisable(GL_BLEND);
00206     }
00207 
00208     lowerPanel->render(clockTick);
00209     lowerPanel->enableBGColor(true);
00210     lowerPanel->setVisibleBounds(true);
00211   }
00212 }
00213 
00214 void GUIComboBox::finalizeSize()
00215 {
00216   if(!items.size() || lockItems )
00217     return;
00218 
00219   GUIFont *font             = GUIFontManager::getFont(fontIndex);
00220   const    int    *spaces   = font ? font->getFontObject()->getCharHorizontalGlyphs() : NULL;
00221   float            maxWidth = 0,
00222                    height   = 0;
00223   int              cbsIndex = 1;
00224   if(spaces)
00225   {
00226     float  width    = 0;
00227     size_t length   = 0;
00228 
00229     height   =  float(font->getFontObject()->getHeight());
00230 
00231     for(size_t l = 0; l < items.size(); l++)
00232     {
00233       length = items[l].size();
00234       width  = 0.0f;
00235 
00236       for(size_t t = 0; t < length; t++)
00237         width += spaces[items[l][t]];
00238 
00239       maxWidth = width > maxWidth ? width : maxWidth;
00240     }
00241   }
00242   else
00243     return;
00244 
00245   currentSelection->setLabelString(items[0]);
00246   currentSelection->setDimensions(maxWidth*fontScales.x + 2.0f, height*fontScales.y);
00247   currentSelection->getLabel()->setFontIndex(fontIndex);
00248   currentSelection->getLabel()->setScales(fontScales);
00249   dropMenuButton->setDimensions(height*fontScales.y + 4.0f, height*fontScales.y + 4.0f);
00250 
00251   char buffer[256];
00252   
00253   for(size_t l = 0; l < items.size(); l++)
00254   {
00255     sprintf(buffer, "itemCBS %d", (cbsIndex++));
00256     GUILabel *newLabel = new GUILabel(items[l].c_str(), buffer);
00257     newLabel->getLabel()->setFontIndex(fontIndex);
00258     newLabel->setDimensions(maxWidth*fontScales.x + 2.0f /*+ height*fontScales.y + 10.0f*/, height*fontScales.y);
00259     newLabel->getLabel()->setScales(fontScales);
00260     if(!lowerPanel->addWidget(newLabel))
00261       deleteObject(newLabel);
00262   }
00263   selectionIndex =    0;
00264   lockItems      = true;
00265 }
00266 
00267 const void GUIComboBox::computeWindowBounds()
00268 {
00269   finalizeSize();
00270 
00271   if(parent && update)
00272   {
00273     upperPanel->setAnchorPoint(getAnchorPoint());
00274     upperPanel->setPosition(getPosition());
00275     upperPanel->setParent(parent);
00276     upperPanel->forceUpdate(true);
00277     upperPanel->computeWindowBounds();
00278     upperPanel->forceUpdate(false);
00279     windowBounds = upperPanel->getWindowBounds();
00280 
00281     lowerPanel->setPosition(0.0f, float(upperPanel->getHeight()));
00282     lowerPanel->setParent(upperPanel);
00283     lowerPanel->forceUpdate(true);
00284 
00285     //Redirect mouse events to combo box action listener
00286     lowerPanel->setParent(this);
00287     upperPanel->setParent(this);
00288   }
00289 }
00290 
00291 void GUIComboBox::addItem(const std::string &item)
00292 {
00293   if(lockItems || !item.size())
00294     return;
00295 
00296   for(size_t t = 0; t < items.size(); t++)
00297     if(items[t] == item)
00298       return;
00299 
00300   items.push_back(item);
00301 }
00302 
00303 int  GUIComboBox::getItemIndex(const std::string &item)
00304 {
00305   for(size_t t = 0; t < items.size(); t++)
00306     if(items[t] == item)
00307       return int(t);
00308 
00309   return -1;
00310 }
00311 
00312 const std::vector<std::string> &GUIComboBox::getItems() const
00313 {
00314   return items;
00315 }
00316 
00317 const char  *GUIComboBox::getSelectedItem()  const
00318 {
00319   return selectionIndex < 0 ? NULL : items[selectionIndex].c_str();
00320 }
00321 
00322 const char  *GUIComboBox::getItem(size_t index) const
00323 {
00324   return index >= items.size() ? NULL :  items[index].c_str();
00325 }
00326 
00327 void    GUIComboBox::setScrollingColor(float r, float g, float b, float a)
00328 {
00329   scrollingColor.set(clamp(r, 0.0f, 255.0f),
00330                      clamp(g, 0.0f, 255.0f),
00331                      clamp(b, 0.0f, 255.0f),
00332                      clamp(a, 0.0f, 255.0f));
00333 
00334   scrollingColor.x /= (scrollingColor.x > 1.0) ? 255.0f : 1.0f;
00335   scrollingColor.y /= (scrollingColor.y > 1.0) ? 255.0f : 1.0f;
00336   scrollingColor.z /= (scrollingColor.z > 1.0) ? 255.0f : 1.0f;
00337   scrollingColor.w /= (scrollingColor.w > 1.0) ? 255.0f : 1.0f;
00338 }
00339 
00340 void    GUIComboBox::setScrollingColor(const Tuple4f &rgba)
00341 {
00342   setScrollingColor(rgba.x, rgba.y, rgba.z, rgba.w);
00343 }
00344 
00345 const   Tuple4f &GUIComboBox::getScrollingColor() const
00346 {
00347   return  scrollingColor;
00348 }
00349 
00350 void    GUIComboBox::enableScrollingRectangle(bool on)
00351 {
00352   displayScrollingRectangle = on;
00353 }
00354 
00355 bool    GUIComboBox::scrollingRectangleEnabled()
00356 {
00357   return displayScrollingRectangle;
00358 }
00359 
00360 bool GUIComboBox::isDeployed()
00361 {
00362   if(lowerPanel) return lowerPanel->isVisible();
00363   return false;
00364 }

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