MezzanineEngine March 18, 2012

uilistbox.cpp

00001 //© Copyright 2010 - 2011 BlackTopp Studios Inc.
00002 /* This file is part of The Mezzanine Engine.
00003 
00004     The Mezzanine Engine is free software: you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation, either version 3 of the License, or
00007     (at your option) any later version.
00008 
00009     The Mezzanine Engine is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with The Mezzanine Engine.  If not, see <http://www.gnu.org/licenses/>.
00016 */
00017 /* The original authors have included a copy of the license specified above in the
00018    'Docs' folder. See 'gpl.txt'
00019 */
00020 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
00021    Build professional software and charge for their product.
00022 
00023    However there are some practical restrictions, so if your project involves
00024    any of the following you should contact us and we will try to work something
00025    out:
00026     - DRM or Copy Protection of any kind(except Copyrights)
00027     - Software Patents You Do Not Wish to Freely License
00028     - Any Kind of Linking to Non-GPL licensed Works
00029     - Are Currently In Violation of Another Copyright Holder's GPL License
00030     - If You want to change our code and not add a few hundred MB of stuff to
00031         your distribution
00032 
00033    These and other limitations could cause serious legal problems if you ignore
00034    them, so it is best to simply contact us or the Free Software Foundation, if
00035    you have any questions.
00036 
00037    Joseph Toppi - toppij@gmail.com
00038    John Blackwood - makoenergy02@gmail.com
00039 */
00040 #ifndef _uilistbox_cpp
00041 #define _uilistbox_cpp
00042 
00043 #include "uilistbox.h"
00044 #include "uimanager.h"
00045 #include "uilayer.h"
00046 #include "uiscreen.h"
00047 #include "uicaption.h"
00048 #include "uirectangle.h"
00049 #include "uiscrollbar.h"
00050 #include "uiviewportupdatetool.h"
00051 #include "inputquerytool.h"
00052 #include "metacode.h"
00053 #include "world.h"
00054 
00055 #include <cmath>
00056 
00057 namespace Mezzanine
00058 {
00059     namespace UI
00060     {
00061         ListBox::ListBox(ConstString& name, const RenderableRect& Rect, const UI::ScrollbarStyle& ScrollStyle, Layer* PLayer)
00062             : Widget(name,PLayer),
00063               Selected(NULL),
00064               AutoHideScroll(true),
00065               LastScrollValue(0),
00066               MaxDisplay(3),
00067               SelectionsAdded(1)
00068         {
00069             /// @todo Currently this class has little support for a border around the selections.
00070             /// Ideally when the UI system is more complete we'll be able to seemlessly move
00071             /// objects around different layers and thus have more control over z-order.  When
00072             /// that happens we should add a rect to this class be be placed over the selections
00073             /// for use with a border or other kind of decoration.
00074             Type = Widget::W_ListBox;
00075 
00076             // Set some sane template defaults
00077             SelectionTemplate.BackgroundColour = ColourValue(1.0,1.0,1.0,1.0);
00078             SelectionTemplate.TextColour = ColourValue(0.0,0.0,0.0,1.0);
00079             SelectionTemplate.TextScale = 1.0;
00080             SelectionTemplate.CursorOffset = 0.0;
00081             SelectionTemplate.HorizontalAlign = UI::Txt_Middle;
00082             SelectionTemplate.VerticalAlign = UI::Txt_Center;
00083             SelectionTemplate.Priority = UI::RP_Medium;
00084 
00085             RenderableRect ScrollRect, BoxRect;
00086             const Vector2& WinDim = ParentLayer->GetParent()->GetViewportDimensions();
00087             if(Rect.Relative)
00088             {
00089                 RelPosition = Rect.Position;
00090                 RelSize = Rect.Size;
00091 
00092                 SelectionTemplate.Size = Rect.Size * WinDim;
00093 
00094                 ScrollRect.Position = Vector2((RelPosition.X + RelSize.X) - ((Rect.Size.Y * WinDim.Y) / WinDim.X),RelPosition.Y);
00095                 ScrollRect.Size = Vector2((Rect.Size.Y * WinDim.Y) / WinDim.X,RelSize.Y * MaxDisplay);
00096                 ScrollRect.Relative = Rect.Relative;
00097             }else{
00098                 RelPosition = Rect.Position / WinDim;
00099                 RelSize = Rect.Size / WinDim;
00100 
00101                 SelectionTemplate.Size = Rect.Size;
00102 
00103                 ScrollRect.Position = Vector2((Rect.Position.X + Rect.Size.X) - Rect.Size.Y,Rect.Position.Y);
00104                 ScrollRect.Size = Vector2(Rect.Size.Y,Rect.Size.Y * MaxDisplay);
00105                 ScrollRect.Relative = Rect.Relative;
00106             }
00107             BoxRect.Position = Rect.Position;
00108             BoxRect.Size.X = Rect.Size.X;
00109             BoxRect.Size.Y = Rect.Size.Y * MaxDisplay;
00110             BoxRect.Relative = Rect.Relative;
00111 
00112             BoxBack = new Rectangle(BoxRect,ParentLayer);
00113             VertScroll = new Scrollbar(Name+"Scr",ScrollRect,ScrollStyle,ParentLayer);
00114             VertScroll->Hide();
00115 
00116             AddSubRenderable(0,RenderablePair(BoxBack,NULL));
00117             AddSubRenderable(1,RenderablePair(NULL,VertScroll));
00118         }
00119 
00120         ListBox::~ListBox()
00121         {
00122             delete BoxBack;
00123             if(!Selections.empty())
00124             {
00125                 for( std::vector<Caption*>::iterator it = Selections.begin() ; it != Selections.end() ; it++ )
00126                 {
00127                     delete (*it);
00128                 }
00129                 Selections.clear();
00130             }
00131             VisibleSelections.clear();
00132         }
00133 
00134         void ListBox::ScrollerSizeCheck()
00135         {
00136             Real ScrollerSize = (Real)MaxDisplay / (Real)Selections.size();
00137             VertScroll->SetScrollerSize(ScrollerSize);
00138         }
00139 
00140         void ListBox::ScrollHideCheck()
00141         {
00142             if(!IsVisible())
00143             {
00144                 VertScroll->Hide();
00145                 return;
00146             }
00147             if(!AutoHideScroll)
00148             {
00149                 VertScroll->Show();
00150                 return;
00151             }
00152             if(Selections.size() > MaxDisplay)
00153                 VertScroll->Show();
00154             else
00155                 VertScroll->Hide();
00156         }
00157 
00158         void ListBox::SelectionSizeCheck(UI::Caption* Selection)
00159         {
00160             const Vector2& WinDim = ParentLayer->GetParent()->GetViewportDimensions();
00161             Vector2 CurrSize = Selection->GetActualSize();
00162             Vector2 TargetSize;
00163             if(VertScroll->IsVisible())
00164                 TargetSize = Vector2(SelectionTemplate.Size.X - VertScroll->GetActualSize().X,SelectionTemplate.Size.Y);
00165             else
00166                 TargetSize = SelectionTemplate.Size;
00167             if(CurrSize != TargetSize)
00168             {
00169                 Selection->SetActualSize(TargetSize);
00170             }
00171         }
00172 
00173         void ListBox::SetArea(const Vector2& Area)
00174         {
00175             RelSize = Area / ParentLayer->GetParent()->GetViewportDimensions();
00176             BoxBack->SetActualSize(Area);
00177             Vector2 ScrollP((GetActualPosition().X + Area.X) - VertScroll->GetActualSize().X,GetActualPosition().Y);
00178             Vector2 ScrollS(VertScroll->GetActualSize().X,Area.Y);
00179             VertScroll->SetActualPosition(ScrollP);
00180             VertScroll->SetActualSize(ScrollS);
00181         }
00182 
00183         void ListBox::DrawList()
00184         {
00185             if(Selections.empty())
00186                 return;
00187             ScrollHideCheck();
00188             VisibleSelections.clear();
00189             Whole FirstCaption = 0;
00190             if(MaxDisplay < Selections.size())
00191             {
00192                 Real ToBeRounded = VertScroll->GetScrollerValue() * (Real)(Selections.size() - MaxDisplay);
00193                 FirstCaption = (Whole)(ToBeRounded + 0.5);
00194             }
00195             Vector2 SelectionPos = GetActualPosition();
00196             Real ActualInc = SelectionTemplate.Size.Y;
00197 
00198             for( Whole w = 0 ; w < FirstCaption ; ++w )
00199             {
00200                 Selections[w]->SetPosition(GetPosition());
00201                 Selections[w]->Hide();
00202                 SelectionSizeCheck(Selections[w]);
00203             }
00204             Whole Displayed = FirstCaption+MaxDisplay > Selections.size() ? Selections.size() : FirstCaption+MaxDisplay;
00205             for( Whole x = FirstCaption ; x < Displayed ; ++x )
00206             {
00207                 VisibleSelections.push_back(Selections[x]);
00208                 Selections[x]->SetVisible(this->IsVisible());
00209             }
00210             for( Whole y = Displayed ; y < Selections.size() ; ++y )
00211             {
00212                 Selections[y]->SetPosition(GetPosition());
00213                 Selections[y]->Hide();
00214                 SelectionSizeCheck(Selections[y]);
00215             }
00216             for( Whole z = 0 ; z < VisibleSelections.size() ; ++z )
00217             {
00218                 VisibleSelections[z]->SetActualPosition(SelectionPos);
00219                 SelectionPos.Y+=ActualInc;
00220                 SelectionSizeCheck(VisibleSelections[z]);
00221             }
00222         }
00223 
00224         void ListBox::UpdateImpl(bool Force)
00225         {
00226             MetaCode::ButtonState State = InputQueryTool::GetMouseButtonState(1);
00227             if(HoveredCaption)
00228             {
00229                 if(MetaCode::BUTTON_PRESSING == State)
00230                 {
00231                     SetSelected(HoveredCaption);
00232                 }
00233             }
00234             if(LastScrollValue != VertScroll->GetScrollerValue())
00235             {
00236                 DrawList();
00237                 LastScrollValue = VertScroll->GetScrollerValue();
00238             }
00239         }
00240 
00241         void ListBox::SetVisibleImpl(bool visible)
00242         {
00243             BoxBack->SetVisible(visible);
00244             DrawList();
00245         }
00246 
00247         bool ListBox::CheckMouseHoverImpl()
00248         {
00249             for( std::vector<Caption*>::iterator it = VisibleSelections.begin() ; it != VisibleSelections.end() ; it++ )
00250             {
00251                 if((*it)->CheckMouseHover())
00252                 {
00253                     HoveredSubWidget = NULL;
00254                     HoveredButton = NULL;
00255                     HoveredCaption = (*it);
00256                     return true;
00257                 }
00258             }
00259             if(VertScroll->CheckMouseHover())
00260             {
00261                 HoveredSubWidget = VertScroll;
00262                 HoveredButton = VertScroll->GetHoveredButton();
00263                 HoveredCaption = NULL;
00264                 return true;
00265             }
00266             else if(BoxBack->CheckMouseHover())
00267             {
00268                 HoveredSubWidget = NULL;
00269                 HoveredButton = NULL;
00270                 HoveredCaption = NULL;
00271                 return true;
00272             }
00273             HoveredCaption = NULL;
00274             return false;
00275         }
00276 
00277         ListBox& ListBox::SetTemplateSize(const Vector2& Size, bool Relative)
00278         {
00279             const Vector2& WinDim = ParentLayer->GetParent()->GetViewportDimensions();
00280             if(Relative)
00281             {
00282                 this->SelectionTemplate.Size = Size * WinDim;
00283                 Vector2 NewSize = Vector2(Size.X,Size.Y * MaxDisplay);
00284                 SetArea(NewSize * WinDim);
00285             }else{
00286                 this->SelectionTemplate.Size = Size;
00287                 Vector2 NewSize = Vector2(Size.X,Size.Y * MaxDisplay);
00288                 SetArea(NewSize);
00289             }
00290             return *this;
00291         }
00292 
00293         ListBox& ListBox::SetTemplateGlyphIndex(const Whole& Glyph)
00294         {
00295             this->SelectionTemplate.GlyphIndex = Glyph;
00296             return *this;
00297         }
00298 
00299         ListBox& ListBox::SetTemplateTextColour(const ColourValue& TextColour)
00300         {
00301             this->SelectionTemplate.TextColour = TextColour;
00302             return *this;
00303         }
00304 
00305         ListBox& ListBox::SetTemplateTextScale(const Real& Scale)
00306         {
00307             this->SelectionTemplate.TextScale = Scale;
00308             return *this;
00309         }
00310 
00311         ListBox& ListBox::SetTemplateCursorOffset(const Whole& Offset)
00312         {
00313             this->SelectionTemplate.CursorOffset = Offset;
00314             return *this;
00315         }
00316 
00317         ListBox& ListBox::SetTemplateBackgroundColour(const ColourValue& BackgroundColour)
00318         {
00319             this->SelectionTemplate.BackgroundColour = BackgroundColour;
00320             return *this;
00321         }
00322 
00323         ListBox& ListBox::SetTemplateHorizontalAlign(const UI::TextHorizontalAlign& HorAlign)
00324         {
00325             this->SelectionTemplate.HorizontalAlign = HorAlign;
00326             return *this;
00327         }
00328 
00329         ListBox& ListBox::SetTemplateVerticalAlign(const UI::TextVerticalAlign& VertAlign)
00330         {
00331             this->SelectionTemplate.VerticalAlign = VertAlign;
00332             return *this;
00333         }
00334 
00335         ListBox& ListBox::SetTemplateRenderPriority(const UI::RenderPriority& Priority)
00336         {
00337             this->SelectionTemplate.Priority = Priority;
00338             return *this;
00339         }
00340 
00341         const UI::TemplateParams& ListBox::GetTemplateInfo()
00342         {
00343             return this->SelectionTemplate;
00344         }
00345 
00346         Caption* ListBox::AddSelection(ConstString& name, ConstString &Text, ConstString& BackgroundSprite)
00347         {
00348             SelectionsAdded++;
00349             RenderableRect SelectionRect(RelPosition,SelectionTemplate.Size / ParentLayer->GetParent()->GetViewportDimensions(),true);
00350             Caption* Select = new Caption(name,SelectionRect,SelectionTemplate.GlyphIndex,Text,ParentLayer);
00351             if(!BackgroundSprite.empty())
00352                 Select->SetBackgroundSprite(BackgroundSprite);
00353             if(SelectionTemplate.BackgroundColour != ColourValue(1.0,1.0,1.0,1.0))
00354                 Select->SetBackgroundColour(SelectionTemplate.BackgroundColour);
00355             if(SelectionTemplate.CursorOffset != 0)
00356                 Select->SetCursorOffset(SelectionTemplate.CursorOffset);
00357             if(SelectionTemplate.TextScale != 1)
00358                 Select->SetTextScale(SelectionTemplate.TextScale);
00359             Select->SetTextColour(SelectionTemplate.TextColour);
00360             Select->HorizontallyAlign(SelectionTemplate.HorizontalAlign);
00361             Select->VerticallyAlign(SelectionTemplate.VerticalAlign);
00362             Select->SetRenderPriority(SelectionTemplate.Priority);
00363             Select->Hide();
00364             Selections.push_back(Select);
00365             AddSubRenderable(SelectionsAdded,RenderablePair(Select,NULL));
00366             ScrollerSizeCheck();
00367             DrawList();
00368             return Select;
00369         }
00370 
00371         Caption* ListBox::GetSelection(ConstString &Name)
00372         {
00373             for ( std::vector<Caption*>::iterator it = Selections.begin() ; it != Selections.end() ; it++ )
00374             {
00375                 if ( Name == (*it)->GetName() )
00376                 {
00377                     UI::Caption* button = (*it);
00378                     return button;
00379                 }
00380             }
00381             return 0;
00382         }
00383 
00384         void ListBox::DestroySelection(Caption* ToBeDestroyed)
00385         {
00386             for ( std::vector<Caption*>::iterator it = Selections.begin() ; it != Selections.end() ; it++ )
00387             {
00388                 if ( ToBeDestroyed == (*it) )
00389                 {
00390                     Selections.erase(it);
00391                     break;
00392                 }
00393             }
00394             for ( RenderableMap::iterator it = SubRenderables.begin() ; it != SubRenderables.end() ; ++it )
00395             {
00396                 if( (*it).second.first == ToBeDestroyed )
00397                 {
00398                     SubRenderables.erase(it);
00399                     break;
00400                 }
00401             }
00402             delete ToBeDestroyed;
00403         }
00404 
00405         void ListBox::DestroySelection(String& ToBeDestroyed)
00406         {
00407             for ( std::vector<Caption*>::iterator it = Selections.begin() ; it != Selections.end() ; it++ )
00408             {
00409                 if ( ToBeDestroyed == (*it)->GetName() )
00410                 {
00411                     delete (*it);
00412                     Selections.erase(it);
00413                     return;
00414                 }
00415             }
00416         }
00417 
00418         void ListBox::SetSelected(Caption* ToBeSelected)
00419         {
00420             /// @todo Maybe add a checker to verify the caption belongs to this widget?
00421             Selected = ToBeSelected;
00422         }
00423 
00424         void ListBox::SetMaxDisplayedSelections(const Whole& MaxSelections)
00425         {
00426             MaxDisplay = MaxSelections;
00427             Vector2 NewBackSize = SelectionTemplate.Size;
00428             NewBackSize.Y*=MaxDisplay;
00429             SetArea(NewBackSize);
00430             ScrollerSizeCheck();
00431         }
00432 
00433         void ListBox::SetAutoHideScroll(bool AutoHide)
00434         {
00435             AutoHideScroll = AutoHide;
00436             ScrollHideCheck();
00437         }
00438 
00439         void ListBox::SetPosition(const Vector2& Position)
00440         {
00441             RelPosition = Position;
00442             Vector2 ScrollOffset = VertScroll->GetPosition() - RelPosition;
00443             BoxBack->SetPosition(Position);
00444             VertScroll->SetPosition(Position + ScrollOffset);
00445             DrawList();
00446         }
00447 
00448         void ListBox::SetActualPosition(const Vector2& Position)
00449         {
00450             RelPosition = Position / ParentLayer->GetParent()->GetViewportDimensions();
00451             Vector2 ScrollOffset = VertScroll->GetActualPosition() - (RelPosition * ParentLayer->GetParent()->GetViewportDimensions());
00452             BoxBack->SetActualPosition(Position);
00453             VertScroll->SetActualPosition(Position + ScrollOffset);
00454             DrawList();
00455         }
00456 
00457         void ListBox::SetSize(const Vector2& Size)
00458         {
00459             // Size is set implicitly
00460         }
00461 
00462         void ListBox::SetActualSize(const Vector2& Size)
00463         {
00464             // Size is set implicitly
00465         }
00466 
00467         void ListBox::UpdateDimensions()
00468         {
00469             /*const Vector2& WinDim = ParentLayer->GetParent()->GetViewportDimensions();
00470             SetArea(RelSize * WinDim);
00471             SetActualPosition(RelPosition * WinDim);*/
00472 
00473             WidgetResult Result = ViewportUpdateTool::UpdateWidget(this);
00474             RelPosition = Result.first / ViewportUpdateTool::GetNewSize();
00475             RelSize = Result.second / ViewportUpdateTool::GetNewSize();
00476             Real Scale = ViewportUpdateTool::GetNewSize().Y / ViewportUpdateTool::GetOldSize().Y;
00477             BoxBack->UpdateDimensions();
00478             VertScroll->UpdateDimensions();
00479             SelectionTemplate.Size*=Scale;
00480             DrawList();
00481             SetPosition(RelPosition);
00482         }
00483 
00484         Caption* ListBox::GetSelected()
00485         {
00486             return Selected;
00487         }
00488 
00489         Rectangle* ListBox::GetBoxBack()
00490         {
00491             return BoxBack;
00492         }
00493 
00494         UI::Scrollbar* ListBox::GetVertScroll()
00495         {
00496             return VertScroll;
00497         }
00498     }//UI
00499 }//Mezzanine
00500 
00501 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines