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