Home | History | Annotate | Download | only in pdfwindow
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "fpdfsdk/include/pdfwindow/PWL_IconList.h"
      8 
      9 #include "fpdfsdk/include/pdfwindow/PWL_Label.h"
     10 #include "fpdfsdk/include/pdfwindow/PWL_ListCtrl.h"
     11 #include "fpdfsdk/include/pdfwindow/PWL_ScrollBar.h"
     12 #include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
     13 #include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"
     14 #include "public/fpdf_fwlevent.h"
     15 
     16 #define PWL_IconList_ITEM_ICON_LEFTMARGIN 10.0f
     17 #define PWL_IconList_ITEM_WIDTH 20.0f
     18 #define PWL_IconList_ITEM_HEIGHT 20.0f
     19 #define PWL_IconList_ITEM_SPACE 4.0f
     20 
     21 CPWL_IconList_Item::CPWL_IconList_Item()
     22     : m_nIconIndex(-1), m_pData(NULL), m_bSelected(FALSE), m_pText(NULL) {}
     23 
     24 CPWL_IconList_Item::~CPWL_IconList_Item() {}
     25 
     26 CFX_ByteString CPWL_IconList_Item::GetClassName() const {
     27   return "CPWL_IconList_Item";
     28 }
     29 
     30 FX_FLOAT CPWL_IconList_Item::GetItemHeight(FX_FLOAT fLimitWidth) {
     31   return PWL_IconList_ITEM_HEIGHT;
     32 }
     33 
     34 void CPWL_IconList_Item::DrawThisAppearance(CFX_RenderDevice* pDevice,
     35                                             CFX_Matrix* pUser2Device) {
     36   CPDF_Rect rcClient = GetClientRect();
     37 
     38   if (m_bSelected) {
     39     if (IsEnabled()) {
     40       CPWL_Utils::DrawFillRect(
     41           pDevice, pUser2Device, rcClient,
     42           CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_SELBACKCOLOR,
     43                                         GetTransparency()));
     44     } else {
     45       CPWL_Utils::DrawFillRect(
     46           pDevice, pUser2Device, rcClient,
     47           CPWL_Utils::PWLColorToFXColor(PWL_DEFAULT_LIGHTGRAYCOLOR,
     48                                         GetTransparency()));
     49     }
     50   }
     51 
     52   CPDF_Rect rcIcon = rcClient;
     53   rcIcon.left += PWL_IconList_ITEM_ICON_LEFTMARGIN;
     54   rcIcon.right = rcIcon.left + PWL_IconList_ITEM_WIDTH;
     55 
     56   CPWL_Utils::DrawIconAppStream(pDevice, pUser2Device, m_nIconIndex, rcIcon,
     57                                 m_crIcon, m_pText->GetTextColor(),
     58                                 GetTransparency());
     59 }
     60 
     61 void CPWL_IconList_Item::SetSelect(FX_BOOL bSelected) {
     62   m_bSelected = bSelected;
     63 
     64   if (bSelected)
     65     m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR);
     66   else
     67     m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR);
     68 }
     69 
     70 FX_BOOL CPWL_IconList_Item::IsSelected() const {
     71   return m_bSelected;
     72 }
     73 
     74 void CPWL_IconList_Item::CreateChildWnd(const PWL_CREATEPARAM& cp) {
     75   m_pText = new CPWL_Label;
     76 
     77   PWL_CREATEPARAM lcp = cp;
     78   lcp.pParentWnd = this;
     79   lcp.dwFlags = PWS_CHILD | PWS_VISIBLE | PES_LEFT | PES_CENTER;
     80   lcp.sTextColor = PWL_DEFAULT_BLACKCOLOR;
     81   lcp.fFontSize = 12;
     82   m_pText->Create(lcp);
     83 }
     84 
     85 void CPWL_IconList_Item::SetData(void* pData) {
     86   m_pData = pData;
     87 }
     88 
     89 void CPWL_IconList_Item::SetIcon(int32_t nIconIndex) {
     90   m_nIconIndex = nIconIndex;
     91 }
     92 
     93 void CPWL_IconList_Item::SetText(const CFX_WideString& str) {
     94   m_pText->SetText(str.c_str());
     95 }
     96 
     97 CFX_WideString CPWL_IconList_Item::GetText() const {
     98   return m_pText->GetText();
     99 }
    100 
    101 void CPWL_IconList_Item::RePosChildWnd() {
    102   CPDF_Rect rcClient = GetClientRect();
    103 
    104   rcClient.left +=
    105       (PWL_IconList_ITEM_ICON_LEFTMARGIN + PWL_IconList_ITEM_WIDTH +
    106        PWL_IconList_ITEM_ICON_LEFTMARGIN);
    107 
    108   m_pText->Move(rcClient, TRUE, FALSE);
    109 }
    110 
    111 void CPWL_IconList_Item::SetIconFillColor(const CPWL_Color& color) {
    112   m_crIcon = color;
    113 }
    114 
    115 void CPWL_IconList_Item::OnEnabled() {
    116   if (m_bSelected)
    117     m_pText->SetTextColor(PWL_DEFAULT_WHITECOLOR);
    118   else
    119     m_pText->SetTextColor(PWL_DEFAULT_BLACKCOLOR);
    120 
    121   InvalidateRect();
    122 }
    123 
    124 void CPWL_IconList_Item::OnDisabled() {
    125   m_pText->SetTextColor(PWL_DEFAULT_HEAVYGRAYCOLOR);
    126 
    127   InvalidateRect();
    128 }
    129 
    130 CPWL_IconList_Content::CPWL_IconList_Content(int32_t nListCount)
    131     : m_nSelectIndex(-1),
    132       m_pNotify(NULL),
    133       m_bEnableNotify(TRUE),
    134       m_bMouseDown(FALSE),
    135       m_nListCount(nListCount) {}
    136 
    137 CPWL_IconList_Content::~CPWL_IconList_Content() {}
    138 
    139 void CPWL_IconList_Content::CreateChildWnd(const PWL_CREATEPARAM& cp) {
    140   for (int32_t i = 0; i < m_nListCount; i++) {
    141     CPWL_IconList_Item* pNewItem = new CPWL_IconList_Item();
    142 
    143     PWL_CREATEPARAM icp = cp;
    144     icp.pParentWnd = this;
    145     icp.dwFlags = PWS_CHILD | PWS_VISIBLE | PWS_NOREFRESHCLIP;
    146     pNewItem->Create(icp);
    147   }
    148 
    149   SetItemSpace(PWL_IconList_ITEM_SPACE);
    150   ResetContent(0);
    151 
    152   if (CPWL_Wnd* pParent = GetParentWindow()) {
    153     CPDF_Rect rcScroll = GetScrollArea();
    154     GetScrollPos();
    155 
    156     PWL_SCROLL_INFO sInfo;
    157     sInfo.fContentMin = rcScroll.bottom;
    158     sInfo.fContentMax = rcScroll.top;
    159     sInfo.fPlateWidth = GetClientRect().Height();
    160     sInfo.fSmallStep = 13.0f;
    161     sInfo.fBigStep = sInfo.fPlateWidth;
    162 
    163     pParent->OnNotify(this, PNM_SETSCROLLINFO, SBT_VSCROLL, (intptr_t)&sInfo);
    164   }
    165 }
    166 
    167 FX_BOOL CPWL_IconList_Content::OnLButtonDown(const CPDF_Point& point,
    168                                              FX_DWORD nFlag) {
    169   SetFocus();
    170 
    171   SetCapture();
    172   m_bMouseDown = TRUE;
    173 
    174   int32_t nItemIndex = FindItemIndex(point);
    175   SetSelect(nItemIndex);
    176   ScrollToItem(nItemIndex);
    177 
    178   return TRUE;
    179 }
    180 
    181 FX_BOOL CPWL_IconList_Content::OnLButtonUp(const CPDF_Point& point,
    182                                            FX_DWORD nFlag) {
    183   m_bMouseDown = FALSE;
    184   ReleaseCapture();
    185 
    186   return TRUE;
    187 }
    188 
    189 FX_BOOL CPWL_IconList_Content::OnMouseMove(const CPDF_Point& point,
    190                                            FX_DWORD nFlag) {
    191   if (m_bMouseDown) {
    192     int32_t nItemIndex = FindItemIndex(point);
    193     SetSelect(nItemIndex);
    194     ScrollToItem(nItemIndex);
    195   }
    196 
    197   return TRUE;
    198 }
    199 
    200 FX_BOOL CPWL_IconList_Content::OnKeyDown(FX_WORD nChar, FX_DWORD nFlag) {
    201   switch (nChar) {
    202     case FWL_VKEY_Up:
    203       if (m_nSelectIndex > 0) {
    204         int32_t nItemIndex = m_nSelectIndex - 1;
    205         SetSelect(nItemIndex);
    206         ScrollToItem(nItemIndex);
    207       }
    208       return TRUE;
    209     case FWL_VKEY_Down:
    210       if (m_nSelectIndex < m_nListCount - 1) {
    211         int32_t nItemIndex = m_nSelectIndex + 1;
    212         SetSelect(nItemIndex);
    213         ScrollToItem(nItemIndex);
    214       }
    215       return TRUE;
    216   }
    217 
    218   return FALSE;
    219 }
    220 
    221 int32_t CPWL_IconList_Content::FindItemIndex(const CPDF_Point& point) {
    222   int32_t nIndex = 0;
    223   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    224     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    225       CPDF_Rect rcWnd = pChild->ChildToParent(pChild->GetWindowRect());
    226 
    227       if (point.y < rcWnd.top) {
    228         nIndex = i;
    229       }
    230     }
    231   }
    232 
    233   return nIndex;
    234 }
    235 
    236 void CPWL_IconList_Content::ScrollToItem(int32_t nItemIndex) {
    237   CPDF_Rect rcClient = GetClientRect();
    238 
    239   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) {
    240     CPDF_Rect rcOrigin = pItem->GetWindowRect();
    241     CPDF_Rect rcWnd = pItem->ChildToParent(rcOrigin);
    242 
    243     if (!(rcWnd.bottom > rcClient.bottom && rcWnd.top < rcClient.top)) {
    244       CPDF_Point ptScroll = GetScrollPos();
    245 
    246       if (rcWnd.top > rcClient.top) {
    247         ptScroll.y = rcOrigin.top;
    248       } else if (rcWnd.bottom < rcClient.bottom) {
    249         ptScroll.y = rcOrigin.bottom + rcClient.Height();
    250       }
    251 
    252       SetScrollPos(ptScroll);
    253       ResetFace();
    254       InvalidateRect();
    255       if (CPWL_Wnd* pParent = GetParentWindow()) {
    256         pParent->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
    257                           (intptr_t)&ptScroll.y);
    258       }
    259     }
    260   }
    261 }
    262 
    263 void CPWL_IconList_Content::SetSelect(int32_t nIndex) {
    264   if (m_nSelectIndex != nIndex) {
    265     SelectItem(m_nSelectIndex, FALSE);
    266     SelectItem(nIndex, TRUE);
    267     m_nSelectIndex = nIndex;
    268 
    269     if (IPWL_IconList_Notify* pNotify = GetNotify())
    270       pNotify->OnNoteListSelChanged(nIndex);
    271   }
    272 }
    273 
    274 int32_t CPWL_IconList_Content::GetSelect() const {
    275   return m_nSelectIndex;
    276 }
    277 
    278 IPWL_IconList_Notify* CPWL_IconList_Content::GetNotify() const {
    279   if (m_bEnableNotify)
    280     return m_pNotify;
    281   return NULL;
    282 }
    283 
    284 void CPWL_IconList_Content::SetNotify(IPWL_IconList_Notify* pNotify) {
    285   m_pNotify = pNotify;
    286 }
    287 
    288 void CPWL_IconList_Content::EnableNotify(FX_BOOL bNotify) {
    289   m_bEnableNotify = bNotify;
    290 }
    291 
    292 void CPWL_IconList_Content::SelectItem(int32_t nItemIndex, FX_BOOL bSelect) {
    293   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex)) {
    294     pItem->SetSelect(bSelect);
    295     pItem->InvalidateRect();
    296   }
    297 }
    298 
    299 CPWL_IconList_Item* CPWL_IconList_Content::GetListItem(
    300     int32_t nItemIndex) const {
    301   if (nItemIndex >= 0 && nItemIndex < m_aChildren.GetSize()) {
    302     if (CPWL_Wnd* pChild = m_aChildren.GetAt(nItemIndex)) {
    303       if (pChild->GetClassName() == "CPWL_IconList_Item") {
    304         return (CPWL_IconList_Item*)pChild;
    305       }
    306     }
    307   }
    308 
    309   return NULL;
    310 }
    311 
    312 void CPWL_IconList_Content::SetListData(int32_t nItemIndex, void* pData) {
    313   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
    314     pItem->SetData(pData);
    315 }
    316 
    317 void CPWL_IconList_Content::SetListIcon(int32_t nItemIndex,
    318                                         int32_t nIconIndex) {
    319   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
    320     pItem->SetIcon(nIconIndex);
    321 }
    322 
    323 void CPWL_IconList_Content::SetListString(int32_t nItemIndex,
    324                                           const CFX_WideString& str) {
    325   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
    326     pItem->SetText(str);
    327 }
    328 
    329 CFX_WideString CPWL_IconList_Content::GetListString(int32_t nItemIndex) const {
    330   if (CPWL_IconList_Item* pItem = GetListItem(nItemIndex))
    331     return pItem->GetText();
    332 
    333   return L"";
    334 }
    335 
    336 void CPWL_IconList_Content::SetIconFillColor(const CPWL_Color& color) {
    337   for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    338     if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
    339       if (pChild->GetClassName() == "CPWL_IconList_Item") {
    340         CPWL_IconList_Item* pItem = (CPWL_IconList_Item*)pChild;
    341         pItem->SetIconFillColor(color);
    342         pItem->InvalidateRect();
    343       }
    344     }
    345   }
    346 }
    347 
    348 CPWL_IconList::CPWL_IconList(int32_t nListCount)
    349     : m_pListContent(NULL), m_nListCount(nListCount) {}
    350 
    351 CPWL_IconList::~CPWL_IconList() {}
    352 
    353 void CPWL_IconList::RePosChildWnd() {
    354   CPWL_Wnd::RePosChildWnd();
    355 
    356   if (m_pListContent)
    357     m_pListContent->Move(GetClientRect(), TRUE, FALSE);
    358 }
    359 
    360 void CPWL_IconList::CreateChildWnd(const PWL_CREATEPARAM& cp) {
    361   m_pListContent = new CPWL_IconList_Content(m_nListCount);
    362 
    363   PWL_CREATEPARAM ccp = cp;
    364   ccp.pParentWnd = this;
    365   ccp.dwFlags = PWS_CHILD | PWS_VISIBLE;
    366   m_pListContent->Create(ccp);
    367 }
    368 
    369 void CPWL_IconList::OnCreated() {
    370   if (CPWL_ScrollBar* pScrollBar = GetVScrollBar()) {
    371     pScrollBar->RemoveFlag(PWS_AUTOTRANSPARENT);
    372     pScrollBar->SetTransparency(255);
    373     pScrollBar->SetNotifyForever(TRUE);
    374   }
    375 }
    376 
    377 void CPWL_IconList::OnNotify(CPWL_Wnd* pWnd,
    378                              FX_DWORD msg,
    379                              intptr_t wParam,
    380                              intptr_t lParam) {
    381   CPWL_Wnd::OnNotify(pWnd, msg, wParam, lParam);
    382 
    383   if (wParam == SBT_VSCROLL) {
    384     switch (msg) {
    385       case PNM_SETSCROLLINFO:
    386         if (PWL_SCROLL_INFO* pInfo = (PWL_SCROLL_INFO*)lParam) {
    387           if (CPWL_ScrollBar* pScrollBar = GetVScrollBar()) {
    388             if (pInfo->fContentMax - pInfo->fContentMin > pInfo->fPlateWidth) {
    389               if (!pScrollBar->IsVisible()) {
    390                 pScrollBar->SetVisible(TRUE);
    391                 RePosChildWnd();
    392               } else {
    393               }
    394             } else {
    395               if (pScrollBar->IsVisible()) {
    396                 pScrollBar->SetVisible(FALSE);
    397                 RePosChildWnd();
    398               }
    399 
    400               if (m_pListContent)
    401                 m_pListContent->SetScrollPos(CPDF_Point(0.0f, 0.0f));
    402             }
    403 
    404             pScrollBar->OnNotify(pWnd, PNM_SETSCROLLINFO, wParam, lParam);
    405           }
    406         }
    407         return;
    408       case PNM_SCROLLWINDOW:
    409         if (m_pListContent) {
    410           m_pListContent->SetScrollPos(CPDF_Point(0.0f, *(FX_FLOAT*)lParam));
    411           m_pListContent->ResetFace();
    412           m_pListContent->InvalidateRect(NULL);
    413         }
    414         return;
    415       case PNM_SETSCROLLPOS:
    416         if (CPWL_ScrollBar* pScrollBar = GetVScrollBar())
    417           pScrollBar->OnNotify(pWnd, PNM_SETSCROLLPOS, wParam, lParam);
    418         return;
    419     }
    420   }
    421 }
    422 
    423 void CPWL_IconList::SetSelect(int32_t nIndex) {
    424   m_pListContent->SetSelect(nIndex);
    425 }
    426 
    427 void CPWL_IconList::SetTopItem(int32_t nIndex) {
    428   m_pListContent->ScrollToItem(nIndex);
    429 }
    430 
    431 int32_t CPWL_IconList::GetSelect() const {
    432   return m_pListContent->GetSelect();
    433 }
    434 
    435 void CPWL_IconList::SetNotify(IPWL_IconList_Notify* pNotify) {
    436   m_pListContent->SetNotify(pNotify);
    437 }
    438 
    439 void CPWL_IconList::EnableNotify(FX_BOOL bNotify) {
    440   m_pListContent->EnableNotify(bNotify);
    441 }
    442 
    443 void CPWL_IconList::SetListData(int32_t nItemIndex, void* pData) {
    444   m_pListContent->SetListData(nItemIndex, pData);
    445 }
    446 
    447 void CPWL_IconList::SetListIcon(int32_t nItemIndex, int32_t nIconIndex) {
    448   m_pListContent->SetListIcon(nItemIndex, nIconIndex);
    449 }
    450 
    451 void CPWL_IconList::SetListString(int32_t nItemIndex,
    452                                   const CFX_WideString& str) {
    453   m_pListContent->SetListString(nItemIndex, str);
    454 }
    455 
    456 CFX_WideString CPWL_IconList::GetListString(int32_t nItemIndex) const {
    457   return m_pListContent->GetListString(nItemIndex);
    458 }
    459 
    460 void CPWL_IconList::SetIconFillColor(const CPWL_Color& color) {
    461   m_pListContent->SetIconFillColor(color);
    462 }
    463 
    464 FX_BOOL CPWL_IconList::OnMouseWheel(short zDelta,
    465                                     const CPDF_Point& point,
    466                                     FX_DWORD nFlag) {
    467   CPDF_Point ptScroll = m_pListContent->GetScrollPos();
    468   CPDF_Rect rcScroll = m_pListContent->GetScrollArea();
    469   CPDF_Rect rcContents = m_pListContent->GetClientRect();
    470 
    471   if (rcScroll.top - rcScroll.bottom > rcContents.Height()) {
    472     CPDF_Point ptNew = ptScroll;
    473 
    474     if (zDelta > 0)
    475       ptNew.y += 30;
    476     else
    477       ptNew.y -= 30;
    478 
    479     if (ptNew.y > rcScroll.top)
    480       ptNew.y = rcScroll.top;
    481     if (ptNew.y < rcScroll.bottom + rcContents.Height())
    482       ptNew.y = rcScroll.bottom + rcContents.Height();
    483     if (ptNew.y < rcScroll.bottom)
    484       ptNew.y = rcScroll.bottom;
    485 
    486     if (ptNew.y != ptScroll.y) {
    487       m_pListContent->SetScrollPos(ptNew);
    488       m_pListContent->ResetFace();
    489       m_pListContent->InvalidateRect(NULL);
    490 
    491       if (CPWL_ScrollBar* pScrollBar = GetVScrollBar())
    492         pScrollBar->OnNotify(this, PNM_SETSCROLLPOS, SBT_VSCROLL,
    493                              (intptr_t)&ptNew.y);
    494 
    495       return TRUE;
    496     }
    497   }
    498 
    499   return FALSE;
    500 }
    501