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);
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
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 }