// 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 (IsEnabled()) { CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR, GetTransparency())); } else { CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient, CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR, 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(), 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(int32_t nIconIndex) { m_nIconIndex = nIconIndex; } void CPWL_IconList_Item::SetText(const CFX_WideString& str) { m_pText->SetText(str.c_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); InvalidateRect(); } void CPWL_IconList_Item::OnDisabled() { m_pText->SetTextColor(PWL_DEFAULT_HEAVYGRAYCOLOR); InvalidateRect(); } /* ----------------- CPWL_IconList_Content ----------------- */ CPWL_IconList_Content::CPWL_IconList_Content(int32_t 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 (int32_t 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); } SetItemSpace(PWL_IconList_ITEM_SPACE); ResetContent(0); if (CPWL_Wnd * pParent = GetParentWindow()) { CPDF_Rect rcScroll = GetScrollArea(); 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, (intptr_t)&sInfo); } } FX_BOOL CPWL_IconList_Content::OnLButtonDown(const CPDF_Point & point, FX_DWORD nFlag) { SetFocus(); SetCapture(); m_bMouseDown = TRUE; int32_t nItemIndex = FindItemIndex(point); SetSelect(nItemIndex); ScrollToItem(nItemIndex); return TRUE; } FX_BOOL CPWL_IconList_Content::OnLButtonUp(const CPDF_Point & point, FX_DWORD nFlag) { m_bMouseDown = FALSE; ReleaseCapture(); return TRUE; } FX_BOOL CPWL_IconList_Content::OnMouseMove(const CPDF_Point & point, FX_DWORD nFlag) { if (m_bMouseDown) { int32_t nItemIndex = FindItemIndex(point); SetSelect(nItemIndex); ScrollToItem(nItemIndex); } return TRUE; } FX_BOOL CPWL_IconList_Content::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) { switch (nChar) { case FWL_VKEY_Up: if (m_nSelectIndex > 0) { int32_t nItemIndex = m_nSelectIndex - 1; SetSelect(nItemIndex); ScrollToItem(nItemIndex); } return TRUE; case FWL_VKEY_Down: if (m_nSelectIndex < m_nListCount-1) { int32_t nItemIndex = m_nSelectIndex + 1; SetSelect(nItemIndex); ScrollToItem(nItemIndex); } return TRUE; } return FALSE; } int32_t CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point) { int32_t nIndex = 0; for (int32_t 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(int32_t 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(); } SetScrollPos(ptScroll); ResetFace(); InvalidateRect(); if (CPWL_Wnd* pParent = GetParentWindow()) { pParent->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&ptScroll.y); } } } } void CPWL_IconList_Content::SetSelect(int32_t nIndex) { if (m_nSelectIndex != nIndex) { SelectItem(m_nSelectIndex, FALSE); SelectItem(nIndex, TRUE); m_nSelectIndex = nIndex; if (IPWL_IconList_Notify* pNotify = GetNotify()) pNotify->OnNoteListSelChanged(nIndex); } } int32_t 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(int32_t nItemIndex, FX_BOOL bSelect) { if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) { pItem->SetSelect(bSelect); pItem->InvalidateRect(); } } CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(int32_t 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(int32_t nItemIndex, void* pData) { if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) pItem->SetData(pData); } void CPWL_IconList_Content::SetListIcon(int32_t nItemIndex, int32_t nIconIndex) { if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) pItem->SetIcon(nIconIndex); } void CPWL_IconList_Content::SetListString(int32_t nItemIndex, const CFX_WideString& str) { if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) pItem->SetText(str); } CFX_WideString CPWL_IconList_Content::GetListString(int32_t nItemIndex) const { if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) return pItem->GetText(); return L""; } void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color) { for (int32_t 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(int32_t 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 = GetVScrollBar()) { pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT); pScrollBar->SetTransparency(255); pScrollBar->SetNotifyForever(TRUE); } } void CPWL_IconList::OnNotify(CPWL_Wnd* pWnd, FX_DWORD msg, intptr_t wParam, intptr_t 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 = 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 = GetVScrollBar()) pScrollBar->OnNotify(pWnd,PNM_SETSCROLLPOS,wParam,lParam); return; } } } void CPWL_IconList::SetSelect(int32_t nIndex) { m_pListContent->SetSelect(nIndex); } void CPWL_IconList::SetTopItem(int32_t nIndex) { m_pListContent->ScrollToItem(nIndex); } int32_t 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(int32_t nItemIndex, void* pData) { m_pListContent->SetListData(nItemIndex, pData); } void CPWL_IconList::SetListIcon(int32_t nItemIndex, int32_t nIconIndex) { m_pListContent->SetListIcon(nItemIndex, nIconIndex); } void CPWL_IconList::SetListString(int32_t nItemIndex, const CFX_WideString& str) { m_pListContent->SetListString(nItemIndex, str); } CFX_WideString CPWL_IconList::GetListString(int32_t 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, FX_DWORD nFlag) { 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 = GetVScrollBar()) pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL, (intptr_t)&ptNew.y); return TRUE; } } return FALSE; }