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