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