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