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