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