MyGUI  3.2.0
MyGUI_MultiListBox.cpp
Go to the documentation of this file.
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