MyGUI
3.0.3
|
00001 00007 /* 00008 This file is part of MyGUI. 00009 00010 MyGUI is free software: you can redistribute it and/or modify 00011 it under the terms of the GNU Lesser General Public License as published by 00012 the Free Software Foundation, either version 3 of the License, or 00013 (at your option) any later version. 00014 00015 MyGUI is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU Lesser General Public License for more details. 00019 00020 You should have received a copy of the GNU Lesser General Public License 00021 along with MyGUI. If not, see <http://www.gnu.org/licenses/>. 00022 */ 00023 #include "MyGUI_Precompiled.h" 00024 #include "MyGUI_ItemBox.h" 00025 #include "MyGUI_Button.h" 00026 #include "MyGUI_VScroll.h" 00027 #include "MyGUI_HScroll.h" 00028 #include "MyGUI_ResourceSkin.h" 00029 #include "MyGUI_InputManager.h" 00030 #include "MyGUI_Gui.h" 00031 #include "MyGUI_WidgetTranslate.h" 00032 #include "MyGUI_WidgetManager.h" 00033 00034 namespace MyGUI 00035 { 00036 00037 ItemBox::ItemBox() : 00038 mCountItemInLine(0), 00039 mCountLines(0), 00040 mFirstVisibleIndex(0), 00041 mFirstOffsetIndex(0), 00042 mIndexSelect(ITEM_NONE), 00043 mIndexActive(ITEM_NONE), 00044 mIndexAccept(ITEM_NONE), 00045 mIndexRefuse(ITEM_NONE), 00046 mIsFocus(false), 00047 mItemDrag(nullptr), 00048 mAlignVert(true) 00049 { 00050 mChangeContentByResize = true; 00051 } 00052 00053 void ItemBox::_initialise(WidgetStyle _style, const IntCoord& _coord, Align _align, ResourceSkin* _info, Widget* _parent, ICroppedRectangle * _croppedParent, IWidgetCreator * _creator, const std::string& _name) 00054 { 00055 Base::_initialise(_style, _coord, _align, _info, _parent, _croppedParent, _creator, _name); 00056 00057 initialiseWidgetSkin(_info); 00058 } 00059 00060 ItemBox::~ItemBox() 00061 { 00062 shutdownWidgetSkin(); 00063 } 00064 00065 void ItemBox::baseChangeWidgetSkin(ResourceSkin* _info) 00066 { 00067 shutdownWidgetSkin(); 00068 Base::baseChangeWidgetSkin(_info); 00069 initialiseWidgetSkin(_info); 00070 } 00071 00072 void ItemBox::initialiseWidgetSkin(ResourceSkin* _info) 00073 { 00074 // нам нужен фокус клавы 00075 mNeedKeyFocus = true; 00076 mDragLayer = "DragAndDrop"; 00077 00078 const MapString& properties = _info->getProperties(); 00079 if (!properties.empty()) 00080 { 00081 MapString::const_iterator iter = properties.find("AlignVert"); 00082 if (iter != properties.end()) mAlignVert = utility::parseBool(iter->second); 00083 iter = properties.find("DragLayer"); 00084 if (iter != properties.end()) mDragLayer = iter->second; 00085 } 00086 00087 for (VectorWidgetPtr::iterator iter=mWidgetChildSkin.begin(); iter!=mWidgetChildSkin.end(); ++iter) 00088 { 00089 if (*(*iter)->_getInternalData<std::string>() == "VScroll") 00090 { 00091 MYGUI_DEBUG_ASSERT( ! mVScroll, "widget already assigned"); 00092 mVScroll = (*iter)->castType<VScroll>(); 00093 mVScroll->eventScrollChangePosition = newDelegate(this, &ItemBox::notifyScrollChangePosition); 00094 } 00095 if (*(*iter)->_getInternalData<std::string>() == "HScroll") 00096 { 00097 MYGUI_DEBUG_ASSERT( ! mHScroll, "widget already assigned"); 00098 mHScroll = (*iter)->castType<HScroll>(); 00099 mHScroll->eventScrollChangePosition = newDelegate(this, &ItemBox::notifyScrollChangePosition); 00100 } 00101 else if (*(*iter)->_getInternalData<std::string>() == "Client") 00102 { 00103 MYGUI_DEBUG_ASSERT( ! mWidgetClient, "widget already assigned"); 00104 mWidgetClient = (*iter); 00105 mWidgetClient->eventMouseWheel = newDelegate(this, &ItemBox::notifyMouseWheel); 00106 mWidgetClient->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMouseButtonPressed); 00107 mWidgetClient->eventMouseButtonReleased = newDelegate(this, &ItemBox::notifyMouseButtonReleased); 00108 mClient = mWidgetClient; 00109 } 00110 } 00111 // сли нет скрола, то клиенская зона не обязательно 00112 //MYGUI_ASSERT(nullptr != mWidgetClient, "Child Widget Client not found in skin (ItemBox must have Client) skin ='" << _info->getSkinName() << "'"); 00113 00114 // подписываем клиент для драгэндропа 00115 if (mWidgetClient != nullptr) 00116 mWidgetClient->_requestGetContainer = newDelegate(this, &ItemBox::_requestGetContainer); 00117 00118 requestItemSize(); 00119 00120 updateScrollSize(); 00121 updateScrollPosition(); 00122 } 00123 00124 void ItemBox::shutdownWidgetSkin() 00125 { 00126 mVScroll = nullptr; 00127 mHScroll = nullptr; 00128 mClient = nullptr; 00129 mWidgetClient = nullptr; 00130 } 00131 00132 void ItemBox::setPosition(const IntPoint& _point) 00133 { 00134 Base::setPosition(_point); 00135 } 00136 00137 void ItemBox::setSize(const IntSize& _size) 00138 { 00139 Base::setSize(_size); 00140 updateFromResize(); 00141 } 00142 00143 void ItemBox::setCoord(const IntCoord& _coord) 00144 { 00145 Base::setCoord(_coord); 00146 updateFromResize(); 00147 } 00148 00149 void ItemBox::requestItemSize() 00150 { 00151 IntCoord coord(0, 0, 1, 1); 00152 00153 // спрашиваем размер иконок 00154 requestCoordItem(this, coord, false); 00155 00156 mSizeItem = coord.size(); 00157 MYGUI_ASSERT((mSizeItem.width > 0 && mSizeItem.height > 0), "(mSizeItem.width > 0 && mSizeItem.height > 0) at requestCoordWidgetItem"); 00158 } 00159 00160 void ItemBox::updateFromResize() 00161 { 00162 requestItemSize(); 00163 00164 updateScrollSize(); 00165 updateScrollPosition(); 00166 00167 _updateAllVisible(true); 00168 _resetContainer(true); 00169 } 00170 00171 void ItemBox::_updateAllVisible(bool _redraw) 00172 { 00173 int count_visible = 0; 00174 if (mAlignVert) 00175 { 00176 count_visible = (_getClientWidget()->getHeight() / mSizeItem.height) + 2; 00177 } 00178 else 00179 { 00180 count_visible = (_getClientWidget()->getWidth() / mSizeItem.width) + 2; 00181 } 00182 00183 size_t start = (mFirstVisibleIndex * mCountItemInLine); 00184 size_t count = (count_visible * mCountItemInLine) + start; 00185 00186 size_t index = 0; 00187 for (size_t pos = start; pos<count; ++pos, ++index) 00188 { 00189 // дальше нет айтемов 00190 if (pos >= mItemsInfo.size()) break; 00191 00192 Widget* item = getItemWidget(index); 00193 if (mAlignVert) 00194 { 00195 item->setPosition(((int)index % mCountItemInLine) * mSizeItem.width - mContentPosition.left, 00196 (((int)index / mCountItemInLine) * mSizeItem.height) - mFirstOffsetIndex); 00197 } 00198 else 00199 { 00200 item->setPosition((((int)index / mCountItemInLine) * mSizeItem.width) - mFirstOffsetIndex, 00201 ((int)index % mCountItemInLine) * mSizeItem.height - mContentPosition.top); 00202 } 00203 00204 item->setSize(mSizeItem); 00205 item->setVisible(true); 00206 00207 if (_redraw) 00208 { 00209 IBDrawItemInfo data(pos, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false); 00210 requestDrawItem(this, item, data); 00211 } 00212 00213 } 00214 00215 // все виджеты еще есть, то их надо бы скрыть 00216 while (index < mVectorItems.size()) 00217 { 00218 mVectorItems[index]->setVisible(false); 00219 index ++; 00220 } 00221 00222 } 00223 00224 Widget* ItemBox::getItemWidget(size_t _index) 00225 { 00226 // еще нет такого виджета, нуно создать 00227 if (_index == mVectorItems.size()) 00228 { 00229 00230 requestItemSize(); 00231 00232 Widget* item = _getClientWidget()->createWidget<Widget>("Default", IntCoord(0, 0, mSizeItem.width, mSizeItem.height), Align::Default); 00233 00234 // вызываем запрос на создание виджета 00235 requestCreateWidgetItem(this, item); 00236 00237 item->eventMouseWheel = newDelegate(this, &ItemBox::notifyMouseWheel); 00238 item->eventRootMouseChangeFocus = newDelegate(this, &ItemBox::notifyRootMouseChangeFocus); 00239 item->eventMouseButtonPressed = newDelegate(this, &ItemBox::notifyMouseButtonPressed); 00240 item->eventMouseButtonReleased = newDelegate(this, &ItemBox::notifyMouseButtonReleased); 00241 item->eventMouseButtonDoubleClick = newDelegate(this, &ItemBox::notifyMouseButtonDoubleClick); 00242 item->eventMouseDrag = newDelegate(this, &ItemBox::notifyMouseDrag); 00243 item->_requestGetContainer = newDelegate(this, &ItemBox::_requestGetContainer); 00244 item->eventKeyButtonPressed = newDelegate(this, &ItemBox::notifyKeyButtonPressed); 00245 item->eventKeyButtonReleased = newDelegate(this, &ItemBox::notifyKeyButtonReleased); 00246 00247 item->_setInternalData((size_t)mVectorItems.size()); 00248 00249 mVectorItems.push_back(item); 00250 } 00251 00252 // запрашивать только последовательно 00253 MYGUI_ASSERT_RANGE(_index, mVectorItems.size(), "ItemBox::getItemWidget"); 00254 00255 return mVectorItems[_index]; 00256 } 00257 00258 void ItemBox::onMouseWheel(int _rel) 00259 { 00260 notifyMouseWheel(nullptr, _rel); 00261 00262 Base::onMouseWheel(_rel); 00263 } 00264 00265 void ItemBox::onKeySetFocus(Widget* _old) 00266 { 00267 mIsFocus = true; 00268 setState("pushed"); 00269 00270 Base::onKeySetFocus(_old); 00271 } 00272 00273 void ItemBox::onKeyLostFocus(Widget* _new) 00274 { 00275 mIsFocus = false; 00276 setState("normal"); 00277 00278 Base::onKeyLostFocus(_new); 00279 } 00280 00281 void ItemBox::resetCurrentActiveItem() 00282 { 00283 // сбрасываем старую подсветку 00284 if (mIndexActive != ITEM_NONE) 00285 { 00286 size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine); 00287 size_t index = mIndexActive; 00288 mIndexActive = ITEM_NONE; 00289 00290 // если видим, то обновляем 00291 if ((mIndexActive >= start) && (mIndexActive < (start + mVectorItems.size()))) 00292 { 00293 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00294 00295 requestDrawItem(this, mVectorItems[mIndexActive - start], data); 00296 } 00297 } 00298 } 00299 00300 void ItemBox::findCurrentActiveItem() 00301 { 00302 MYGUI_DEBUG_ASSERT(mIndexActive == ITEM_NONE, "use : resetCurrentActiveItem() before findCurrentActiveItem()"); 00303 00304 const IntPoint& point = InputManager::getInstance().getMousePositionByLayer(); 00305 00306 // сначала проверяем клиентскую зону 00307 const IntRect& rect = _getClientAbsoluteRect(); 00308 if ((point.left < rect.left) || (point.left > rect.right) || (point.top < rect.top) || (point.top > rect.bottom)) 00309 { 00310 return; 00311 } 00312 00313 for (size_t pos=0; pos<mVectorItems.size(); ++pos) 00314 { 00315 Widget* item = mVectorItems[pos]; 00316 const IntRect& abs_rect = item->getAbsoluteRect(); 00317 if ((point.left>= abs_rect.left) && (point.left <= abs_rect.right) && (point.top>= abs_rect.top) && (point.top <= abs_rect.bottom)) 00318 { 00319 00320 size_t index = calcIndexByWidget(item); 00321 // при переборе индекс может быть больше, так как может создасться сколько угодно 00322 if (index < mItemsInfo.size()) 00323 { 00324 00325 mIndexActive = index; 00326 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00327 00328 requestDrawItem(this, item, data); 00329 } 00330 00331 break; 00332 } 00333 } 00334 } 00335 00336 void ItemBox::_requestGetContainer(Widget* _sender, Widget*& _container, size_t& _index) 00337 { 00338 if (_sender == _getClientWidget()) 00339 { 00340 _container = this; 00341 _index = ITEM_NONE; 00342 } 00343 else 00344 { 00345 size_t index = calcIndexByWidget(_sender); 00346 if (index < mItemsInfo.size()) 00347 { 00348 _container = this; 00349 _index = index; 00350 } 00351 } 00352 } 00353 00354 void ItemBox::_setContainerItemInfo(size_t _index, bool _set, bool _accept) 00355 { 00356 if (_index == ITEM_NONE) return; 00357 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::_setContainerItemInfo"); 00358 00359 mIndexAccept = (_set && _accept ) ? _index : ITEM_NONE; 00360 mIndexRefuse = (_set && !_accept) ? _index : ITEM_NONE; 00361 00362 size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine); 00363 if ((_index >= start) && (_index < (start + mVectorItems.size()))) 00364 { 00365 IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00366 requestDrawItem(this, mVectorItems[_index - start], data); 00367 } 00368 } 00369 00370 void ItemBox::setItemDataAt(size_t _index, Any _data) 00371 { 00372 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::setItemData"); 00373 mItemsInfo[_index].data = _data; 00374 00375 size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine); 00376 if ((_index >= start) && (_index < (start + mVectorItems.size()))) 00377 { 00378 IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false); 00379 requestDrawItem(this, mVectorItems[_index - start], data); 00380 } 00381 00382 _resetContainer(true); 00383 } 00384 00385 void ItemBox::insertItemAt(size_t _index, Any _data) 00386 { 00387 MYGUI_ASSERT_RANGE_INSERT(_index, mItemsInfo.size(), "ItemBox::insertItemAt"); 00388 if (_index == ITEM_NONE) _index = mItemsInfo.size(); 00389 00390 _resetContainer(false); 00391 00392 resetCurrentActiveItem(); 00393 00394 mItemsInfo.insert(mItemsInfo.begin() + _index, ItemDataInfo(_data)); 00395 00396 // расчитываем новый индекс выделения 00397 if (mIndexSelect != ITEM_NONE) 00398 { 00399 if (mIndexSelect >= _index) 00400 { 00401 mIndexSelect ++; 00402 } 00403 } 00404 00405 updateScrollSize(); 00406 updateScrollPosition(); 00407 00408 findCurrentActiveItem(); 00409 00410 _updateAllVisible(true); 00411 } 00412 00413 void ItemBox::removeItemAt(size_t _index) 00414 { 00415 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::removeItemAt"); 00416 00417 _resetContainer(false); 00418 resetCurrentActiveItem(); 00419 00420 mItemsInfo.erase(mItemsInfo.begin() + _index); 00421 00422 // расчитываем новый индекс выделения 00423 if (mIndexSelect != ITEM_NONE) 00424 { 00425 if (mItemsInfo.empty()) 00426 { 00427 mIndexSelect = ITEM_NONE; 00428 } 00429 else if ((mIndexSelect > _index) || (mIndexSelect == mItemsInfo.size())) 00430 { 00431 mIndexSelect --; 00432 } 00433 } 00434 00435 updateScrollSize(); 00436 updateScrollPosition(); 00437 00438 findCurrentActiveItem(); 00439 00440 _updateAllVisible(true); 00441 } 00442 00443 void ItemBox::removeAllItems() 00444 { 00445 if (0 == mItemsInfo.size()) return; 00446 _resetContainer(false); 00447 00448 mItemsInfo.clear(); 00449 00450 mIndexSelect = ITEM_NONE; 00451 mIndexActive = ITEM_NONE; 00452 00453 updateScrollSize(); 00454 updateScrollPosition(); 00455 00456 _updateAllVisible(true); 00457 } 00458 00459 void ItemBox::redrawItemAt(size_t _index) 00460 { 00461 MYGUI_ASSERT_RANGE(_index, mItemsInfo.size(), "ItemBox::redrawItemAt"); 00462 00463 size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine); 00464 if ((_index >= start) && (_index < (start + mVectorItems.size()))) 00465 { 00466 IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, true, false); 00467 requestDrawItem(this, mVectorItems[_index - start], data); 00468 } 00469 } 00470 00471 void ItemBox::setIndexSelected(size_t _index) 00472 { 00473 MYGUI_ASSERT_RANGE_AND_NONE(_index, mItemsInfo.size(), "ItemBox::setIndexSelected"); 00474 if (_index == mIndexSelect) return; 00475 00476 size_t start = (size_t)(mFirstVisibleIndex * mCountItemInLine); 00477 00478 // сбрасываем старое выделение 00479 if (mIndexSelect != ITEM_NONE) 00480 { 00481 size_t index = mIndexSelect; 00482 mIndexSelect = ITEM_NONE; 00483 00484 if ((index >= start) && (index < (start + mVectorItems.size()))) 00485 { 00486 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00487 requestDrawItem(this, mVectorItems[index - start], data); 00488 } 00489 } 00490 00491 mIndexSelect = _index; 00492 if (mIndexSelect != ITEM_NONE) 00493 { 00494 if ((_index >= start) && (_index < (start + mVectorItems.size()))) 00495 { 00496 IBDrawItemInfo data(_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00497 requestDrawItem(this, mVectorItems[_index - start], data); 00498 } 00499 } 00500 00501 } 00502 00503 void ItemBox::notifyMouseButtonDoubleClick(Widget* _sender) 00504 { 00505 size_t index = getIndexByWidget(_sender); 00506 00507 eventSelectItemAccept(this, index); 00508 } 00509 00510 void ItemBox::setItemBoxAlignVert(bool _vert) 00511 { 00512 if (mAlignVert == _vert) return; 00513 mAlignVert = _vert; 00514 00515 mCountItemInLine = -1; 00516 updateFromResize(); 00517 } 00518 00519 void ItemBox::notifyKeyButtonPressed(Widget* _sender, KeyCode _key, Char _char) 00520 { 00521 eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyPressed, _key, _char)); 00522 } 00523 00524 void ItemBox::notifyKeyButtonReleased(Widget* _sender, KeyCode _key) 00525 { 00526 eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::KeyReleased, _key)); 00527 } 00528 00529 size_t ItemBox::getIndexByWidget(Widget* _widget) 00530 { 00531 MYGUI_ASSERT(_widget, "ItemBox::getIndexByWidget : Widget == nullptr"); 00532 if (_widget == _getClientWidget()) return ITEM_NONE; 00533 MYGUI_ASSERT(_widget->getParent() == _getClientWidget(), "ItemBox::getIndexByWidget : Widget is not child"); 00534 00535 size_t index = calcIndexByWidget(_widget); 00536 MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::getIndexByWidget"); 00537 00538 return index; 00539 } 00540 00541 size_t ItemBox::_getContainerIndex(const IntPoint& _point) 00542 { 00543 for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter) 00544 { 00545 if ((*iter)->isVisible()) 00546 { 00547 if ((*iter)->getAbsoluteRect().inside(_point)) 00548 { 00549 return getIndexByWidget(*iter); 00550 } 00551 } 00552 } 00553 return ITEM_NONE; 00554 } 00555 00556 void ItemBox::_resetContainer(bool _update) 00557 { 00558 // обязательно у базового 00559 Base::_resetContainer(_update); 00560 00561 if ( ! _update) 00562 { 00563 WidgetManager& instance = WidgetManager::getInstance(); 00564 for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter) 00565 { 00566 instance.unlinkFromUnlinkers(*iter); 00567 } 00568 } 00569 } 00570 00571 Widget* ItemBox::getWidgetByIndex(size_t _index) 00572 { 00573 for (VectorWidgetPtr::iterator iter=mVectorItems.begin(); iter!=mVectorItems.end(); ++iter) 00574 { 00575 if ((*iter)->isVisible()) 00576 { 00577 size_t index = getIndexByWidget(*iter); 00578 00579 if (index == _index) return (*iter); 00580 } 00581 } 00582 return nullptr; 00583 } 00584 00585 void ItemBox::onMouseButtonPressed(int _left, int _top, MouseButton _id) 00586 { 00587 Base::onMouseButtonPressed(_left, _top, _id); 00588 } 00589 00590 void ItemBox::onMouseButtonReleased(int _left, int _top, MouseButton _id) 00591 { 00592 Base::onMouseButtonReleased(_left, _top, _id); 00593 } 00594 00595 void ItemBox::onMouseDrag(int _left, int _top) 00596 { 00597 Base::onMouseDrag(_left, _top); 00598 } 00599 00600 void ItemBox::removeDropItems() 00601 { 00602 if (mItemDrag) mItemDrag->setVisible(false); 00603 } 00604 00605 void ItemBox::updateDropItems() 00606 { 00607 if (nullptr == mItemDrag) 00608 { 00609 // спрашиваем размер иконок 00610 IntCoord coord; 00611 00612 requestCoordItem(this, coord, true); 00613 00614 mPointDragOffset = coord.point(); 00615 00616 // создаем и запрашиваем детей 00617 mItemDrag = Gui::getInstance().createWidget<Widget>("Default", IntCoord(0, 0, coord.width, coord.height), Align::Default, mDragLayer); 00618 requestCreateWidgetItem(this, mItemDrag); 00619 } 00620 00621 const IntPoint& point = InputManager::getInstance().getMousePosition(); 00622 00623 mItemDrag->setPosition(point.left - mClickInWidget.left + mPointDragOffset.left, point.top - mClickInWidget.top + mPointDragOffset.top); 00624 mItemDrag->setVisible(true); 00625 } 00626 00627 void ItemBox::updateDropItemsState(const DDWidgetState& _state) 00628 { 00629 IBDrawItemInfo data; 00630 data.drop_accept = _state.accept; 00631 data.drop_refuse = _state.refuse; 00632 00633 data.select = false; 00634 data.active = false; 00635 00636 data.index = mDropSenderIndex; 00637 data.update = _state.update; 00638 data.drag = true; 00639 00640 requestDrawItem(this, mItemDrag, data); 00641 } 00642 00643 void ItemBox::notifyMouseDrag(Widget* _sender, int _left, int _top) 00644 { 00645 mouseDrag(); 00646 } 00647 00648 void ItemBox::notifyMouseButtonPressed(Widget* _sender, int _left, int _top, MouseButton _id) 00649 { 00650 mouseButtonPressed(_id); 00651 00652 if ( MouseButton::Left == _id) 00653 { 00654 size_t old = mIndexSelect; 00655 00656 if (_sender == _getClientWidget()) 00657 { 00658 // сбрасываем выделение 00659 setIndexSelected(ITEM_NONE); 00660 } 00661 else 00662 { 00663 // индекс отправителя 00664 mDropSenderIndex = getIndexByWidget(_sender); 00665 00666 // выделенный елемент 00667 setIndexSelected(mDropSenderIndex); 00668 } 00669 00670 // смещение внутри виджета, куда кликнули мышкой 00671 mClickInWidget = InputManager::getInstance().getLastLeftPressed() - _sender->getAbsolutePosition(); 00672 00673 // отсылаем событие 00674 eventMouseItemActivate(this, mIndexSelect); 00675 // смену позиции отсылаем только при реальном изменении 00676 if (old != mIndexSelect) eventChangeItemPosition(this, mIndexSelect); 00677 } 00678 00679 eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::MousePressed, _left, _top, _id)); 00680 } 00681 00682 void ItemBox::notifyMouseButtonReleased(Widget* _sender, int _left, int _top, MouseButton _id) 00683 { 00684 bool needEvent = !mStartDrop; 00685 mouseButtonReleased(_id); 00686 00687 if (needEvent) 00688 eventNotifyItem(this, IBNotifyItemData(getIndexByWidget(_sender), IBNotifyItemData::MouseReleased, _left, _top, _id)); 00689 } 00690 00691 void ItemBox::notifyRootMouseChangeFocus(Widget* _sender, bool _focus) 00692 { 00693 size_t index = calcIndexByWidget(_sender); 00694 if (_focus) 00695 { 00696 MYGUI_ASSERT_RANGE(index, mItemsInfo.size(), "ItemBox::notifyRootMouseChangeFocus"); 00697 00698 // сбрасываем старый 00699 if (mIndexActive != ITEM_NONE) 00700 { 00701 size_t old_index = mIndexActive; 00702 mIndexActive = ITEM_NONE; 00703 IBDrawItemInfo data(old_index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00704 requestDrawItem(this, mVectorItems[old_index - (mFirstVisibleIndex * mCountItemInLine)], data); 00705 } 00706 00707 mIndexActive = index; 00708 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00709 requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data); 00710 } 00711 else 00712 { 00713 // при сбросе виджет может быть уже скрыт, и соответсвенно отсутсвовать индекс 00714 // сбрасываем индекс, только если мы и есть актив 00715 if (index < mItemsInfo.size() && mIndexActive == index) 00716 { 00717 mIndexActive = ITEM_NONE; 00718 IBDrawItemInfo data(index, mIndexSelect, mIndexActive, mIndexAccept, mIndexRefuse, false, false); 00719 requestDrawItem(this, mVectorItems[*_sender->_getInternalData<size_t>()], data); 00720 } 00721 } 00722 } 00723 00724 void ItemBox::updateMetrics() 00725 { 00726 if (mAlignVert) 00727 { 00728 // колличество айтемов на одной строке 00729 mCountItemInLine = _getClientWidget()->getWidth() / mSizeItem.width; 00730 } 00731 else 00732 { 00733 // колличество айтемов на одной строке 00734 mCountItemInLine = _getClientWidget()->getHeight() / mSizeItem.height; 00735 } 00736 00737 if (1 > mCountItemInLine) mCountItemInLine = 1; 00738 00739 // колличество строк 00740 mCountLines = mItemsInfo.size() / mCountItemInLine; 00741 if (0 != (mItemsInfo.size() % mCountItemInLine)) mCountLines ++; 00742 00743 if (mAlignVert) 00744 { 00745 mContentSize.width = (mSizeItem.width * mCountItemInLine); 00746 mContentSize.height = (mSizeItem.height * mCountLines); 00747 } 00748 else 00749 { 00750 mContentSize.width = (mSizeItem.width * mCountLines); 00751 mContentSize.height = (mSizeItem.height * mCountItemInLine); 00752 } 00753 } 00754 00755 void ItemBox::notifyScrollChangePosition(VScroll* _sender, size_t _index) 00756 { 00757 if (_sender == mVScroll) 00758 { 00759 mContentPosition.top = (int)_index; 00760 } 00761 else if (_sender == mHScroll) 00762 { 00763 mContentPosition.left = (int)_index; 00764 } 00765 00766 setContentPosition(mContentPosition); 00767 } 00768 00769 void ItemBox::notifyMouseWheel(Widget* _sender, int _rel) 00770 { 00771 if (mAlignVert) 00772 { 00773 if (mContentSize.height <= 0) return; 00774 00775 int offset = mContentPosition.top; 00776 if (_rel < 0) offset += mSizeItem.height; 00777 else offset -= mSizeItem.height; 00778 00779 if (mContentSize.height <= _getClientWidget()->getHeight()) return; 00780 00781 if (offset >= mContentSize.height - _getClientWidget()->getHeight()) offset = mContentSize.height - _getClientWidget()->getHeight(); 00782 else if (offset < 0) offset = 0; 00783 00784 if (mContentPosition.top == offset) return; 00785 00786 // сбрасываем старую подсветку 00787 // так как при прокрутке, мышь может находиться над окном 00788 resetCurrentActiveItem(); 00789 00790 mContentPosition.top = offset; 00791 } 00792 else 00793 { 00794 if (mContentSize.width <= 0) return; 00795 00796 int offset = mContentPosition.left; 00797 if (_rel < 0) offset += mSizeItem.width; 00798 else offset -= mSizeItem.width; 00799 00800 if (mContentSize.width <= _getClientWidget()->getWidth()) return; 00801 00802 if (offset >= mContentSize.width - _getClientWidget()->getWidth()) offset = mContentSize.width - _getClientWidget()->getWidth(); 00803 else if (offset < 0) offset = 0; 00804 00805 if (mContentPosition.left == offset) return; 00806 00807 // сбрасываем старую подсветку 00808 // так как при прокрутке, мышь может находиться над окном 00809 resetCurrentActiveItem(); 00810 00811 mContentPosition.left = offset; 00812 } 00813 00814 setContentPosition(mContentPosition); 00815 00816 // заново ищем и подсвечиваем айтем 00817 if (!mNeedDrop) 00818 findCurrentActiveItem(); 00819 00820 if (nullptr != mVScroll) mVScroll->setScrollPosition(mContentPosition.top); 00821 if (nullptr != mHScroll) mHScroll->setScrollPosition(mContentPosition.left); 00822 } 00823 00824 void ItemBox::setContentPosition(const IntPoint& _point) 00825 { 00826 mContentPosition = _point; 00827 00828 int old = mFirstVisibleIndex; 00829 00830 if (mAlignVert) 00831 { 00832 mFirstVisibleIndex = mContentPosition.top / mSizeItem.height; 00833 mFirstOffsetIndex = mContentPosition.top % mSizeItem.height; 00834 } 00835 else 00836 { 00837 mFirstVisibleIndex = mContentPosition.left / mSizeItem.width; 00838 mFirstOffsetIndex = mContentPosition.left % mSizeItem.width; 00839 } 00840 00841 _updateAllVisible(old != mFirstVisibleIndex); 00842 _resetContainer(true); 00843 } 00844 00845 void ItemBox::redrawAllItems() 00846 { 00847 _updateAllVisible(true); 00848 } 00849 00850 void ItemBox::resetDrag() 00851 { 00852 endDrop(true); 00853 } 00854 00855 size_t ItemBox::calcIndexByWidget(Widget* _widget) 00856 { 00857 return *_widget->_getInternalData<size_t>() + (mFirstVisibleIndex * mCountItemInLine); 00858 } 00859 00860 IntSize ItemBox::getContentSize() 00861 { 00862 return mContentSize; 00863 } 00864 00865 IntPoint ItemBox::getContentPosition() 00866 { 00867 return mContentPosition; 00868 } 00869 00870 IntSize ItemBox::getViewSize() const 00871 { 00872 return _getClientWidget()->getSize(); 00873 } 00874 00875 void ItemBox::eraseContent() 00876 { 00877 updateMetrics(); 00878 } 00879 00880 size_t ItemBox::getHScrollPage() 00881 { 00882 return mSizeItem.width; 00883 } 00884 00885 size_t ItemBox::getVScrollPage() 00886 { 00887 return mSizeItem.height; 00888 } 00889 00890 Align ItemBox::getContentAlign() 00891 { 00892 return Align::Default; 00893 } 00894 00895 IntRect ItemBox::_getClientAbsoluteRect() 00896 { 00897 return _getClientWidget()->getAbsoluteRect(); 00898 } 00899 00900 Widget* ItemBox::_getClientWidget() 00901 { 00902 return mWidgetClient == nullptr ? this : mWidgetClient; 00903 } 00904 00905 const Widget* ItemBox::_getClientWidget() const 00906 { 00907 return mWidgetClient == nullptr ? this : mWidgetClient; 00908 } 00909 00910 } // namespace MyGUI