00001 #include "gui_slider.hpp"
00002 #include "gui_frame.hpp"
00003 #include "gui_manager.hpp"
00004 #include "gui_texture.hpp"
00005 #include "gui_event.hpp"
00006 #include "gui_out.hpp"
00007
00008 #include <sstream>
00009
00010 namespace gui
00011 {
00012 void step_value(float& fValue, float fStep)
00013 {
00014
00015
00016 if (fStep != 0.0f)
00017 fValue = round(fValue/fStep)*fStep;
00018 }
00019
00020 slider::slider(manager* pManager) : frame(pManager),
00021 bUpdateThumbTexture_(false), mOrientation_(ORIENT_VERTICAL), fValue_(0.0f),
00022 fMinValue_(0.0f), fMaxValue_(1.0f), fValueStep_(0.1f), bAllowClicksOutsideThumb_(true),
00023 mThumbLayer_(LAYER_OVERLAY), pThumbTexture_(nullptr), bThumbMoved_(false), bMouseInThumb_(false)
00024 {
00025 enable_mouse(true);
00026 lType_.push_back("Slider");
00027 }
00028
00029 slider::~slider()
00030 {
00031 }
00032
00033 std::string slider::serialize(const std::string& sTab) const
00034 {
00035 std::ostringstream sStr;
00036
00037 sStr << frame::serialize(sTab);
00038 sStr << sTab << " # Orientation: ";
00039 switch (mOrientation_)
00040 {
00041 case ORIENT_HORIZONTAL : sStr << "HORIZONTAL"; break;
00042 case ORIENT_VERTICAL : sStr << "VERTICAL"; break;
00043 }
00044 sStr << "\n";
00045 sStr << sTab << " # Value : " << fValue_ << "\n";
00046 sStr << sTab << " # Min value : " << fMinValue_ << "\n";
00047 sStr << sTab << " # Max value : " << fMaxValue_ << "\n";
00048 sStr << sTab << " # Step : " << fValueStep_ << "\n";
00049 sStr << sTab << " # Click out : " << bAllowClicksOutsideThumb_ << "\n";
00050
00051 return sStr.str();
00052 }
00053
00054 bool slider::can_use_script(const std::string& sScriptName) const
00055 {
00056 if (frame::can_use_script(sScriptName))
00057 return true;
00058 else if (sScriptName == "OnValueChanged")
00059 return true;
00060 else
00061 return false;
00062 }
00063
00064 void slider::copy_from(uiobject* pObj)
00065 {
00066 frame::copy_from(pObj);
00067
00068 slider* pSlider = dynamic_cast<slider*>(pObj);
00069
00070 if (pSlider)
00071 {
00072 this->set_value_step(pSlider->get_value_step());
00073 this->set_min_value(pSlider->get_min_value());
00074 this->set_max_value(pSlider->get_max_value());
00075 this->set_value(pSlider->get_value());
00076 this->set_thumb_draw_layer(pSlider->get_thumb_draw_layer());
00077 this->set_orientation(pSlider->get_orientation());
00078 this->set_allow_clicks_outside_thumb(pSlider->are_clicks_outside_thumb_allowed());
00079
00080 texture* pThumb = pSlider->get_thumb_texture();
00081 if (pThumb)
00082 {
00083 this->create_thumb_texture_();
00084 if (this->is_virtual())
00085 pThumbTexture_->set_virtual();
00086 pThumbTexture_->set_name(pThumb->get_name());
00087 if (!pManager_->add_uiobject(pThumbTexture_))
00088 {
00089 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00090 "Trying to add \""+pThumb->get_name()+"\" to \""+sName_+"\",\n"
00091 "but its name was already taken : \""+pThumbTexture_->get_name()+"\". Skipped." << std::endl;
00092 delete pThumbTexture_; pThumbTexture_ = nullptr;
00093 }
00094 else
00095 {
00096 if (!is_virtual())
00097 pThumbTexture_->create_glue();
00098
00099 this->add_region(pThumbTexture_);
00100 pThumbTexture_->copy_from(pThumb);
00101 pThumbTexture_->notify_loaded();
00102 }
00103 }
00104 }
00105 }
00106
00107 void slider::constrain_thumb_()
00108 {
00109 if (fMaxValue_ == fMinValue_)
00110 return;
00111
00112 if ((mOrientation_ == ORIENT_HORIZONTAL && uiAbsWidth_ != 0) ||
00113 (mOrientation_ == ORIENT_VERTICAL && uiAbsHeight_ != 0))
00114 {
00115 float fValue = 0.0f;
00116
00117 if (bThumbMoved_)
00118 {
00119 if (mOrientation_ == ORIENT_HORIZONTAL)
00120 fValue = float(pThumbTexture_->get_point(ANCHOR_CENTER)->get_abs_offset_x())/float(uiAbsWidth_);
00121 else
00122 fValue = float(pThumbTexture_->get_point(ANCHOR_CENTER)->get_abs_offset_y())/float(uiAbsHeight_);
00123
00124 fValue *= (fMaxValue_ - fMinValue_);
00125 fValue += fMinValue_;
00126 fValue = fValue > fMaxValue_ ? fMaxValue_ : (fValue < fMinValue_ ? fMinValue_ : fValue);
00127 step_value(fValue, fValueStep_);
00128 }
00129
00130 float fCoef = (fValue - fMinValue_)/(fMaxValue_ - fMinValue_);
00131
00132 anchor* pAnchor = pThumbTexture_->modify_point(ANCHOR_CENTER);
00133 if (mOrientation_ == ORIENT_HORIZONTAL)
00134 pAnchor->set_abs_offset(uiAbsWidth_*fCoef, 0);
00135 else
00136 pAnchor->set_abs_offset(0, uiAbsHeight_*fCoef);
00137 }
00138 }
00139
00140 void slider::on_event(const event& mEvent)
00141 {
00142 frame::on_event(mEvent);
00143
00144 if (bIsMouseEnabled_ && pManager_->is_input_enabled())
00145 {
00146 if (mEvent.get_name() == "MOUSE_PRESSED")
00147 {
00148 if (bMouseInThumb_)
00149 {
00150 pManager_->start_moving(
00151 pThumbTexture_, pThumbTexture_->modify_point(ANCHOR_CENTER),
00152 mOrientation_ == ORIENT_HORIZONTAL ? CONSTRAINT_X : CONSTRAINT_Y,
00153 std::bind(&slider::constrain_thumb_, this)
00154 );
00155 bThumbMoved_ = true;
00156 }
00157 else if (bMouseInFrame_ && bAllowClicksOutsideThumb_)
00158 {
00159 float fValue;
00160 if (mOrientation_ == ORIENT_HORIZONTAL)
00161 {
00162 float fOffset = float(iMousePosX_ - lBorderList_[BORDER_LEFT]);
00163 fValue = fOffset/uiAbsWidth_;
00164 set_value(fValue*(fMaxValue_ - fMinValue_) + fMinValue_);
00165 }
00166 else
00167 {
00168 float fOffset = float(iMousePosY_ - lBorderList_[BORDER_TOP]);
00169 fValue = fOffset/uiAbsHeight_;
00170 set_value(fValue*(fMaxValue_ - fMinValue_) + fMinValue_);
00171 }
00172
00173 if (pThumbTexture_)
00174 {
00175 float fCoef = (fValue_ - fMinValue_)/(fMaxValue_ - fMinValue_);
00176
00177 anchor* pAnchor = pThumbTexture_->modify_point(ANCHOR_CENTER);
00178 if (mOrientation_ == ORIENT_HORIZONTAL)
00179 pAnchor->set_abs_offset(uiAbsWidth_*fCoef, 0);
00180 else
00181 pAnchor->set_abs_offset(0, uiAbsHeight_*fCoef);
00182
00183 pManager_->start_moving(
00184 pThumbTexture_, pThumbTexture_->modify_point(ANCHOR_CENTER),
00185 mOrientation_ == ORIENT_HORIZONTAL ? CONSTRAINT_X : CONSTRAINT_Y
00186 );
00187 bThumbMoved_ = true;
00188 }
00189 }
00190 }
00191 else if (mEvent.get_name() == "MOUSE_RELEASED")
00192 {
00193 if (pThumbTexture_)
00194 {
00195 pManager_->stop_moving(pThumbTexture_);
00196 bThumbMoved_ = false;
00197 }
00198 }
00199 }
00200 }
00201
00202 void slider::set_min_value(float fMin)
00203 {
00204 if (fMin != fMinValue_)
00205 {
00206 fMinValue_ = fMin;
00207 if (fMinValue_ > fMaxValue_) fMinValue_ = fMaxValue_;
00208 else step_value(fMinValue_, fValueStep_);
00209
00210 if (fValue_ < fMinValue_)
00211 {
00212 fValue_ = fMinValue_;
00213 lQueuedEventList_.push_back("ValueChanged");
00214 }
00215
00216 fire_update_thumb_texture_();
00217 }
00218 }
00219
00220 void slider::set_max_value(float fMax)
00221 {
00222 if (fMax != fMaxValue_)
00223 {
00224 fMaxValue_ = fMax;
00225 if (fMaxValue_ < fMaxValue_) fMaxValue_ = fMinValue_;
00226 else step_value(fMaxValue_, fValueStep_);
00227
00228 if (fValue_ > fMaxValue_)
00229 {
00230 fValue_ = fMaxValue_;
00231 lQueuedEventList_.push_back("ValueChanged");
00232 }
00233
00234 fire_update_thumb_texture_();
00235 }
00236 }
00237
00238 void slider::set_min_max_values(float fMin, float fMax)
00239 {
00240 if (fMin != fMinValue_ || fMax != fMaxValue_)
00241 {
00242 fMinValue_ = std::min(fMin, fMax);
00243 fMaxValue_ = std::max(fMin, fMax);
00244 step_value(fMinValue_, fValueStep_);
00245 step_value(fMaxValue_, fValueStep_);
00246
00247 if (fValue_ > fMaxValue_ || fValue_ < fMinValue_)
00248 {
00249 fValue_ = fValue_ > fMaxValue_ ? fMaxValue_ : (fValue_ < fMinValue_ ? fMinValue_ : fValue_);
00250 lQueuedEventList_.push_back("ValueChanged");
00251 }
00252
00253 fire_update_thumb_texture_();
00254 }
00255 }
00256
00257 void slider::set_value(float fValue, bool bSilent)
00258 {
00259 if (fValue != fValue_)
00260 {
00261 fValue_ = fValue;
00262 fValue_ = fValue_ > fMaxValue_ ? fMaxValue_ : (fValue_ < fMinValue_ ? fMinValue_ : fValue_);
00263 step_value(fValue_, fValueStep_);
00264
00265 if (!bSilent)
00266 lQueuedEventList_.push_back("ValueChanged");
00267
00268 fire_update_thumb_texture_();
00269 }
00270 }
00271
00272 void slider::set_value_step(float fValueStep)
00273 {
00274 if (fValueStep_ != fValueStep)
00275 {
00276 fValueStep_ = fValueStep;
00277
00278 step_value(fMinValue_, fValueStep_);
00279 step_value(fMaxValue_, fValueStep_);
00280
00281 float fOldValue = fValue_;
00282 step_value(fValue_, fValueStep_);
00283 fValue_ = fValue_ > fMaxValue_ ? fMaxValue_ : (fValue_ < fMinValue_ ? fMinValue_ : fValue_);
00284
00285 if (fValue_ != fOldValue)
00286 lQueuedEventList_.push_back("ValueChanged");
00287
00288 fire_update_thumb_texture_();
00289 }
00290 }
00291
00292 void slider::set_thumb_texture(texture* pTexture)
00293 {
00294 pThumbTexture_ = pTexture;
00295 pThumbTexture_->clear_all_points();
00296 pThumbTexture_->set_point(anchor(
00297 pThumbTexture_, ANCHOR_CENTER, sName_,
00298 mOrientation_ == ORIENT_HORIZONTAL ? ANCHOR_LEFT : ANCHOR_TOP
00299 ));
00300
00301 fire_update_thumb_texture_();
00302 }
00303
00304 void slider::set_orientation(orientation mOrientation)
00305 {
00306 if (mOrientation != mOrientation_)
00307 {
00308 mOrientation_ = mOrientation;
00309 if (pThumbTexture_)
00310 {
00311 pThumbTexture_->set_point(anchor(
00312 pThumbTexture_, ANCHOR_CENTER, sName_,
00313 mOrientation_ == ORIENT_HORIZONTAL ? ANCHOR_LEFT : ANCHOR_TOP
00314 ));
00315 }
00316
00317 fire_update_thumb_texture_();
00318 }
00319 }
00320
00321 void slider::set_thumb_draw_layer(layer_type mThumbLayer)
00322 {
00323 mThumbLayer_ = mThumbLayer;
00324 if (pThumbTexture_)
00325 pThumbTexture_->set_draw_layer(mThumbLayer_);
00326 }
00327
00328 void slider::set_thumb_draw_layer(const std::string& sThumbLayer)
00329 {
00330 if (sThumbLayer == "ARTWORK")
00331 mThumbLayer_ = LAYER_ARTWORK;
00332 else if (sThumbLayer == "BACKGROUND")
00333 mThumbLayer_ = LAYER_BACKGROUND;
00334 else if (sThumbLayer == "BORDER")
00335 mThumbLayer_ = LAYER_BORDER;
00336 else if (sThumbLayer == "HIGHLIGHT")
00337 mThumbLayer_ = LAYER_HIGHLIGHT;
00338 else if (sThumbLayer == "OVERLAY")
00339 mThumbLayer_ = LAYER_OVERLAY;
00340 else
00341 {
00342 gui::out << gui::warning << "gui::" << lType_.back() << " : "
00343 "Uknown layer type : \""+sThumbLayer+"\". Using \"OVERLAY\"." << std::endl;
00344 mThumbLayer_ = LAYER_OVERLAY;
00345 }
00346
00347 if (pThumbTexture_)
00348 pThumbTexture_->set_draw_layer(mThumbLayer_);
00349 }
00350
00351 float slider::get_min_value() const
00352 {
00353 return fMinValue_;
00354 }
00355
00356 float slider::get_max_value() const
00357 {
00358 return fMaxValue_;
00359 }
00360
00361 float slider::get_value() const
00362 {
00363 return fValue_;
00364 }
00365
00366 float slider::get_value_step() const
00367 {
00368 return fValueStep_;
00369 }
00370
00371 texture* slider::get_thumb_texture() const
00372 {
00373 return pThumbTexture_;
00374 }
00375
00376 slider::orientation slider::get_orientation() const
00377 {
00378 return mOrientation_;
00379 }
00380
00381 layer_type slider::get_thumb_draw_layer() const
00382 {
00383 return mThumbLayer_;
00384 }
00385
00386 void slider::set_allow_clicks_outside_thumb(bool bAllow)
00387 {
00388 bAllowClicksOutsideThumb_ = bAllow;
00389 }
00390
00391 bool slider::are_clicks_outside_thumb_allowed()
00392 {
00393 return bAllowClicksOutsideThumb_;
00394 }
00395
00396 texture* slider::create_thumb_texture_()
00397 {
00398 if (!pThumbTexture_)
00399 {
00400 pThumbTexture_ = new texture(pManager_);
00401 pThumbTexture_->set_special();
00402 pThumbTexture_->set_parent(this);
00403 pThumbTexture_->set_draw_layer(mThumbLayer_);
00404 }
00405
00406 return pThumbTexture_;
00407 }
00408
00409 bool slider::is_in_frame(int iX, int iY) const
00410 {
00411 if (bAllowClicksOutsideThumb_)
00412 {
00413 if (pThumbTexture_)
00414 return frame::is_in_frame(iX, iY) || pThumbTexture_->is_in_region(iX, iY);
00415 else
00416 return frame::is_in_frame(iX, iY);
00417 }
00418 else
00419 {
00420 if (pThumbTexture_)
00421 return pThumbTexture_->is_in_region(iX, iY);
00422 else
00423 return false;
00424 }
00425 }
00426
00427 void slider::notify_mouse_in_frame(bool bMouseInFrame, int iX, int iY)
00428 {
00429 if (bAllowClicksOutsideThumb_)
00430 frame::notify_mouse_in_frame(bMouseInFrame, iX, iY);
00431
00432 bMouseInThumb_ = (bMouseInFrame && pThumbTexture_ && pThumbTexture_->is_in_region(iX, iY));
00433 }
00434
00435 void slider::update(float fDelta)
00436 {
00437 frame::update(fDelta);
00438
00439 if ((bUpdateThumbTexture_ || bThumbMoved_) && pThumbTexture_)
00440 {
00441 if ((mOrientation_ == ORIENT_HORIZONTAL && uiAbsWidth_ != 0) ||
00442 (mOrientation_ == ORIENT_VERTICAL && uiAbsHeight_ != 0))
00443 {
00444 if (fMaxValue_ == fMinValue_)
00445 {
00446 pThumbTexture_->hide();
00447 return;
00448 }
00449 else
00450 pThumbTexture_->show();
00451
00452 float fOldValue = fValue_;
00453
00454 if (bThumbMoved_)
00455 {
00456 if (mOrientation_ == ORIENT_HORIZONTAL)
00457 fValue_ = float(pThumbTexture_->get_point(ANCHOR_CENTER)->get_abs_offset_x())/float(uiAbsWidth_);
00458 else
00459 fValue_ = float(pThumbTexture_->get_point(ANCHOR_CENTER)->get_abs_offset_y())/float(uiAbsHeight_);
00460
00461 fValue_ *= (fMaxValue_ - fMinValue_);
00462 fValue_ += fMinValue_;
00463 fValue_ = fValue_ > fMaxValue_ ? fMaxValue_ : (fValue_ < fMinValue_ ? fMinValue_ : fValue_);
00464 step_value(fValue_, fValueStep_);
00465
00466 if (fValue_ != fOldValue)
00467 lQueuedEventList_.push_back("ValueChanged");
00468 }
00469
00470 float fCoef = (fValue_ - fMinValue_)/(fMaxValue_ - fMinValue_);
00471
00472 anchor* pAnchor = pThumbTexture_->modify_point(ANCHOR_CENTER);
00473 if (mOrientation_ == ORIENT_HORIZONTAL)
00474 pAnchor->set_abs_offset(uiAbsWidth_*fCoef, 0);
00475 else
00476 pAnchor->set_abs_offset(0, uiAbsHeight_*fCoef);
00477
00478 pThumbTexture_->fire_update_borders();
00479 pThumbTexture_->update(fDelta);
00480
00481
00482
00483
00484
00485
00486 bUpdateThumbTexture_ = false;
00487 }
00488 }
00489 }
00490
00491 void slider::fire_update_borders() const
00492 {
00493 frame::fire_update_borders();
00494 fire_update_thumb_texture_();
00495 }
00496
00497 void slider::create_glue()
00498 {
00499 if (bVirtual_)
00500 {
00501 utils::wptr<lua::state> pLua = pManager_->get_lua();
00502 pLua->push_number(uiID_);
00503 lGlueList_.push_back(pLua->push_new<lua_virtual_glue>());
00504 pLua->set_global(sLuaName_);
00505 pLua->pop();
00506 }
00507 else
00508 {
00509 utils::wptr<lua::state> pLua = pManager_->get_lua();
00510 pLua->push_string(sLuaName_);
00511 lGlueList_.push_back(pLua->push_new<lua_slider>());
00512 pLua->set_global(sLuaName_);
00513 pLua->pop();
00514 }
00515 }
00516
00517 void slider::fire_update_thumb_texture_() const
00518 {
00519 bUpdateThumbTexture_ = true;
00520 }
00521 }