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