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