diff options
Diffstat (limited to 'plugins/MirandaG15/src/LCDFramework/CLCDList.h')
-rw-r--r-- | plugins/MirandaG15/src/LCDFramework/CLCDList.h | 1886 |
1 files changed, 944 insertions, 942 deletions
diff --git a/plugins/MirandaG15/src/LCDFramework/CLCDList.h b/plugins/MirandaG15/src/LCDFramework/CLCDList.h index ae019fe914..80a6b246cf 100644 --- a/plugins/MirandaG15/src/LCDFramework/CLCDList.h +++ b/plugins/MirandaG15/src/LCDFramework/CLCDList.h @@ -1,943 +1,945 @@ -#ifndef _CLCDLIST_H_
-#define _CLCDLIST_H_
-
-#include "CLCDTextObject.h"
-#include "CLCDBar.h"
-#include <math.h>
-
-
-enum EListEntryType { ROOT = 0,CONTAINER = 1,ITEM = 2};
-
-template <class T, class G = tstring> class CListEntry
-{
-public:
- CListEntry(CListEntry<T,G> *pParent)
- {
- m_iIndex = -1;
- m_iEntryCount = 0;
- m_Position = NULL;
- m_pParent = pParent;
- if(pParent == NULL)
- {
- m_iLevel = 0;
- m_eType = ROOT;
- m_pRoot = this;
- }
- else
- m_iLevel = m_pParent->GetLevel()+1;
- }
-
- virtual ~CListEntry()
- {
-
- }
-
- int GetLevel()
- {
- return m_iLevel;
- }
-
- virtual CListEntry<T,G> *GetNextEntry()
- {
- if(m_pParent == NULL)
- return NULL;
-
- return m_pParent->GetNextEntry(this);
- }
-
- virtual CListEntry<T,G> *GetPreviousEntry()
- {
- if(m_pParent == NULL)
- return NULL;
-
- return m_pParent->GetPreviousEntry(this);
- }
-
- virtual CListEntry<T,G> *GetNextEntry(CListEntry<T,G> *pEntry)
- {
- return NULL;
- }
-
- virtual CListEntry<T,G> *GetPreviousEntry(CListEntry<T,G> *pEntry)
- {
- return NULL;
- }
-
- EListEntryType GetType()
- {
- return m_eType;
- }
-
- int GetEntryCount()
- {
- return m_iEntryCount;
- }
-
- virtual void UpdateEntryCount()
- {
- m_iEntryCount = 0;
- }
-
- void SetRoot(CListEntry<T,G>* pRoot)
- {
- m_pRoot = pRoot;
- }
-
- virtual void DeleteItem(T Entry)
- {
- }
-
- virtual void DeleteGroup(G Group)
- {
- }
-
- CListEntry<T,G> *GetPosition()
- {
- return m_Position;
- }
-
- virtual void SetPosition(CListEntry<T,G> *pPosition)
- {
- m_Position = pPosition;
- }
-
- CListEntry<T,G> *GetParent()
- {
- return m_pParent;
- }
-
- int GetIndex()
- {
- return m_iIndex;
- }
-
- void SetIndex(int iIndex)
- {
- m_iIndex = iIndex;
- }
-
-protected:
- int m_iIndex;
- int m_iEntryCount;
- int m_iLevel;
- EListEntryType m_eType;
- CListEntry<T,G> *m_pParent;
- CListEntry<T,G> *m_pRoot;
- CListEntry<T,G> *m_Position;
-};
-
-template <class T, class G = tstring> class CListItem : public CListEntry<T,G>
-{
-public:
- CListItem(CListEntry<T,G> *pParent,T Entry) : CListEntry<T,G>(pParent)
- {
- m_Item = Entry;
- m_eType = ITEM;
- }
-
- ~CListItem()
- {
- m_pRoot->DeleteItem(GetItemData());
- }
-
- T GetItemData()
- {
- return m_Item;
- }
-private:
- T m_Item;
-};
-
-template <class T, class G = tstring> class CListContainer : public CListEntry<T,G>
-{
-public:
- typedef typename list<CListEntry<T,G>* >::iterator iterator;
-
- typename list<CListEntry<T,G>* >::iterator end()
- {
- return m_Entrys.end();
- }
-
- typename list<CListEntry<T,G>* >::iterator begin()
- {
- return m_Entrys.begin();
- }
-
- typename list<CListEntry<T,G>* >::size_type size()
- {
- return m_Entrys.size();
- }
-
- bool empty()
- {
- bool b = m_Entrys.empty();
- return m_Entrys.empty();
- }
-
- CListContainer(CListEntry<T,G> *pParent) : CListEntry<T,G>(pParent)
- {
- if(m_pParent != NULL)
- {
- m_eType = CONTAINER;
- m_bOpen = false;
- }
- else
- m_bOpen = true;
- }
-
- ~CListContainer()
- {
- if(m_pRoot != NULL) {
- m_pRoot->DeleteGroup(GetGroupData());
- }
- Clear();
- }
-
- void Clear()
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListItem<T,G> *pItem = NULL;
- CListContainer<T,G> *pContainer = NULL;
-
- while(iter != m_Entrys.end())
- {
- delete *iter;
- if(m_pRoot && m_pRoot->GetPosition() == *iter)
- {
- if(GetType() == ROOT)
- m_pRoot->SetPosition(NULL);
- else
- m_pRoot->SetPosition(this);
- }
-
- iter++;
- }
- m_Entrys.clear();
- }
-
- void SetGroupData(G GroupData)
- {
- m_GroupData = GroupData;
- }
-
- bool IsEmpty()
- {
- return m_Entrys.empty();
- }
-
- CListEntry<T,G> *GetLastOwnEntry()
- {
- if(m_Entrys.empty())
- return NULL;
-
- return *(--m_Entrys.end());
- }
-
- CListEntry<T,G> *GetLastEntry()
- {
- if(!m_Entrys.empty())
- {
-
- CListEntry<T,G> *pEntry = *(--m_Entrys.end());
- if(pEntry->GetType() == ITEM || !((CListContainer<T,G>*)pEntry)->IsOpen() || ((CListContainer<T,G>*)pEntry)->IsEmpty())
- return pEntry;
- return ((CListContainer<T,G>*)pEntry)->GetLastEntry();
- }
- return NULL;
- }
-
- CListEntry<T,G> *GetFirstEntry()
- {
- if(!m_Entrys.empty())
- return *(m_Entrys.begin());
- return NULL;
- }
-
- CListEntry<T,G> *GetNextEntry()
- {
- if(!IsOpen() || m_Entrys.empty())
- {
- if(!m_pParent)
- return NULL;
- return m_pParent->GetNextEntry(this);
- }
-
- return *m_Entrys.begin();
- }
-
- CListEntry<T,G> *GetNextEntry(CListEntry<T,G> *pEntry)
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- while(iter != m_Entrys.end())
- {
- if((CListEntry<T,G>*)(*iter) == pEntry)
- {
- if(++iter == m_Entrys.end())
- {
- if(m_pParent == NULL)
- return NULL;
- return m_pParent->GetNextEntry(this);
- }
- else
- return *iter;
- }
- iter++;
- }
- return NULL;
- }
-
- CListEntry<T,G> *GetPreviousEntry(CListEntry<T,G> *pEntry)
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
-
- while(iter != m_Entrys.end())
- {
- if((CListEntry<T,G>*)(*iter) == pEntry)
- {
- if(iter == m_Entrys.begin())
- {
- if(m_pParent == NULL)
- return NULL;
- return this;
- }
- else
- {
- iter--;
- if((*iter)->GetType() == CONTAINER)
- {
- CListContainer<T,G>* pContainer = (CListContainer<T,G>*)*iter;
- if(pContainer->IsOpen() && !pContainer->IsEmpty())
- return pContainer->GetLastEntry();
- }
- return *iter;
- }
- }
- iter++;
- }
- return NULL;
- }
-
- virtual CListItem<T,G> *InsertItem(iterator _Where,T Entry)
- {
- CListItem<T,G> *pItem = new CListItem<T,G>(this,Entry);
- pItem->SetRoot(m_pRoot);
- m_Entrys.insert(_Where,pItem);
-
- m_pRoot->UpdateEntryCount();
-
- return pItem;
- }
-
- virtual CListContainer<T,G> *InsertGroup(iterator _Where,G Group)
- {
- CListContainer<T,G> *pGroup = new CListContainer<T,G>(this);
- pGroup->SetGroupData(Group);
- pGroup->SetRoot(m_pRoot);
- m_Entrys.insert(_Where,(CListEntry<T,G>*)pGroup);
-
- m_pRoot->UpdateEntryCount();
-
- return pGroup;
- }
-
- virtual CListItem<T,G> * AddItem(T Entry)
- {
- return InsertItem(end(),Entry);
- }
-
- virtual CListContainer<T,G> * AddGroup(G Group)
- {
- return InsertGroup(end(),Group);
- }
-
-
-
- virtual void RemoveGroup(G Group)
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListContainer<T,G> *pContainer = NULL;
- while(iter != m_Entrys.end())
- {
- if((*iter)->GetType() == CONTAINER)
- {
- pContainer = (CListContainer<T,G>*)(*iter);
- if(pContainer->GetGroupData() == Group)
- {
- pContainer->Clear();
- if(m_pRoot && m_pRoot->GetPosition() == *iter)
- {
- CListEntry<T,G> *pPosition = (*iter)->GetPreviousEntry();
- if(!pPosition)
- pPosition = (*iter)->GetNextEntry();
- m_pRoot->SetPosition(pPosition);
- }
- delete *iter;
- m_Entrys.erase(iter);
- m_pRoot->UpdateEntryCount();
- return;
- }
- }
- iter++;
- }
- }
-
- virtual void RemoveItem(T Entry)
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListItem<T,G> *pItem = NULL;
- while(iter != m_Entrys.end())
- {
- if((*iter)->GetType() == ITEM)
- {
- pItem = (CListItem<T,G>*)(*iter);
- if(pItem->GetItemData() == Entry)
- {
- if(m_pRoot && m_pRoot->GetPosition() == *iter)
- {
- CListEntry<T,G> *pPosition = (*iter)->GetPreviousEntry();
- if(!pPosition)
- pPosition = (*iter)->GetNextEntry();
- m_pRoot->SetPosition(pPosition);
- }
- delete *iter;
-
- m_Entrys.erase(iter);
- m_pRoot->UpdateEntryCount();
- return;
- }
- }
- iter++;
- }
- }
-
- CListContainer<T,G> *GetGroup(G Group)
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListContainer<T,G> *pContainer = NULL;
- while(iter != m_Entrys.end())
- {
- if((*iter)->GetType() == CONTAINER)
- {
- pContainer = (CListContainer<T,G>*)(*iter);
- if(pContainer->GetGroupData() == Group)
- return pContainer;
- }
- iter++;
- }
- return NULL;
- }
-
- G GetGroupData()
- {
- return m_GroupData;
- }
-
- bool IsOpen()
- {
- return m_bOpen;
- }
-
- void ToggleOpen()
- {
- m_bOpen = !m_bOpen;
-
- m_pRoot->UpdateEntryCount();
- if(m_pRoot)
- m_pRoot->SetPosition(this);
- }
-
- void SetOpen(bool bOpen = true)
- {
- if(bOpen == m_bOpen)
- return;
-
- m_bOpen = bOpen;
-
- m_pRoot->UpdateEntryCount();
- if(m_pRoot)
- m_pRoot->SetPosition(this);
- }
-
- void CollapseAll()
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListContainer<T,G>* pContainer = NULL;
- while(iter != m_Entrys.end())
- {
- if((*iter)->GetType() == CONTAINER)
- {
- pContainer = (CListContainer<T,G>*)(*iter);
- pContainer->CollapseAll();
- pContainer->SetOpen(false);
- }
- iter++;
- }
- }
-
- void ExpandAll()
- {
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- CListContainer<T,G>* pContainer = NULL;
- while(iter != m_Entrys.end())
- {
- if((*iter)->GetType() == CONTAINER)
- {
- pContainer = (CListContainer<T,G>*)(*iter);
- pContainer->ExpandAll();
- pContainer->SetOpen(true);
- }
- iter++;
- }
- }
-
- void UpdateEntryCount()
- {
- m_iEntryCount = 0;
-
- int iIndex = GetIndex()+1;
-
- if(!IsOpen())
- return;
-
- list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin();
- while(iter != m_Entrys.end())
- {
- (*iter)->SetIndex(iIndex+m_iEntryCount);
- (*iter)->UpdateEntryCount();
- m_iEntryCount += 1+(*iter)->GetEntryCount();
-
- iter++;
- }
-
- if(GetType() == ROOT)
- {
- if(GetPosition() == NULL && !m_Entrys.empty())
- SetPosition(*m_Entrys.begin());
- else
- SetPosition(GetPosition());
- }
- }
-
- template<class _Pr3>
- void sort(_Pr3 _Pred) {
- m_Entrys.sort(_Pred);
- UpdateEntryCount();
- m_pRoot->SetPosition(m_pRoot->GetPosition());
- }
-
-private:
- typename list< CListEntry<T,G>* > m_Entrys;
- G m_GroupData;
- bool m_bOpen;
-};
-
-
-template <class T, class G = tstring> class CLCDList : public CLCDTextObject, public CListContainer<T,G>
-{
-friend CListContainer<T,G>;
-friend CListItem<T,G>;
-public:
- //************************************************************************
- // Constructor
- //************************************************************************
- CLCDList() : CListContainer<T,G>(NULL)
- {
- m_pScrollbar = NULL;
- m_iIndention = 10;
- m_iColumns = 1;
- m_bDrawTreeLines = true;
- m_iEntryHeight = 10;
- }
-
- //************************************************************************
- // Destructor
- //************************************************************************
- ~CLCDList()
- {
- }
-
- //************************************************************************
- // Initializes the list
- //************************************************************************
- bool Initialize()
- {
- if(!CLCDTextObject::Initialize())
- return false;
-
- return true;
- }
-
- //************************************************************************
- // Deinitializes the list
- //************************************************************************
- bool Shutdown()
- {
- if(!CLCDTextObject::Shutdown())
- return false;
-
- Clear();
-
- return true;
- }
-
- //************************************************************************
- // updates the list
- //************************************************************************
- bool Update()
- {
- if(!CLCDTextObject::Update())
- return false;
-
- return true;
- }
-
- //************************************************************************
- // draws the list
- //************************************************************************
- bool Draw(CLCDGfx *pGfx)
- {
- if(!CLCDTextObject::Draw(pGfx))
- return false;
-
- SelectObject(pGfx->GetHDC(),m_hFont);
-
- POINT ptPrevViewportOrg = { 0, 0 };
- HRGN hRgn = NULL;
- int iHeight = 0,iLimit=0;
- int iYOffset = 0, iXOffset=0;
- int iColWidth = (GetWidth()- (m_iColumns-1)*3)/m_iColumns;
- int iSpace = GetHeight() - (GetHeight()/m_iEntryHeight)*m_iEntryHeight;
- int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns;
-
- int iEntriesDrawn = 0;
- CListEntry<T,G> *pPosition = m_Position;
-
- // if nothing is selected, skip drawing
- if(pPosition == NULL)
- return true;
-
- bool bDrawGroup = false;
- bool bSelected = false;
-
- // calculate the start offset
-
- if(m_iStartIndex < pPosition->GetIndex())
- {
- while(pPosition && pPosition->GetIndex() != m_iStartIndex)
- pPosition = pPosition->GetPreviousEntry();
- }
-
- if(m_iStartIndex > 0 && pPosition->GetIndex() > 0)
- pPosition = pPosition->GetPreviousEntry();
-
- for(int iCol = 0;iCol<m_iColumns;iCol++)
- {
- iHeight = 0;
- if(iCol == 0)
- {
- if(pPosition->GetIndex() < m_iStartIndex)
- iHeight -= m_iEntryHeight-iSpace;
- else if(GetEntryCount() >= (iPerPage/m_iColumns) +1)
- iHeight = iSpace;
- }
-
- // bottom selection
- while(pPosition != NULL )
- {
- iYOffset = iHeight;
-
- bSelected = m_Position == pPosition;
- bDrawGroup = pPosition->GetType() == CONTAINER;
-
- // ~~~~~~~~~~~~~~~~~~~~~~
- // Draw tree lines
- // ~~~~~~~~~~~~~~~~~~~~~~
-
- // set the clip region for the entry
- int iClipHeight = m_iEntryHeight;
- if(GetOrigin().y+iYOffset+iClipHeight > GetOrigin().y + GetHeight())
- iClipHeight = GetHeight() - iYOffset;
-
- pGfx->SetClipRegion(GetOrigin().x+iXOffset,GetOrigin().y+iYOffset,
- iColWidth, iClipHeight);
-
- // offset the control at its origin so entry use (0,0)
- SetViewportOrgEx(pGfx->GetHDC(),
- GetOrigin().x+iXOffset,
- GetOrigin().y+iYOffset,
- &ptPrevViewportOrg);
-
- if(m_bDrawTreeLines)
- {
- for(int i=1;i<pPosition->GetLevel();i++)
- {
- if(i == pPosition->GetLevel()-1)
- {
- // -
- pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight/2,i*m_iIndention,m_iEntryHeight/2);
- // |
- if(pPosition == ((CListContainer<T,G>*)pPosition->GetParent())->GetLastOwnEntry())
- pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight/2);
- // |
- // |
- else
- pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight);
- }
- else
- {
- CListEntry<T,G> *pPosition2 = pPosition;
- for(int j = pPosition->GetLevel();j>i+1;j--)
- pPosition2 = pPosition2->GetParent();
- // |
- // |
- if(pPosition2 != ((CListContainer<T,G>*)pPosition2->GetParent())->GetLastOwnEntry())
- pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight);
- }
- }
- }
-
- // ~~~~~~~~~~~~~~~~~~~~~~
- // Draw the entry
- // ~~~~~~~~~~~~~~~~~~~~~~
- pGfx->SetClipRegion(GetOrigin().x+(pPosition->GetLevel()-1)*m_iIndention+iXOffset,
- GetOrigin().y+iYOffset,
- iColWidth-(pPosition->GetLevel()-1)*m_iIndention,
- iClipHeight);
- // set the offset
- SetViewportOrgEx(pGfx->GetHDC(),
- GetOrigin().x+(pPosition->GetLevel()-1)*m_iIndention+iXOffset,
- GetOrigin().y+iYOffset,
- &ptPrevViewportOrg);
-
- // draw the entry
- if(!bDrawGroup)
- DrawEntry(pGfx,((CListItem<T,G>*)pPosition)->GetItemData(),bSelected);
- else
- // draw the group
- DrawGroup(pGfx,((CListContainer<T,G>*)pPosition)->GetGroupData(),((CListContainer<T,G>*)pPosition)->IsOpen(),bSelected);
-
- // ~~~~~~~~~~~~~~~~~~~~~~
-
- if(pPosition->GetIndex() >= m_iStartIndex && iHeight + m_iEntryHeight <= GetHeight())
- iEntriesDrawn++;
-
- iHeight += m_iEntryHeight;
- pPosition = pPosition->GetNextEntry();
-
- if(iHeight >= GetHeight())
- break;
- }
- if(iCol != m_iColumns-1)
- {
- pGfx->SetClipRegion(GetOrigin().x,
- GetOrigin().y,
- GetWidth(),
- GetHeight());
- // set the offset
- SetViewportOrgEx(pGfx->GetHDC(),
- GetOrigin().x,
- GetOrigin().y,
- &ptPrevViewportOrg);
-
- pGfx->DrawLine(iCol*3 + iColWidth + 1,0,iCol*3 + iColWidth + 1,GetHeight());
- }
- iXOffset += 3 + iColWidth;
- }
-
- if(m_pScrollbar)
- {
- m_pScrollbar->ScrollTo(m_iStartIndex);
- m_pScrollbar->SetSliderSize(iEntriesDrawn);
- }
- return true;
- }
-
-
- void SetPosition(CListEntry<T,G> *pEntry)
- {
- CListContainer<T,G>::SetPosition(pEntry);
-
- if(pEntry == NULL)
- return;
-
- int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns;
- m_iStartIndex = pEntry->GetIndex();
- if(m_iStartIndex + (iPerPage-1) > GetEntryCount()-1)
- m_iStartIndex = (GetEntryCount()-1)-(iPerPage-1);
- if(m_iStartIndex < 0)
- m_iStartIndex = 0;
- }
-
- //************************************************************************
- // scrolls up
- //************************************************************************
- bool ScrollUp()
- {
- if(m_Position != NULL)
- {
- CListEntry<T,G> *pEntry = m_Position->GetPreviousEntry();
- if(pEntry != NULL)
- {
- m_Position = pEntry;
-
- int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns;
- if(m_Position->GetIndex() < m_iStartIndex)
- m_iStartIndex--;
- return true;
- }
- }
- return false;
- }
-
- //************************************************************************
- // scrolls down
- //************************************************************************
- bool ScrollDown()
- {
- if(m_Position != NULL)
- {
- CListEntry<T,G> *pEntry = m_Position->GetNextEntry();
- if(pEntry != NULL)
- {
- m_Position = pEntry;
-
- int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns;
- if(m_Position->GetIndex() >= m_iStartIndex + iPerPage)
- m_iStartIndex++;
- return true;
- }
- }
- return false;
- }
-
- //************************************************************************
- // returns the selected list entry
- //************************************************************************
- CListEntry<T,G> *GetSelectedEntry()
- {
- return m_Position;
- }
-
- //************************************************************************
- // associates a scrollbar with the list
- //************************************************************************
- void SetScrollbar(CLCDBar *pScrollbar)
- {
- m_pScrollbar = pScrollbar;
- if(m_pScrollbar)
- {
- m_pScrollbar->SetRange(0,m_iEntryCount-1);
- m_pScrollbar->ScrollTo(m_Position != NULL?m_Position->GetIndex():0);
-
- m_pScrollbar->SetAlignment(TOP);
- }
- }
-
- //************************************************************************
- // sets the group indention in pixels
- //************************************************************************
- void SetIndention(int iIndention)
- {
- m_iIndention = iIndention;
- }
-
- //************************************************************************
- // sets the lists entry height
- //************************************************************************
- void SetEntryHeight(int iEntryHeight)
- {
- m_iEntryHeight = iEntryHeight;
- }
-
- //************************************************************************
- // returns the lists entry height
- //************************************************************************
- int GetEntryHeight()
- {
- return m_iEntryHeight;
- }
-
- //************************************************************************
- // enables/disables drawing of treelines
- //************************************************************************
- void SetDrawTreeLines(bool bDraw)
- {
- m_bDrawTreeLines = bDraw;
- }
-
- //************************************************************************
- // sets the amount of columns the list uses
- //************************************************************************
- void SetColumns(int iColumns)
- {
- if(m_iColumns == iColumns)
- return;
- m_iColumns = iColumns;
- SetPosition(GetPosition());
- }
-protected:
- //************************************************************************
- // called when the lists size has changed
- //************************************************************************
- void OnSizeChanged()
- {
- SetPosition(GetPosition());
- }
-
- //************************************************************************
- // updates the list's entry count
- //************************************************************************
- void UpdateEntryCount()
- {
- CListContainer<T,G>::UpdateEntryCount();
- if(m_pScrollbar)
- {
- m_pScrollbar->SetRange(0,m_iEntryCount-1);
- if(GetPosition() != NULL)
- m_pScrollbar->ScrollTo(GetPosition()->GetIndex());
- }
- }
-
- //************************************************************************
- // Called to delete the specified entry
- //************************************************************************
- virtual void DeleteEntry(T Entry)
- {
-
- }
-
- //************************************************************************
- // Called to delete the specified group
- //************************************************************************
- virtual void DeleteGroup(G Group)
- {
-
- }
-
- //************************************************************************
- // Called to draw the specified entry
- //************************************************************************
- virtual void DrawEntry(CLCDGfx *pGfx,T Entry, bool bSelected)
- {
- }
-
- //************************************************************************
- // Called to draw the specified entry
- //************************************************************************
- virtual void DrawGroup(CLCDGfx *pGfx,G Group, bool bOpen, bool bSelected)
- {
- }
-
-
-
-protected:
- int m_iStartIndex;
- int m_iColumns;
-
- bool m_bDrawTreeLines;
- int m_iIndention;
- int m_iEntryHeight;
- CLCDBar *m_pScrollbar;
-};
-
+#ifndef _CLCDLIST_H_ +#define _CLCDLIST_H_ + +#include "CLCDTextObject.h" +#include "CLCDBar.h" +#include <math.h> + + +enum EListEntryType { ROOT = 0,CONTAINER = 1,ITEM = 2}; + +template <class T, class G = tstring> class CListEntry +{ +public: + CListEntry(CListEntry<T,G> *pParent) + { + m_iIndex = -1; + m_iEntryCount = 0; + m_Position = NULL; + m_pParent = pParent; + if(pParent == NULL) + { + m_iLevel = 0; + m_eType = ROOT; + m_pRoot = this; + } + else + m_iLevel = m_pParent->GetLevel()+1; + } + + virtual ~CListEntry() + { + + } + + int GetLevel() + { + return m_iLevel; + } + + virtual CListEntry<T,G> *GetNextEntry() + { + if(m_pParent == NULL) + return NULL; + + return m_pParent->GetNextEntry(this); + } + + virtual CListEntry<T,G> *GetPreviousEntry() + { + if(m_pParent == NULL) + return NULL; + + return m_pParent->GetPreviousEntry(this); + } + + virtual CListEntry<T,G> *GetNextEntry(CListEntry<T,G> *pEntry) + { + return NULL; + } + + virtual CListEntry<T,G> *GetPreviousEntry(CListEntry<T,G> *pEntry) + { + return NULL; + } + + EListEntryType GetType() + { + return m_eType; + } + + int GetEntryCount() + { + return m_iEntryCount; + } + + virtual void UpdateEntryCount() + { + m_iEntryCount = 0; + } + + void SetRoot(CListEntry<T,G>* pRoot) + { + m_pRoot = pRoot; + } + + virtual void DeleteItem(T Entry) + { + } + + virtual void DeleteGroup(G Group) + { + } + + CListEntry<T,G> *GetPosition() + { + return m_Position; + } + + virtual void SetPosition(CListEntry<T,G> *pPosition) + { + m_Position = pPosition; + } + + CListEntry<T,G> *GetParent() + { + return m_pParent; + } + + int GetIndex() + { + return m_iIndex; + } + + void SetIndex(int iIndex) + { + m_iIndex = iIndex; + } + +protected: + int m_iIndex; + int m_iEntryCount; + int m_iLevel; + EListEntryType m_eType; + CListEntry<T,G> *m_pParent; + CListEntry<T,G> *m_pRoot; + CListEntry<T,G> *m_Position; +}; + +template <class T, class G = tstring> class CListItem : public CListEntry<T,G> +{ +public: + CListItem(CListEntry<T,G> *pParent,T Entry) : CListEntry<T,G>(pParent) + { + m_Item = Entry; + m_eType = ITEM; + } + + ~CListItem() + { + m_pRoot->DeleteItem(GetItemData()); + } + + T GetItemData() + { + return m_Item; + } +private: + T m_Item; +}; + +template <class T, class G = tstring> class CListContainer : public CListEntry<T,G> +{ +public: + typedef typename list<CListEntry<T,G>* >::iterator iterator; + + typename list<CListEntry<T,G>* >::iterator end() + { + return m_Entrys.end(); + } + + typename list<CListEntry<T,G>* >::iterator begin() + { + return m_Entrys.begin(); + } + + typename list<CListEntry<T,G>* >::size_type size() + { + return m_Entrys.size(); + } + + bool empty() + { + bool b = m_Entrys.empty(); + return m_Entrys.empty(); + } + + CListContainer(CListEntry<T,G> *pParent) : CListEntry<T,G>(pParent) + { + if(m_pParent != NULL) + { + m_eType = CONTAINER; + m_bOpen = false; + } + else + m_bOpen = true; + } + + ~CListContainer() + { + if(m_pRoot != NULL) { + m_pRoot->DeleteGroup(GetGroupData()); + } + Clear(); + } + + void Clear() + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListItem<T,G> *pItem = NULL; + CListContainer<T,G> *pContainer = NULL; + + while(iter != m_Entrys.end()) + { + delete *iter; + if(m_pRoot && m_pRoot->GetPosition() == *iter) + { + if(GetType() == ROOT) + m_pRoot->SetPosition(NULL); + else + m_pRoot->SetPosition(this); + } + + iter++; + } + m_Entrys.clear(); + } + + void SetGroupData(G GroupData) + { + m_GroupData = GroupData; + } + + bool IsEmpty() + { + return m_Entrys.empty(); + } + + CListEntry<T,G> *GetLastOwnEntry() + { + if(m_Entrys.empty()) + return NULL; + + return *(--m_Entrys.end()); + } + + CListEntry<T,G> *GetLastEntry() + { + if(!m_Entrys.empty()) + { + + CListEntry<T,G> *pEntry = *(--m_Entrys.end()); + if(pEntry->GetType() == ITEM || !((CListContainer<T,G>*)pEntry)->IsOpen() || ((CListContainer<T,G>*)pEntry)->IsEmpty()) + return pEntry; + return ((CListContainer<T,G>*)pEntry)->GetLastEntry(); + } + return NULL; + } + + CListEntry<T,G> *GetFirstEntry() + { + if(!m_Entrys.empty()) + return *(m_Entrys.begin()); + return NULL; + } + + CListEntry<T,G> *GetNextEntry() + { + if(!IsOpen() || m_Entrys.empty()) + { + if(!m_pParent) + return NULL; + return m_pParent->GetNextEntry(this); + } + + return *m_Entrys.begin(); + } + + CListEntry<T,G> *GetNextEntry(CListEntry<T,G> *pEntry) + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + while(iter != m_Entrys.end()) + { + if((CListEntry<T,G>*)(*iter) == pEntry) + { + if(++iter == m_Entrys.end()) + { + if(m_pParent == NULL) + return NULL; + return m_pParent->GetNextEntry(this); + } + else + return *iter; + } + iter++; + } + return NULL; + } + + CListEntry<T,G> *GetPreviousEntry(CListEntry<T,G> *pEntry) + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + + while(iter != m_Entrys.end()) + { + if((CListEntry<T,G>*)(*iter) == pEntry) + { + if(iter == m_Entrys.begin()) + { + if(m_pParent == NULL) + return NULL; + return this; + } + else + { + iter--; + if((*iter)->GetType() == CONTAINER) + { + CListContainer<T,G>* pContainer = (CListContainer<T,G>*)*iter; + if(pContainer->IsOpen() && !pContainer->IsEmpty()) + return pContainer->GetLastEntry(); + } + return *iter; + } + } + iter++; + } + return NULL; + } + + virtual CListItem<T,G> *InsertItem(iterator _Where,T Entry) + { + CListItem<T,G> *pItem = new CListItem<T,G>(this,Entry); + pItem->SetRoot(m_pRoot); + m_Entrys.insert(_Where,pItem); + + m_pRoot->UpdateEntryCount(); + + return pItem; + } + + virtual CListContainer<T,G> *InsertGroup(iterator _Where,G Group) + { + CListContainer<T,G> *pGroup = new CListContainer<T,G>(this); + pGroup->SetGroupData(Group); + pGroup->SetRoot(m_pRoot); + m_Entrys.insert(_Where,(CListEntry<T,G>*)pGroup); + + m_pRoot->UpdateEntryCount(); + + return pGroup; + } + + virtual CListItem<T,G> * AddItem(T Entry) + { + return InsertItem(end(),Entry); + } + + virtual CListContainer<T,G> * AddGroup(G Group) + { + return InsertGroup(end(),Group); + } + + + + virtual void RemoveGroup(G Group) + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListContainer<T,G> *pContainer = NULL; + while(iter != m_Entrys.end()) + { + if((*iter)->GetType() == CONTAINER) + { + pContainer = (CListContainer<T,G>*)(*iter); + if(pContainer->GetGroupData() == Group) + { + pContainer->Clear(); + if(m_pRoot && m_pRoot->GetPosition() == *iter) + { + CListEntry<T,G> *pPosition = (*iter)->GetPreviousEntry(); + if(!pPosition) + pPosition = (*iter)->GetNextEntry(); + m_pRoot->SetPosition(pPosition); + } + delete *iter; + m_Entrys.erase(iter); + m_pRoot->UpdateEntryCount(); + return; + } + } + iter++; + } + } + + virtual void RemoveItem(T Entry) + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListItem<T,G> *pItem = NULL; + while(iter != m_Entrys.end()) + { + if((*iter)->GetType() == ITEM) + { + pItem = (CListItem<T,G>*)(*iter); + if(pItem->GetItemData() == Entry) + { + if(m_pRoot && m_pRoot->GetPosition() == *iter) + { + CListEntry<T,G> *pPosition = (*iter)->GetPreviousEntry(); + if(!pPosition) + pPosition = (*iter)->GetNextEntry(); + m_pRoot->SetPosition(pPosition); + } + delete *iter; + + m_Entrys.erase(iter); + m_pRoot->UpdateEntryCount(); + return; + } + } + iter++; + } + } + + CListContainer<T,G> *GetGroup(G Group) + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListContainer<T,G> *pContainer = NULL; + while(iter != m_Entrys.end()) + { + if((*iter)->GetType() == CONTAINER) + { + pContainer = (CListContainer<T,G>*)(*iter); + if(pContainer->GetGroupData() == Group) + return pContainer; + } + iter++; + } + return NULL; + } + + G GetGroupData() + { + return m_GroupData; + } + + bool IsOpen() + { + return m_bOpen; + } + + void ToggleOpen() + { + m_bOpen = !m_bOpen; + + if (m_pRoot) { + m_pRoot->UpdateEntryCount(); + m_pRoot->SetPosition(this); + } + } + + void SetOpen(bool bOpen = true) + { + if(bOpen == m_bOpen) + return; + + m_bOpen = bOpen; + + if (m_pRoot) { + m_pRoot->UpdateEntryCount(); + m_pRoot->SetPosition(this); + } + } + + void CollapseAll() + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListContainer<T,G>* pContainer = NULL; + while(iter != m_Entrys.end()) + { + if((*iter)->GetType() == CONTAINER) + { + pContainer = (CListContainer<T,G>*)(*iter); + pContainer->CollapseAll(); + pContainer->SetOpen(false); + } + iter++; + } + } + + void ExpandAll() + { + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + CListContainer<T,G>* pContainer = NULL; + while(iter != m_Entrys.end()) + { + if((*iter)->GetType() == CONTAINER) + { + pContainer = (CListContainer<T,G>*)(*iter); + pContainer->ExpandAll(); + pContainer->SetOpen(true); + } + iter++; + } + } + + void UpdateEntryCount() + { + m_iEntryCount = 0; + + int iIndex = GetIndex()+1; + + if(!IsOpen()) + return; + + list< CListEntry<T,G>* >::iterator iter = m_Entrys.begin(); + while(iter != m_Entrys.end()) + { + (*iter)->SetIndex(iIndex+m_iEntryCount); + (*iter)->UpdateEntryCount(); + m_iEntryCount += 1+(*iter)->GetEntryCount(); + + iter++; + } + + if(GetType() == ROOT) + { + if(GetPosition() == NULL && !m_Entrys.empty()) + SetPosition(*m_Entrys.begin()); + else + SetPosition(GetPosition()); + } + } + + template<class _Pr3> + void sort(_Pr3 _Pred) { + m_Entrys.sort(_Pred); + UpdateEntryCount(); + m_pRoot->SetPosition(m_pRoot->GetPosition()); + } + +private: + typename list< CListEntry<T,G>* > m_Entrys; + G m_GroupData; + bool m_bOpen; +}; + + +template <class T, class G = tstring> class CLCDList : public CLCDTextObject, public CListContainer<T,G> +{ +friend CListContainer<T,G>; +friend CListItem<T,G>; +public: + //************************************************************************ + // Constructor + //************************************************************************ + CLCDList() : CListContainer<T,G>(NULL) + { + m_pScrollbar = NULL; + m_iIndention = 10; + m_iColumns = 1; + m_bDrawTreeLines = true; + m_iEntryHeight = 10; + } + + //************************************************************************ + // Destructor + //************************************************************************ + ~CLCDList() + { + } + + //************************************************************************ + // Initializes the list + //************************************************************************ + bool Initialize() + { + if(!CLCDTextObject::Initialize()) + return false; + + return true; + } + + //************************************************************************ + // Deinitializes the list + //************************************************************************ + bool Shutdown() + { + if(!CLCDTextObject::Shutdown()) + return false; + + Clear(); + + return true; + } + + //************************************************************************ + // updates the list + //************************************************************************ + bool Update() + { + if(!CLCDTextObject::Update()) + return false; + + return true; + } + + //************************************************************************ + // draws the list + //************************************************************************ + bool Draw(CLCDGfx *pGfx) + { + if(!CLCDTextObject::Draw(pGfx)) + return false; + + SelectObject(pGfx->GetHDC(),m_hFont); + + POINT ptPrevViewportOrg = { 0, 0 }; + HRGN hRgn = NULL; + int iHeight = 0,iLimit=0; + int iYOffset = 0, iXOffset=0; + int iColWidth = (GetWidth()- (m_iColumns-1)*3)/m_iColumns; + int iSpace = GetHeight() - (GetHeight()/m_iEntryHeight)*m_iEntryHeight; + int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns; + + int iEntriesDrawn = 0; + CListEntry<T,G> *pPosition = m_Position; + + // if nothing is selected, skip drawing + if(pPosition == NULL) + return true; + + bool bDrawGroup = false; + bool bSelected = false; + + // calculate the start offset + + if(m_iStartIndex < pPosition->GetIndex()) + { + while(pPosition && pPosition->GetIndex() != m_iStartIndex) + pPosition = pPosition->GetPreviousEntry(); + } + + if(m_iStartIndex > 0 && pPosition->GetIndex() > 0) + pPosition = pPosition->GetPreviousEntry(); + + for(int iCol = 0;iCol<m_iColumns;iCol++) + { + iHeight = 0; + if(iCol == 0) + { + if(pPosition->GetIndex() < m_iStartIndex) + iHeight -= m_iEntryHeight-iSpace; + else if(GetEntryCount() >= (iPerPage/m_iColumns) +1) + iHeight = iSpace; + } + + // bottom selection + while(pPosition != NULL ) + { + iYOffset = iHeight; + + bSelected = m_Position == pPosition; + bDrawGroup = pPosition->GetType() == CONTAINER; + + // ~~~~~~~~~~~~~~~~~~~~~~ + // Draw tree lines + // ~~~~~~~~~~~~~~~~~~~~~~ + + // set the clip region for the entry + int iClipHeight = m_iEntryHeight; + if(GetOrigin().y+iYOffset+iClipHeight > GetOrigin().y + GetHeight()) + iClipHeight = GetHeight() - iYOffset; + + pGfx->SetClipRegion(GetOrigin().x+iXOffset,GetOrigin().y+iYOffset, + iColWidth, iClipHeight); + + // offset the control at its origin so entry use (0,0) + SetViewportOrgEx(pGfx->GetHDC(), + GetOrigin().x+iXOffset, + GetOrigin().y+iYOffset, + &ptPrevViewportOrg); + + if(m_bDrawTreeLines) + { + for(int i=1;i<pPosition->GetLevel();i++) + { + if(i == pPosition->GetLevel()-1) + { + // - + pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight/2,i*m_iIndention,m_iEntryHeight/2); + // | + if(pPosition == ((CListContainer<T,G>*)pPosition->GetParent())->GetLastOwnEntry()) + pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight/2); + // | + // | + else + pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight); + } + else + { + CListEntry<T,G> *pPosition2 = pPosition; + for(int j = pPosition->GetLevel();j>i+1;j--) + pPosition2 = pPosition2->GetParent(); + // | + // | + if(pPosition2 != ((CListContainer<T,G>*)pPosition2->GetParent())->GetLastOwnEntry()) + pGfx->DrawLine((i-1)*m_iIndention+m_iIndention/2,0,(i-1)*m_iIndention+m_iIndention/2,m_iEntryHeight); + } + } + } + + // ~~~~~~~~~~~~~~~~~~~~~~ + // Draw the entry + // ~~~~~~~~~~~~~~~~~~~~~~ + pGfx->SetClipRegion(GetOrigin().x+(pPosition->GetLevel()-1)*m_iIndention+iXOffset, + GetOrigin().y+iYOffset, + iColWidth-(pPosition->GetLevel()-1)*m_iIndention, + iClipHeight); + // set the offset + SetViewportOrgEx(pGfx->GetHDC(), + GetOrigin().x+(pPosition->GetLevel()-1)*m_iIndention+iXOffset, + GetOrigin().y+iYOffset, + &ptPrevViewportOrg); + + // draw the entry + if(!bDrawGroup) + DrawEntry(pGfx,((CListItem<T,G>*)pPosition)->GetItemData(),bSelected); + else + // draw the group + DrawGroup(pGfx,((CListContainer<T,G>*)pPosition)->GetGroupData(),((CListContainer<T,G>*)pPosition)->IsOpen(),bSelected); + + // ~~~~~~~~~~~~~~~~~~~~~~ + + if(pPosition->GetIndex() >= m_iStartIndex && iHeight + m_iEntryHeight <= GetHeight()) + iEntriesDrawn++; + + iHeight += m_iEntryHeight; + pPosition = pPosition->GetNextEntry(); + + if(iHeight >= GetHeight()) + break; + } + if(iCol != m_iColumns-1) + { + pGfx->SetClipRegion(GetOrigin().x, + GetOrigin().y, + GetWidth(), + GetHeight()); + // set the offset + SetViewportOrgEx(pGfx->GetHDC(), + GetOrigin().x, + GetOrigin().y, + &ptPrevViewportOrg); + + pGfx->DrawLine(iCol*3 + iColWidth + 1,0,iCol*3 + iColWidth + 1,GetHeight()); + } + iXOffset += 3 + iColWidth; + } + + if(m_pScrollbar) + { + m_pScrollbar->ScrollTo(m_iStartIndex); + m_pScrollbar->SetSliderSize(iEntriesDrawn); + } + return true; + } + + + void SetPosition(CListEntry<T,G> *pEntry) + { + CListContainer<T,G>::SetPosition(pEntry); + + if(pEntry == NULL) + return; + + int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns; + m_iStartIndex = pEntry->GetIndex(); + if(m_iStartIndex + (iPerPage-1) > GetEntryCount()-1) + m_iStartIndex = (GetEntryCount()-1)-(iPerPage-1); + if(m_iStartIndex < 0) + m_iStartIndex = 0; + } + + //************************************************************************ + // scrolls up + //************************************************************************ + bool ScrollUp() + { + if(m_Position != NULL) + { + CListEntry<T,G> *pEntry = m_Position->GetPreviousEntry(); + if(pEntry != NULL) + { + m_Position = pEntry; + + int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns; + if(m_Position->GetIndex() < m_iStartIndex) + m_iStartIndex--; + return true; + } + } + return false; + } + + //************************************************************************ + // scrolls down + //************************************************************************ + bool ScrollDown() + { + if(m_Position != NULL) + { + CListEntry<T,G> *pEntry = m_Position->GetNextEntry(); + if(pEntry != NULL) + { + m_Position = pEntry; + + int iPerPage = (GetHeight()/m_iEntryHeight)*m_iColumns; + if(m_Position->GetIndex() >= m_iStartIndex + iPerPage) + m_iStartIndex++; + return true; + } + } + return false; + } + + //************************************************************************ + // returns the selected list entry + //************************************************************************ + CListEntry<T,G> *GetSelectedEntry() + { + return m_Position; + } + + //************************************************************************ + // associates a scrollbar with the list + //************************************************************************ + void SetScrollbar(CLCDBar *pScrollbar) + { + m_pScrollbar = pScrollbar; + if(m_pScrollbar) + { + m_pScrollbar->SetRange(0,m_iEntryCount-1); + m_pScrollbar->ScrollTo(m_Position != NULL?m_Position->GetIndex():0); + + m_pScrollbar->SetAlignment(TOP); + } + } + + //************************************************************************ + // sets the group indention in pixels + //************************************************************************ + void SetIndention(int iIndention) + { + m_iIndention = iIndention; + } + + //************************************************************************ + // sets the lists entry height + //************************************************************************ + void SetEntryHeight(int iEntryHeight) + { + m_iEntryHeight = iEntryHeight; + } + + //************************************************************************ + // returns the lists entry height + //************************************************************************ + int GetEntryHeight() + { + return m_iEntryHeight; + } + + //************************************************************************ + // enables/disables drawing of treelines + //************************************************************************ + void SetDrawTreeLines(bool bDraw) + { + m_bDrawTreeLines = bDraw; + } + + //************************************************************************ + // sets the amount of columns the list uses + //************************************************************************ + void SetColumns(int iColumns) + { + if(m_iColumns == iColumns) + return; + m_iColumns = iColumns; + SetPosition(GetPosition()); + } +protected: + //************************************************************************ + // called when the lists size has changed + //************************************************************************ + void OnSizeChanged() + { + SetPosition(GetPosition()); + } + + //************************************************************************ + // updates the list's entry count + //************************************************************************ + void UpdateEntryCount() + { + CListContainer<T,G>::UpdateEntryCount(); + if(m_pScrollbar) + { + m_pScrollbar->SetRange(0,m_iEntryCount-1); + if(GetPosition() != NULL) + m_pScrollbar->ScrollTo(GetPosition()->GetIndex()); + } + } + + //************************************************************************ + // Called to delete the specified entry + //************************************************************************ + virtual void DeleteEntry(T Entry) + { + + } + + //************************************************************************ + // Called to delete the specified group + //************************************************************************ + virtual void DeleteGroup(G Group) + { + + } + + //************************************************************************ + // Called to draw the specified entry + //************************************************************************ + virtual void DrawEntry(CLCDGfx *pGfx,T Entry, bool bSelected) + { + } + + //************************************************************************ + // Called to draw the specified entry + //************************************************************************ + virtual void DrawGroup(CLCDGfx *pGfx,G Group, bool bOpen, bool bSelected) + { + } + + + +protected: + int m_iStartIndex; + int m_iColumns; + + bool m_bDrawTreeLines; + int m_iIndention; + int m_iEntryHeight; + CLCDBar *m_pScrollbar; +}; + #endif
\ No newline at end of file |