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_MultiListBox.h" 00009 #include "MyGUI_MultiListItem.h" 00010 #include "MyGUI_ResourceSkin.h" 00011 #include "MyGUI_Button.h" 00012 #include "MyGUI_ImageBox.h" 00013 #include "MyGUI_ListBox.h" 00014 #include "MyGUI_Gui.h" 00015 #include "MyGUI_WidgetManager.h" 00016 00017 namespace MyGUI 00018 { 00019 00020 MultiListBox::MultiListBox() : 00021 mHeightButton(0), 00022 mWidthBar(0), 00023 mWidgetEmpty(nullptr), 00024 mLastMouseFocusIndex(ITEM_NONE), 00025 mSortUp(true), 00026 mSortColumnIndex(ITEM_NONE), 00027 mWidthSeparator(0), 00028 mItemSelected(ITEM_NONE), 00029 mFrameAdvise(false), 00030 mClient(nullptr), 00031 mHeaderPlace(nullptr) 00032 { 00033 } 00034 00035 void MultiListBox::initialiseOverride() 00036 { 00037 Base::initialiseOverride(); 00038 00039 std::string skinButtonEmpty; 00040 00041 if (isUserString("SkinButton")) 00042 mSkinButton = getUserString("SkinButton"); 00043 00044 if (isUserString("SkinList")) 00045 mSkinList = getUserString("SkinList"); 00046 00047 if (isUserString("SkinSeparator")) 00048 mSkinSeparator = getUserString("SkinSeparator"); 00049 00050 if (isUserString("WidthSeparator")) 00051 mWidthSeparator = utility::parseValue<int>(getUserString("WidthSeparator")); 00052 00053 // OBSOLETE 00054 if (isUserString("HeightButton")) 00055 mHeightButton = utility::parseValue<int>(getUserString("HeightButton")); 00056 if (mHeightButton < 0) 00057 mHeightButton = 0; 00058 00060 assignWidget(mHeaderPlace, "HeaderPlace"); 00061 00063 assignWidget(mClient, "Client"); 00064 if (mClient != nullptr) 00065 setWidgetClient(mClient); 00066 00067 if (nullptr == mClient) 00068 mClient = this; 00069 00071 assignWidget(mWidgetEmpty, "Empty"); 00072 00073 if (mWidgetEmpty == nullptr) 00074 { 00075 if (isUserString("SkinButtonEmpty")) 00076 skinButtonEmpty = getUserString("SkinButtonEmpty"); 00077 00078 if (!skinButtonEmpty.empty()) 00079 mWidgetEmpty = mClient->createWidget<Widget>(skinButtonEmpty, IntCoord(0, 0, mClient->getWidth(), getButtonHeight()), Align::Default); 00080 } 00081 00082 if (getUpdateByResize()) 00083 updateColumns(); 00084 } 00085 00086 void MultiListBox::shutdownOverride() 00087 { 00088 mClient = nullptr; 00089 00090 Base::shutdownOverride(); 00091 } 00092 00093 void MultiListBox::setColumnNameAt(size_t _column, const UString& _name) 00094 { 00095 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::setColumnNameAt"); 00096 mVectorColumnInfo[_column].name = _name; 00097 // обновляем кэпшен сначала 00098 redrawButtons(); 00099 updateColumns(); 00100 } 00101 00102 void MultiListBox::setColumnWidthAt(size_t _column, int _width) 00103 { 00104 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::setColumnWidthAt"); 00105 mVectorColumnInfo[_column].width = _width; 00106 updateColumns(); 00107 } 00108 00109 const UString& MultiListBox::getColumnNameAt(size_t _column) 00110 { 00111 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnNameAt"); 00112 return mVectorColumnInfo[_column].name; 00113 } 00114 00115 int MultiListBox::getColumnWidthAt(size_t _column) 00116 { 00117 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getColumnWidthAt"); 00118 return mVectorColumnInfo[_column].width; 00119 } 00120 00121 void MultiListBox::removeAllColumns() 00122 { 00123 while (!mVectorColumnInfo.empty()) 00124 removeColumnAt(0); 00125 } 00126 00127 void MultiListBox::sortByColumn(size_t _column, bool _backward) 00128 { 00129 mSortColumnIndex = _column; 00130 if (_backward) 00131 { 00132 mSortUp = !mSortUp; 00133 redrawButtons(); 00134 // если было недосортированно то сортируем 00135 if (mFrameAdvise) 00136 sortList(); 00137 00138 flipList(); 00139 } 00140 else 00141 { 00142 mSortUp = true; 00143 redrawButtons(); 00144 sortList(); 00145 } 00146 } 00147 00148 size_t MultiListBox::getItemCount() const 00149 { 00150 if (mVectorColumnInfo.empty()) 00151 return 0; 00152 return mVectorColumnInfo.front().list->getItemCount(); 00153 } 00154 00155 void MultiListBox::removeAllItems() 00156 { 00157 BiIndexBase::removeAllItems(); 00158 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00159 { 00160 (*iter).list->removeAllItems(); 00161 } 00162 00163 mItemSelected = ITEM_NONE; 00164 } 00165 00166 void MultiListBox::updateBackSelected(size_t _index) 00167 { 00168 if (_index == ITEM_NONE) 00169 { 00170 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00171 { 00172 (*iter).list->clearIndexSelected(); 00173 } 00174 } 00175 else 00176 { 00177 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00178 { 00179 (*iter).list->setIndexSelected(_index); 00180 } 00181 } 00182 } 00183 00184 void MultiListBox::setIndexSelected(size_t _index) 00185 { 00186 if (_index == mItemSelected) 00187 return; 00188 00189 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::setIndexSelected"); 00190 MYGUI_ASSERT_RANGE_AND_NONE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::setIndexSelected"); 00191 00192 mItemSelected = _index; 00193 updateBackSelected(BiIndexBase::convertToBack(mItemSelected)); 00194 } 00195 00196 void MultiListBox::setSubItemNameAt(size_t _column, size_t _index, const UString& _name) 00197 { 00198 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::setSubItemAt"); 00199 00200 size_t index = BiIndexBase::convertToBack(_index); 00201 getSubItemAt(_column)->setItemNameAt(index, _name); 00202 00203 // если мы попортили список с активным сортом, надо пересчитывать 00204 if (_column == mSortColumnIndex) 00205 frameAdvise(true); 00206 } 00207 00208 const UString& MultiListBox::getSubItemNameAt(size_t _column, size_t _index) 00209 { 00210 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::getSubItemNameAt"); 00211 00212 size_t index = BiIndexBase::convertToBack(_index); 00213 return getSubItemAt(_column)->getItemNameAt(index); 00214 } 00215 00216 size_t MultiListBox::findSubItemWith(size_t _column, const UString& _name) 00217 { 00218 size_t index = getSubItemAt(_column)->findItemIndexWith(_name); 00219 return BiIndexBase::convertToFace(index); 00220 } 00221 00222 int MultiListBox::getButtonHeight() const 00223 { 00224 if (mHeaderPlace != nullptr) 00225 return mHeaderPlace->getHeight(); 00226 return mHeightButton; 00227 } 00228 00229 void MultiListBox::updateOnlyEmpty() 00230 { 00231 if (nullptr == mWidgetEmpty) 00232 return; 00233 00234 // кнопка, для заполнения пустоты 00235 if (mWidthBar >= mClient->getWidth()) 00236 mWidgetEmpty->setVisible(false); 00237 else 00238 { 00239 mWidgetEmpty->setCoord(mWidthBar, 0, mClient->getWidth() - mWidthBar, getButtonHeight()); 00240 mWidgetEmpty->setVisible(true); 00241 } 00242 } 00243 00244 void MultiListBox::notifyListChangePosition(ListBox* _sender, size_t _position) 00245 { 00246 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00247 { 00248 if (_sender != (*iter).list) 00249 (*iter).list->setIndexSelected(_position); 00250 } 00251 00252 updateBackSelected(_position); 00253 00254 mItemSelected = BiIndexBase::convertToFace(_position); 00255 00256 // наш евент 00257 eventListChangePosition(this, mItemSelected); 00258 } 00259 00260 void MultiListBox::notifyListSelectAccept(ListBox* _sender, size_t _position) 00261 { 00262 // наш евент 00263 eventListSelectAccept(this, BiIndexBase::convertToFace(_position)); 00264 } 00265 00266 void MultiListBox::notifyListChangeFocus(ListBox* _sender, size_t _position) 00267 { 00268 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00269 { 00270 if (_sender != (*iter).list) 00271 { 00272 if (ITEM_NONE != mLastMouseFocusIndex) 00273 (*iter).list->_setItemFocus(mLastMouseFocusIndex, false); 00274 if (ITEM_NONE != _position) 00275 (*iter).list->_setItemFocus(_position, true); 00276 } 00277 } 00278 mLastMouseFocusIndex = _position; 00279 } 00280 00281 void MultiListBox::notifyListChangeScrollPosition(ListBox* _sender, size_t _position) 00282 { 00283 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00284 { 00285 if (_sender != (*iter).list) 00286 (*iter).list->setScrollPosition(_position); 00287 } 00288 } 00289 00290 void MultiListBox::notifyButtonClick(MyGUI::Widget* _sender) 00291 { 00292 size_t index = *_sender->_getInternalData<size_t>(); 00293 sortByColumn(index, index == mSortColumnIndex); 00294 } 00295 00296 void MultiListBox::redrawButtons() 00297 { 00298 size_t pos = 0; 00299 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00300 { 00301 if (pos == mSortColumnIndex) 00302 { 00303 if (mSortUp) 00304 (*iter).button->setImageName("Up"); 00305 else 00306 (*iter).button->setImageName("Down"); 00307 } 00308 else 00309 (*iter).button->setImageName("None"); 00310 00311 (*iter).button->setCaption((*iter).name); 00312 pos++; 00313 } 00314 } 00315 00316 void MultiListBox::frameEntered(float _frame) 00317 { 00318 sortList(); 00319 } 00320 00321 void MultiListBox::frameAdvise(bool _advise) 00322 { 00323 if (_advise) 00324 { 00325 if (!mFrameAdvise) 00326 { 00327 MyGUI::Gui::getInstance().eventFrameStart += MyGUI::newDelegate( this, &MultiListBox::frameEntered ); 00328 mFrameAdvise = true; 00329 } 00330 } 00331 else 00332 { 00333 if (mFrameAdvise) 00334 { 00335 MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate( this, &MultiListBox::frameEntered ); 00336 mFrameAdvise = false; 00337 } 00338 } 00339 } 00340 00341 Widget* MultiListBox::getSeparator(size_t _index) 00342 { 00343 if (!mWidthSeparator || mSkinSeparator.empty()) 00344 return nullptr; 00345 // последний столбик 00346 if (_index == mVectorColumnInfo.size() - 1) 00347 return nullptr; 00348 00349 while (_index >= mSeparators.size()) 00350 { 00351 Widget* separator = mClient->createWidget<Widget>(mSkinSeparator, IntCoord(), Align::Default); 00352 mSeparators.push_back(separator); 00353 } 00354 00355 return mSeparators[_index]; 00356 } 00357 00358 void MultiListBox::flipList() 00359 { 00360 if (ITEM_NONE == mSortColumnIndex) 00361 return; 00362 00363 size_t last = mVectorColumnInfo.front().list->getItemCount(); 00364 if (0 == last) 00365 return; 00366 last --; 00367 size_t first = 0; 00368 00369 while (first < last) 00370 { 00371 BiIndexBase::swapItemsBackAt(first, last); 00372 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00373 { 00374 (*iter).list->swapItemsAt(first, last); 00375 } 00376 00377 first++; 00378 last--; 00379 } 00380 00381 updateBackSelected(BiIndexBase::convertToBack(mItemSelected)); 00382 } 00383 00384 bool MultiListBox::compare(ListBox* _list, size_t _left, size_t _right) 00385 { 00386 bool result = false; 00387 if (mSortUp) 00388 std::swap(_left, _right); 00389 if (requestOperatorLess.empty()) 00390 result = _list->getItemNameAt(_left) < _list->getItemNameAt(_right); 00391 else 00392 requestOperatorLess(this, mSortColumnIndex, _list->getItemNameAt(_left), _list->getItemNameAt(_right), result); 00393 return result; 00394 } 00395 00396 void MultiListBox::sortList() 00397 { 00398 if (ITEM_NONE == mSortColumnIndex) 00399 return; 00400 00401 ListBox* list = mVectorColumnInfo[mSortColumnIndex].list; 00402 00403 size_t count = list->getItemCount(); 00404 if (0 == count) 00405 return; 00406 00407 // shell sort 00408 int first; 00409 size_t last; 00410 for (size_t step = count >> 1; step > 0 ; step >>= 1) 00411 { 00412 for (size_t i = 0; i < (count - step); i++) 00413 { 00414 first = (int)i; 00415 while (first >= 0) 00416 { 00417 last = first + step; 00418 if (compare(list, first, last)) 00419 { 00420 BiIndexBase::swapItemsBackAt(first, last); 00421 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00422 { 00423 (*iter).list->swapItemsAt(first, last); 00424 } 00425 } 00426 first--; 00427 } 00428 } 00429 } 00430 00431 frameAdvise(false); 00432 00433 updateBackSelected(BiIndexBase::convertToBack(mItemSelected)); 00434 } 00435 00436 void MultiListBox::insertItemAt(size_t _index, const UString& _name, Any _data) 00437 { 00438 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::insertItemAt"); 00439 MYGUI_ASSERT_RANGE_INSERT(_index, mVectorColumnInfo.front().list->getItemCount(), "MultiListBox::insertItemAt"); 00440 if (ITEM_NONE == _index) 00441 _index = mVectorColumnInfo.front().list->getItemCount(); 00442 00443 // если надо, то меняем выделенный элемент 00444 // при сортировке, обновится 00445 if ((mItemSelected != ITEM_NONE) && (_index <= mItemSelected)) 00446 mItemSelected ++; 00447 00448 size_t index = BiIndexBase::insertItemAt(_index); 00449 00450 // вставляем во все поля пустые, а потом присваиваем первому 00451 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00452 { 00453 (*iter).list->insertItemAt(index, ""); 00454 } 00455 mVectorColumnInfo.front().list->setItemNameAt(index, _name); 00456 mVectorColumnInfo.front().list->setItemDataAt(index, _data); 00457 00458 frameAdvise(true); 00459 } 00460 00461 void MultiListBox::removeItemAt(size_t _index) 00462 { 00463 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::removeItemAt"); 00464 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::removeItemAt"); 00465 00466 size_t index = BiIndexBase::removeItemAt(_index); 00467 00468 for (VectorColumnInfo::iterator iter = mVectorColumnInfo.begin(); iter != mVectorColumnInfo.end(); ++iter) 00469 { 00470 (*iter).list->removeItemAt(index); 00471 } 00472 00473 // если надо, то меняем выделенный элемент 00474 size_t count = mVectorColumnInfo.begin()->list->getItemCount(); 00475 if (count == 0) 00476 mItemSelected = ITEM_NONE; 00477 else if (mItemSelected != ITEM_NONE) 00478 { 00479 if (_index < mItemSelected) 00480 mItemSelected --; 00481 else if ((_index == mItemSelected) && (mItemSelected == count)) 00482 mItemSelected --; 00483 } 00484 updateBackSelected(BiIndexBase::convertToBack(mItemSelected)); 00485 } 00486 00487 void MultiListBox::swapItemsAt(size_t _index1, size_t _index2) 00488 { 00489 MYGUI_ASSERT(!mVectorColumnInfo.empty(), "MultiListBox::removeItemAt"); 00490 MYGUI_ASSERT_RANGE(_index1, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::swapItemsAt"); 00491 MYGUI_ASSERT_RANGE(_index2, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::swapItemsAt"); 00492 00493 // при сортированном, меняем только индексы 00494 BiIndexBase::swapItemsFaceAt(_index1, _index2); 00495 00496 // при несортированном, нужно наоборот, поменять только данные 00497 // FIXME 00498 } 00499 00500 void MultiListBox::setColumnDataAt(size_t _index, Any _data) 00501 { 00502 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::setColumnDataAt"); 00503 mVectorColumnInfo[_index].data = _data; 00504 } 00505 00506 void MultiListBox::setSubItemDataAt(size_t _column, size_t _index, Any _data) 00507 { 00508 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.begin()->list->getItemCount(), "MultiListBox::setSubItemDataAt"); 00509 00510 size_t index = BiIndexBase::convertToBack(_index); 00511 getSubItemAt(_column)->setItemDataAt(index, _data); 00512 } 00513 00514 size_t MultiListBox::getColumnCount() const 00515 { 00516 return mVectorColumnInfo.size(); 00517 } 00518 00519 void MultiListBox::addColumn(const UString& _name, int _width, Any _data) 00520 { 00521 insertColumnAt(ITEM_NONE, _name, _width, _data); 00522 } 00523 00524 void MultiListBox::clearColumnDataAt(size_t _index) 00525 { 00526 setColumnDataAt(_index, Any::Null); 00527 } 00528 00529 void MultiListBox::addItem(const UString& _name, Any _data) 00530 { 00531 insertItemAt(ITEM_NONE, _name, _data); 00532 } 00533 00534 void MultiListBox::setItemNameAt(size_t _index, const UString& _name) 00535 { 00536 setSubItemNameAt(0, _index, _name); 00537 } 00538 00539 const UString& MultiListBox::getItemNameAt(size_t _index) 00540 { 00541 return getSubItemNameAt(0, _index); 00542 } 00543 00544 size_t MultiListBox::getIndexSelected() const 00545 { 00546 return mItemSelected; 00547 } 00548 00549 void MultiListBox::clearIndexSelected() 00550 { 00551 setIndexSelected(ITEM_NONE); 00552 } 00553 00554 void MultiListBox::setItemDataAt(size_t _index, Any _data) 00555 { 00556 setSubItemDataAt(0, _index, _data); 00557 } 00558 00559 void MultiListBox::clearItemDataAt(size_t _index) 00560 { 00561 setItemDataAt(_index, Any::Null); 00562 } 00563 00564 void MultiListBox::clearSubItemDataAt(size_t _column, size_t _index) 00565 { 00566 setSubItemDataAt(_column, _index, Any::Null); 00567 } 00568 00569 ListBox* MultiListBox::getSubItemAt(size_t _column) 00570 { 00571 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::getSubItemAt"); 00572 return mVectorColumnInfo[_column].list; 00573 } 00574 00575 size_t MultiListBox::_getItemCount() 00576 { 00577 return getColumnCount(); 00578 } 00579 00580 void MultiListBox::_addItem(const MyGUI::UString& _name) 00581 { 00582 addColumn(_name); 00583 setColumnResizingPolicyAt(getColumnCount() - 1, ResizingPolicy::Auto); 00584 } 00585 00586 void MultiListBox::_removeItemAt(size_t _index) 00587 { 00588 removeColumnAt(_index); 00589 } 00590 00591 void MultiListBox::_setItemNameAt(size_t _index, const UString& _name) 00592 { 00593 setColumnNameAt(_index, _name); 00594 } 00595 00596 const UString& MultiListBox::_getItemNameAt(size_t _index) 00597 { 00598 return getColumnNameAt(_index); 00599 } 00600 00601 void MultiListBox::insertColumnAt(size_t _column, const UString& _name, int _width, Any _data) 00602 { 00603 MYGUI_ASSERT_RANGE_INSERT(_column, mVectorColumnInfo.size(), "MultiListBox::insertColumnAt"); 00604 if (_column == ITEM_NONE) 00605 _column = mVectorColumnInfo.size(); 00606 00607 createWidget<MultiListItem>("", IntCoord(), Align::Default); 00608 00609 mVectorColumnInfo.back().width = _width; 00610 mVectorColumnInfo.back().sizeType = ResizingPolicy::Fixed; 00611 mVectorColumnInfo.back().name = _name; 00612 mVectorColumnInfo.back().data = _data; 00613 mVectorColumnInfo.back().button->setCaption(_name); 00614 00615 if (_column == (mVectorColumnInfo.size() - 1)) 00616 { 00617 updateColumns(); 00618 00619 mVectorColumnInfo.back().list->setScrollVisible(true); 00620 } 00621 else 00622 { 00623 _swapColumnsAt(_column, mVectorColumnInfo.size() - 1); 00624 } 00625 } 00626 00627 void MultiListBox::removeColumnAt(size_t _column) 00628 { 00629 MYGUI_ASSERT_RANGE(_column, mVectorColumnInfo.size(), "MultiListBox::removeColumnAt"); 00630 00631 ColumnInfo& info = mVectorColumnInfo[_column]; 00632 00633 WidgetManager::getInstance().destroyWidget(info.item); 00634 } 00635 00636 void MultiListBox::swapColumnsAt(size_t _index1, size_t _index2) 00637 { 00638 MYGUI_ASSERT_RANGE(_index1, mVectorColumnInfo.size(), "MultiListBox::swapColumnsAt"); 00639 MYGUI_ASSERT_RANGE(_index2, mVectorColumnInfo.size(), "MultiListBox::swapColumnsAt"); 00640 00641 _swapColumnsAt(_index1, _index2); 00642 } 00643 00644 void MultiListBox::_swapColumnsAt(size_t _index1, size_t _index2) 00645 { 00646 if (_index1 == _index2) 00647 return; 00648 00649 mVectorColumnInfo[_index1].list->setScrollVisible(false); 00650 mVectorColumnInfo[_index2].list->setScrollVisible(false); 00651 00652 std::swap(mVectorColumnInfo[_index1], mVectorColumnInfo[_index2]); 00653 00654 updateColumns(); 00655 00656 mVectorColumnInfo.back().list->setScrollVisible(true); 00657 } 00658 00659 void MultiListBox::onWidgetCreated(Widget* _widget) 00660 { 00661 Base::onWidgetCreated(_widget); 00662 00663 MultiListItem* child = _widget->castType<MultiListItem>(false); 00664 if (child != nullptr) 00665 { 00666 _wrapItem(child); 00667 } 00668 } 00669 00670 void MultiListBox::onWidgetDestroy(Widget* _widget) 00671 { 00672 Base::onWidgetDestroy(_widget); 00673 00674 MultiListItem* child = _widget->castType<MultiListItem>(false); 00675 if (child != nullptr) 00676 { 00677 _unwrapItem(child); 00678 } 00679 else 00680 { 00681 for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item) 00682 { 00683 if ((*item).button == _widget) 00684 (*item).button = nullptr; 00685 } 00686 } 00687 } 00688 00689 void MultiListBox::_wrapItem(MultiListItem* _item) 00690 { 00691 // скрываем у крайнего скролл 00692 if (!mVectorColumnInfo.empty()) 00693 mVectorColumnInfo.back().list->setScrollVisible(false); 00694 else 00695 mSortColumnIndex = ITEM_NONE; 00696 00697 ColumnInfo column; 00698 column.width = 0; 00699 column.sizeType = ResizingPolicy::Auto; 00700 00701 column.item = _item; 00702 column.list = _item->createWidget<ListBox>(mSkinList, IntCoord(0, 0, _item->getWidth(), _item->getHeight()), Align::Stretch); 00703 column.list->eventListChangePosition += newDelegate(this, &MultiListBox::notifyListChangePosition); 00704 column.list->eventListMouseItemFocus += newDelegate(this, &MultiListBox::notifyListChangeFocus); 00705 column.list->eventListChangeScroll += newDelegate(this, &MultiListBox::notifyListChangeScrollPosition); 00706 column.list->eventListSelectAccept += newDelegate(this, &MultiListBox::notifyListSelectAccept); 00707 00708 if (mHeaderPlace != nullptr) 00709 column.button = mHeaderPlace->createWidget<Button>(mSkinButton, IntCoord(), Align::Default); 00710 else 00711 column.button = mClient->createWidget<Button>(mSkinButton, IntCoord(), Align::Default); 00712 00713 column.button->eventMouseButtonClick += newDelegate(this, &MultiListBox::notifyButtonClick); 00714 00715 // если уже были столбики, то делаем то же колличество полей 00716 if (!mVectorColumnInfo.empty()) 00717 { 00718 size_t count = mVectorColumnInfo.front().list->getItemCount(); 00719 for (size_t pos = 0; pos < count; ++pos) 00720 column.list->addItem(""); 00721 } 00722 00723 mVectorColumnInfo.push_back(column); 00724 00725 updateColumns(); 00726 00727 // показываем скролл нового крайнего 00728 mVectorColumnInfo.back().list->setScrollVisible(true); 00729 } 00730 00731 void MultiListBox::_unwrapItem(MultiListItem* _item) 00732 { 00733 for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item) 00734 { 00735 if ((*item).item == _item) 00736 { 00737 if ((*item).button != nullptr) 00738 WidgetManager::getInstance().destroyWidget((*item).button); 00739 00740 mVectorColumnInfo.erase(item); 00741 break; 00742 } 00743 } 00744 00745 if (mVectorColumnInfo.empty()) 00746 { 00747 mSortColumnIndex = ITEM_NONE; 00748 mItemSelected = ITEM_NONE; 00749 } 00750 else 00751 { 00752 mSortColumnIndex = ITEM_NONE; 00753 mSortUp = true; 00754 sortList(); 00755 } 00756 00757 updateColumns(); 00758 00759 if (!mVectorColumnInfo.empty()) 00760 mVectorColumnInfo.back().list->setScrollVisible(true); 00761 } 00762 00763 Widget* MultiListBox::_getItemAt(size_t _index) 00764 { 00765 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::_getItemAt"); 00766 return mVectorColumnInfo[_index].item; 00767 } 00768 00769 void MultiListBox::setColumnName(MultiListItem* _item, const UString& _name) 00770 { 00771 setColumnNameAt(getColumnIndex(_item), _name); 00772 } 00773 00774 const UString& MultiListBox::getColumnName(MultiListItem* _item) 00775 { 00776 return getColumnNameAt(getColumnIndex(_item)); 00777 } 00778 00779 size_t MultiListBox::getColumnIndex(MultiListItem* _item) 00780 { 00781 for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index) 00782 { 00783 if (mVectorColumnInfo[index].item == _item) 00784 return index; 00785 } 00786 00787 return ITEM_NONE; 00788 } 00789 00790 void MultiListBox::setColumnResizingPolicy(MultiListItem* _item, ResizingPolicy _value) 00791 { 00792 setColumnResizingPolicyAt(getColumnIndex(_item), _value); 00793 } 00794 00795 void MultiListBox::setColumnResizingPolicyAt(size_t _index, ResizingPolicy _value) 00796 { 00797 MYGUI_ASSERT_RANGE(_index, mVectorColumnInfo.size(), "MultiListBox::setColumnWidthAt"); 00798 mVectorColumnInfo[_index].sizeType = _value; 00799 updateColumns(); 00800 } 00801 00802 void MultiListBox::setColumnWidth(MultiListItem* _item, int _width) 00803 { 00804 setColumnWidthAt(getColumnIndex(_item), _width); 00805 } 00806 00807 void MultiListBox::setPosition(const IntPoint& _point) 00808 { 00809 Base::setPosition(_point); 00810 } 00811 00812 void MultiListBox::setSize(const IntSize& _size) 00813 { 00814 Base::setSize(_size); 00815 00816 if (getUpdateByResize()) 00817 updateColumns(); 00818 } 00819 00820 void MultiListBox::setCoord(const IntCoord& _coord) 00821 { 00822 Base::setCoord(_coord); 00823 00824 if (getUpdateByResize()) 00825 updateColumns(); 00826 } 00827 00828 void MultiListBox::setPosition(int _left, int _top) 00829 { 00830 setPosition(IntPoint(_left, _top)); 00831 } 00832 00833 void MultiListBox::setSize(int _width, int _height) 00834 { 00835 setSize(IntSize(_width, _height)); 00836 } 00837 00838 void MultiListBox::setCoord(int _left, int _top, int _width, int _height) 00839 { 00840 setCoord(IntCoord(_left, _top, _width, _height)); 00841 } 00842 00843 bool MultiListBox::getUpdateByResize() 00844 { 00845 if (mWidgetEmpty != nullptr) 00846 return true; 00847 00848 for (VectorColumnInfo::iterator item = mVectorColumnInfo.begin(); item != mVectorColumnInfo.end(); ++item) 00849 { 00850 if ((*item).sizeType == ResizingPolicy::Fill) 00851 return true; 00852 } 00853 return false; 00854 } 00855 00856 int MultiListBox::getColumnWidth(size_t _index, int _freeSpace, size_t _countStars, size_t _lastIndexStar, int _starWidth) const 00857 { 00858 const ColumnInfo& info = mVectorColumnInfo[_index]; 00859 00860 if (info.sizeType == ResizingPolicy::Auto) 00861 { 00862 return info.realWidth; 00863 } 00864 else if (info.sizeType == ResizingPolicy::Fixed) 00865 { 00866 return info.realWidth; 00867 } 00868 else if (info.sizeType == ResizingPolicy::Fill) 00869 { 00870 if (_lastIndexStar == _index) 00871 { 00872 return _starWidth + _freeSpace - (_starWidth * _countStars); 00873 } 00874 else 00875 { 00876 return _starWidth; 00877 } 00878 } 00879 return 0; 00880 } 00881 00882 int MultiListBox::updateWidthColumns(size_t& _countStars, size_t& _lastIndexStar) 00883 { 00884 _countStars = 0; 00885 _lastIndexStar = ITEM_NONE; 00886 00887 int width = 0; 00888 00889 for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index) 00890 { 00891 ColumnInfo& info = mVectorColumnInfo[index]; 00892 00893 if (info.sizeType == ResizingPolicy::Auto) 00894 { 00895 info.realWidth = info.button->getWidth() - info.button->getTextRegion().width + info.button->getTextSize().width; 00896 } 00897 else if (info.sizeType == ResizingPolicy::Fixed) 00898 { 00899 info.realWidth = info.width < 0 ? 0 : info.width; 00900 } 00901 else if (info.sizeType == ResizingPolicy::Fill) 00902 { 00903 info.realWidth = 0; 00904 _countStars ++; 00905 _lastIndexStar = index; 00906 } 00907 else 00908 { 00909 info.realWidth = 0; 00910 } 00911 00912 width += info.realWidth; 00913 } 00914 00915 return width; 00916 } 00917 00918 void MultiListBox::updateColumns() 00919 { 00920 size_t countStars = 0; 00921 size_t lastIndexStar = ITEM_NONE; 00922 00923 int allColumnsWidth = updateWidthColumns(countStars, lastIndexStar); 00924 int clientWidth = mClient->getWidth(); 00925 int separatorsWidth = mVectorColumnInfo.empty() ? 0 : (mVectorColumnInfo.size() - 1) * mWidthSeparator; 00926 int freeSpace = clientWidth - separatorsWidth - allColumnsWidth; 00927 int starWidth = (countStars != 0 && freeSpace > 0) ? (freeSpace / countStars) : 0; 00928 00929 mWidthBar = 0; 00930 for (size_t index = 0; index < mVectorColumnInfo.size(); ++ index) 00931 { 00932 ColumnInfo& info = mVectorColumnInfo[index]; 00933 00934 int columnWidth = getColumnWidth(index, freeSpace, countStars, lastIndexStar, starWidth); 00935 00936 if (mHeaderPlace != nullptr) 00937 { 00938 info.item->setCoord(mWidthBar, 0, columnWidth, mClient->getHeight()); 00939 } 00940 else 00941 { 00942 info.item->setCoord(mWidthBar, mHeightButton, columnWidth, mClient->getHeight() - mHeightButton); 00943 } 00944 00945 info.button->setCoord(mWidthBar, 0, columnWidth, getButtonHeight()); 00946 info.button->_setInternalData(index); 00947 00948 mWidthBar += columnWidth; 00949 00950 // промежуток между листами 00951 Widget* separator = getSeparator(index); 00952 if (separator) 00953 { 00954 separator->setCoord(mWidthBar, 0, mWidthSeparator, mClient->getHeight()); 00955 } 00956 00957 mWidthBar += mWidthSeparator; 00958 } 00959 00960 redrawButtons(); 00961 updateOnlyEmpty(); 00962 } 00963 00964 } // namespace MyGUI