| // Copyright 2014 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "../../include/pdfwindow/PDFWindow.h" | |
| #include "../../include/pdfwindow/PWL_Wnd.h" | |
| #include "../../include/pdfwindow/PWL_ListCtrl.h" | |
| #include "../../include/pdfwindow/PWL_IconList.h" | |
| #include "../../include/pdfwindow/PWL_Utils.h" | |
| #include "../../include/pdfwindow/PWL_ScrollBar.h" | |
| #include "../../include/pdfwindow/PWL_Label.h" | |
| #define PWL_IconList_ITEM_ICON_LEFTMARGIN 10.0f | |
| #define PWL_IconList_ITEM_WIDTH 20.0f | |
| #define PWL_IconList_ITEM_HEIGHT 20.0f | |
| #define PWL_IconList_ITEM_SPACE 4.0f | |
| /* ------------------ CPWL_IconList_Item ------------------- */ | |
| CPWL_IconList_Item::CPWL_IconList_Item() : | |
| m_nIconIndex(-1), | |
| m_pData(NULL), | |
| m_bSelected(FALSE), | |
| m_pText(NULL) | |
| { | |
| } | |
| CPWL_IconList_Item::~CPWL_IconList_Item() | |
| { | |
| } | |
| CFX_ByteString CPWL_IconList_Item::GetClassName() const | |
| { | |
| return "CPWL_IconList_Item"; | |
| } | |
| FX_FLOAT CPWL_IconList_Item::GetItemHeight(FX_FLOAT fLimitWidth) | |
| { | |
| return PWL_IconList_ITEM_HEIGHT; | |
| } | |
| void CPWL_IconList_Item::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device) | |
| { | |
| CPDF_Rect rcClient = GetClientRect(); | |
| if (m_bSelected) | |
| { | |
| if (this->IsEnabled()) | |
| { | |
| CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, | |
| CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR,this->GetTransparency())); | |
| } | |
| else | |
| { | |
| CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, | |
| CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR,this->GetTransparency())); | |
| } | |
| } | |
| CPDF_Rect rcIcon = rcClient; | |
| rcIcon.left += PWL_IconList_ITEM_ICON_LEFTMARGIN; | |
| rcIcon.right = rcIcon.left + PWL_IconList_ITEM_WIDTH; | |
| CPWL_Utils::DrawIconAppStream(pDevice, pUser2Device, m_nIconIndex, rcIcon, | |
| m_crIcon, m_pText->GetTextColor(), this->GetTransparency()); | |
| } | |
| void CPWL_IconList_Item::SetSelect(FX_BOOL bSelected) | |
| { | |
| m_bSelected = bSelected; | |
| if (bSelected) | |
| m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR); | |
| else | |
| m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR); | |
| } | |
| FX_BOOL CPWL_IconList_Item::IsSelected() const | |
| { | |
| return m_bSelected; | |
| } | |
| void CPWL_IconList_Item::CreateChildWnd(const PWL_CREATEPARAM & cp) | |
| { | |
| m_pText = new CPWL_Label; | |
| PWL_CREATEPARAM lcp = cp; | |
| lcp.pParentWnd = this; | |
| lcp.dwFlags = PWS_CHILD | PWS_VISIBLE | PES_LEFT | PES_CENTER; | |
| lcp.sTextColor = PWL_DEFAULT_BLACKCOLOR; | |
| lcp.fFontSize = 12; | |
| m_pText->Create(lcp); | |
| } | |
| void CPWL_IconList_Item::SetData(void* pData) | |
| { | |
| m_pData = pData; | |
| } | |
| void CPWL_IconList_Item::SetIcon(FX_INT32 nIconIndex) | |
| { | |
| m_nIconIndex = nIconIndex; | |
| } | |
| void CPWL_IconList_Item::SetText(const CFX_WideString& str) | |
| { | |
| m_pText->SetText(str); | |
| } | |
| CFX_WideString CPWL_IconList_Item::GetText() const | |
| { | |
| return m_pText->GetText(); | |
| } | |
| void CPWL_IconList_Item::RePosChildWnd() | |
| { | |
| CPDF_Rect rcClient = GetClientRect(); | |
| rcClient.left += (PWL_IconList_ITEM_ICON_LEFTMARGIN + PWL_IconList_ITEM_WIDTH + PWL_IconList_ITEM_ICON_LEFTMARGIN); | |
| m_pText->Move(rcClient, TRUE, FALSE); | |
| } | |
| void CPWL_IconList_Item::SetIconFillColor(const CPWL_Color& color) | |
| { | |
| m_crIcon = color; | |
| } | |
| void CPWL_IconList_Item::OnEnabled() | |
| { | |
| if (m_bSelected) | |
| m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR); | |
| else | |
| m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR); | |
| this->InvalidateRect(); | |
| } | |
| void CPWL_IconList_Item::OnDisabled() | |
| { | |
| m_pText->SetTextColor(PWL_DEFAULT_HEAVYGRAYCOLOR); | |
| this->InvalidateRect(); | |
| } | |
| /* ----------------- CPWL_IconList_Content ----------------- */ | |
| CPWL_IconList_Content::CPWL_IconList_Content(FX_INT32 nListCount) : | |
| m_nSelectIndex(-1), | |
| m_pNotify(NULL), | |
| m_bEnableNotify(TRUE), | |
| m_bMouseDown(FALSE), | |
| m_nListCount(nListCount) | |
| { | |
| } | |
| CPWL_IconList_Content::~CPWL_IconList_Content() | |
| { | |
| } | |
| void CPWL_IconList_Content::CreateChildWnd(const PWL_CREATEPARAM & cp) | |
| { | |
| for (FX_INT32 i=0; i<m_nListCount; i++) | |
| { | |
| CPWL_IconList_Item* pNewItem = new CPWL_IconList_Item(); | |
| PWL_CREATEPARAM icp = cp; | |
| icp.pParentWnd = this; | |
| icp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_NOREFRESHCLIP; | |
| pNewItem->Create(icp); | |
| } | |
| this->SetItemSpace(PWL_IconList_ITEM_SPACE); | |
| this->ResetContent(0); | |
| if (CPWL_Wnd * pParent = this->GetParentWindow()) | |
| { | |
| CPDF_Rect rcScroll = this->GetScrollArea(); | |
| this->GetScrollPos(); | |
| PWL_SCROLL_INFO sInfo; | |
| sInfo.fContentMin = rcScroll.bottom; | |
| sInfo.fContentMax = rcScroll.top; | |
| sInfo.fPlateWidth = GetClientRect().Height(); | |
| sInfo.fSmallStep = 13.0f; | |
| sInfo.fBigStep = sInfo.fPlateWidth; | |
| pParent->OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (FX_INTPTR)&sInfo); | |
| } | |
| } | |
| FX_BOOL CPWL_IconList_Content::OnLButtonDown(const CPDF_Point & point) | |
| { | |
| SetFocus(); | |
| SetCapture(); | |
| m_bMouseDown = TRUE; | |
| FX_INT32 nItemIndex = FindItemIndex(point); | |
| SetSelect(nItemIndex); | |
| ScrollToItem(nItemIndex); | |
| return TRUE; | |
| } | |
| FX_BOOL CPWL_IconList_Content::OnLButtonUp(const CPDF_Point & point) | |
| { | |
| m_bMouseDown = FALSE; | |
| ReleaseCapture(); | |
| return TRUE; | |
| } | |
| FX_BOOL CPWL_IconList_Content::OnMouseMove(const CPDF_Point & point) | |
| { | |
| if (m_bMouseDown) | |
| { | |
| FX_INT32 nItemIndex = FindItemIndex(point); | |
| SetSelect(nItemIndex); | |
| ScrollToItem(nItemIndex); | |
| } | |
| return TRUE; | |
| } | |
| FX_BOOL CPWL_IconList_Content::OnKeyDown(FX_WORD nChar) | |
| { | |
| switch (nChar) | |
| { | |
| case FWL_VKEY_Up: | |
| if (m_nSelectIndex > 0) | |
| { | |
| FX_INT32 nItemIndex = m_nSelectIndex - 1; | |
| SetSelect(nItemIndex); | |
| ScrollToItem(nItemIndex); | |
| } | |
| return TRUE; | |
| case FWL_VKEY_Down: | |
| if (m_nSelectIndex < m_nListCount-1) | |
| { | |
| FX_INT32 nItemIndex = m_nSelectIndex + 1; | |
| SetSelect(nItemIndex); | |
| ScrollToItem(nItemIndex); | |
| } | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| FX_INT32 CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point) | |
| { | |
| FX_INT32 nIndex = 0; | |
| for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++) | |
| { | |
| if (CPWL_Wnd * pChild = m_aChildren.GetAt(i)) | |
| { | |
| CPDF_Rect rcWnd = pChild->ChildToParent(pChild->GetWindowRect()); | |
| if (point.y < rcWnd.top) | |
| { | |
| nIndex = i; | |
| } | |
| } | |
| } | |
| return nIndex; | |
| } | |
| void CPWL_IconList_Content::ScrollToItem(FX_INT32 nItemIndex) | |
| { | |
| CPDF_Rect rcClient = GetClientRect(); | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| { | |
| CPDF_Rect rcOrigin = pItem->GetWindowRect(); | |
| CPDF_Rect rcWnd = pItem->ChildToParent(rcOrigin); | |
| if (!(rcWnd.bottom > rcClient.bottom && rcWnd.top < rcClient.top)) | |
| { | |
| CPDF_Point ptScroll = GetScrollPos(); | |
| if (rcWnd.top > rcClient.top) | |
| { | |
| ptScroll.y = rcOrigin.top; | |
| } | |
| else if (rcWnd.bottom < rcClient.bottom) | |
| { | |
| ptScroll.y = rcOrigin.bottom + rcClient.Height(); | |
| } | |
| this->SetScrollPos(ptScroll); | |
| this->ResetFace(); | |
| this->InvalidateRect(); | |
| if (CPWL_Wnd* pParent = this->GetParentWindow()) | |
| { | |
| pParent->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptScroll.y); | |
| } | |
| } | |
| } | |
| } | |
| void CPWL_IconList_Content::SetSelect(FX_INT32 nIndex) | |
| { | |
| if (m_nSelectIndex != nIndex) | |
| { | |
| SelectItem(m_nSelectIndex, FALSE); | |
| SelectItem(nIndex, TRUE); | |
| m_nSelectIndex = nIndex; | |
| if (IPWL_IconList_Notify* pNotify = GetNotify()) | |
| pNotify->OnNoteListSelChanged(nIndex); | |
| } | |
| } | |
| FX_INT32 CPWL_IconList_Content::GetSelect() const | |
| { | |
| return m_nSelectIndex; | |
| } | |
| IPWL_IconList_Notify* CPWL_IconList_Content::GetNotify() const | |
| { | |
| if (m_bEnableNotify) | |
| return m_pNotify; | |
| return NULL; | |
| } | |
| void CPWL_IconList_Content::SetNotify(IPWL_IconList_Notify* pNotify) | |
| { | |
| m_pNotify = pNotify; | |
| } | |
| void CPWL_IconList_Content::EnableNotify(FX_BOOL bNotify) | |
| { | |
| m_bEnableNotify = bNotify; | |
| } | |
| void CPWL_IconList_Content::SelectItem(FX_INT32 nItemIndex, FX_BOOL bSelect) | |
| { | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| { | |
| pItem->SetSelect(bSelect); | |
| pItem->InvalidateRect(); | |
| } | |
| } | |
| CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(FX_INT32 nItemIndex) const | |
| { | |
| if (nItemIndex >= 0 && nItemIndex<m_aChildren.GetSize()) | |
| { | |
| if (CPWL_Wnd * pChild = m_aChildren.GetAt(nItemIndex)) | |
| { | |
| if (pChild->GetClassName() == "CPWL_IconList_Item") | |
| { | |
| return (CPWL_IconList_Item*)pChild; | |
| } | |
| } | |
| } | |
| return NULL; | |
| } | |
| void CPWL_IconList_Content::SetListData(FX_INT32 nItemIndex, void* pData) | |
| { | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| pItem->SetData(pData); | |
| } | |
| void CPWL_IconList_Content::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex) | |
| { | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| pItem->SetIcon(nIconIndex); | |
| } | |
| void CPWL_IconList_Content::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str) | |
| { | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| pItem->SetText(str); | |
| } | |
| CFX_WideString CPWL_IconList_Content::GetListString(FX_INT32 nItemIndex) const | |
| { | |
| if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) | |
| return pItem->GetText(); | |
| return L""; | |
| } | |
| void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color) | |
| { | |
| for (FX_INT32 i=0,sz=m_aChildren.GetSize(); i<sz; i++) | |
| { | |
| if (CPWL_Wnd * pChild = m_aChildren.GetAt(i)) | |
| { | |
| if (pChild->GetClassName() == "CPWL_IconList_Item") | |
| { | |
| CPWL_IconList_Item* pItem = (CPWL_IconList_Item*)pChild; | |
| pItem->SetIconFillColor(color); | |
| pItem->InvalidateRect(); | |
| } | |
| } | |
| } | |
| } | |
| /* -------------------- CPWL_IconList --------------------- */ | |
| CPWL_IconList::CPWL_IconList(FX_INT32 nListCount) : | |
| m_pListContent(NULL), | |
| m_nListCount(nListCount) | |
| { | |
| } | |
| CPWL_IconList::~CPWL_IconList() | |
| { | |
| } | |
| void CPWL_IconList::RePosChildWnd() | |
| { | |
| CPWL_Wnd::RePosChildWnd(); | |
| if (m_pListContent) | |
| m_pListContent->Move(GetClientRect(), TRUE, FALSE); | |
| } | |
| void CPWL_IconList::CreateChildWnd(const PWL_CREATEPARAM & cp) | |
| { | |
| m_pListContent = new CPWL_IconList_Content(m_nListCount); | |
| PWL_CREATEPARAM ccp = cp; | |
| ccp.pParentWnd = this; | |
| ccp.dwFlags = PWS_CHILD | PWS_VISIBLE; | |
| m_pListContent->Create(ccp); | |
| } | |
| void CPWL_IconList::OnCreated() | |
| { | |
| if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) | |
| { | |
| pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT); | |
| pScrollBar->SetTransparency(255); | |
| pScrollBar->SetNotifyForever(TRUE); | |
| } | |
| } | |
| void CPWL_IconList::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, FX_INTPTR wParam, FX_INTPTR lParam) | |
| { | |
| CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam); | |
| if (wParam == SBT_VSCROLL) | |
| { | |
| switch (msg) | |
| { | |
| case PNM_SETSCROLLINFO: | |
| if (PWL_SCROLL_INFO* pInfo = (PWL_SCROLL_INFO*)lParam) | |
| { | |
| if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) | |
| { | |
| if (pInfo->fContentMax - pInfo->fContentMin > pInfo->fPlateWidth) | |
| { | |
| if (!pScrollBar->IsVisible()) | |
| { | |
| pScrollBar->SetVisible(TRUE); | |
| RePosChildWnd(); | |
| } | |
| else | |
| { | |
| } | |
| } | |
| else | |
| { | |
| if (pScrollBar->IsVisible()) | |
| { | |
| pScrollBar->SetVisible(FALSE); | |
| RePosChildWnd(); | |
| } | |
| if (m_pListContent) | |
| m_pListContent->SetScrollPos(CPDF_Point(0.0f,0.0f)); | |
| } | |
| pScrollBar->OnNotify(pWnd,PNM_SETSCROLLINFO,wParam,lParam); | |
| } | |
| } | |
| return; | |
| case PNM_SCROLLWINDOW: | |
| if (m_pListContent) | |
| { | |
| m_pListContent->SetScrollPos(CPDF_Point(0.0f, *(FX_FLOAT*)lParam)); | |
| m_pListContent->ResetFace(); | |
| m_pListContent->InvalidateRect(NULL); | |
| } | |
| return; | |
| case PNM_SETSCROLLPOS: | |
| if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) | |
| pScrollBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam); | |
| return; | |
| } | |
| } | |
| } | |
| void CPWL_IconList::SetSelect(FX_INT32 nIndex) | |
| { | |
| m_pListContent->SetSelect(nIndex); | |
| } | |
| void CPWL_IconList::SetTopItem(FX_INT32 nIndex) | |
| { | |
| m_pListContent->ScrollToItem(nIndex); | |
| } | |
| FX_INT32 CPWL_IconList::GetSelect() const | |
| { | |
| return m_pListContent->GetSelect(); | |
| } | |
| void CPWL_IconList::SetNotify(IPWL_IconList_Notify* pNotify) | |
| { | |
| m_pListContent->SetNotify(pNotify); | |
| } | |
| void CPWL_IconList::EnableNotify(FX_BOOL bNotify) | |
| { | |
| m_pListContent->EnableNotify(bNotify); | |
| } | |
| void CPWL_IconList::SetListData(FX_INT32 nItemIndex, void* pData) | |
| { | |
| m_pListContent->SetListData(nItemIndex, pData); | |
| } | |
| void CPWL_IconList::SetListIcon(FX_INT32 nItemIndex, FX_INT32 nIconIndex) | |
| { | |
| m_pListContent->SetListIcon(nItemIndex, nIconIndex); | |
| } | |
| void CPWL_IconList::SetListString(FX_INT32 nItemIndex, const CFX_WideString& str) | |
| { | |
| m_pListContent->SetListString(nItemIndex, str); | |
| } | |
| CFX_WideString CPWL_IconList::GetListString(FX_INT32 nItemIndex) const | |
| { | |
| return m_pListContent->GetListString(nItemIndex); | |
| } | |
| void CPWL_IconList::SetIconFillColor(const CPWL_Color& color) | |
| { | |
| m_pListContent->SetIconFillColor(color); | |
| } | |
| FX_BOOL CPWL_IconList::OnMouseWheel(short zDelta, const CPDF_Point & point) | |
| { | |
| CPDF_Point ptScroll = m_pListContent->GetScrollPos(); | |
| CPDF_Rect rcScroll = m_pListContent->GetScrollArea(); | |
| CPDF_Rect rcContents = m_pListContent->GetClientRect(); | |
| if (rcScroll.top - rcScroll.bottom > rcContents.Height()) | |
| { | |
| CPDF_Point ptNew = ptScroll; | |
| if (zDelta > 0) | |
| ptNew.y += 30; | |
| else | |
| ptNew.y -= 30; | |
| if (ptNew.y > rcScroll.top) | |
| ptNew.y = rcScroll.top; | |
| if (ptNew.y < rcScroll.bottom + rcContents.Height()) | |
| ptNew.y = rcScroll.bottom + rcContents.Height(); | |
| if (ptNew.y < rcScroll.bottom) | |
| ptNew.y = rcScroll.bottom; | |
| if (ptNew.y != ptScroll.y) | |
| { | |
| m_pListContent->SetScrollPos(ptNew); | |
| m_pListContent->ResetFace(); | |
| m_pListContent->InvalidateRect(NULL); | |
| if (CPWL_ScrollBar* pScrollBar = this->GetVScrollBar()) | |
| pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (FX_INTPTR)&ptNew.y); | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |