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