OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "xfa/fwl/core/ifwl_combolist.h" | |
8 | |
9 #include <memory> | |
10 #include <utility> | |
11 | |
12 #include "third_party/base/ptr_util.h" | |
13 #include "xfa/fwl/core/cfwl_msgkey.h" | |
14 #include "xfa/fwl/core/cfwl_msgkillfocus.h" | |
15 #include "xfa/fwl/core/cfwl_msgmouse.h" | |
16 #include "xfa/fwl/core/ifwl_combobox.h" | |
17 #include "xfa/fwl/core/ifwl_comboedit.h" | |
18 #include "xfa/fwl/core/ifwl_listbox.h" | |
19 | |
20 IFWL_ComboList::IFWL_ComboList( | |
21 const CFWL_App* app, | |
22 std::unique_ptr<CFWL_WidgetProperties> properties, | |
23 IFWL_Widget* pOuter) | |
24 : IFWL_ListBox(app, std::move(properties), pOuter), m_bNotifyOwner(true) { | |
25 ASSERT(pOuter); | |
26 } | |
27 | |
28 int32_t IFWL_ComboList::MatchItem(const CFX_WideString& wsMatch) { | |
29 if (wsMatch.IsEmpty()) | |
30 return -1; | |
31 | |
32 int32_t iCount = CountItems(this); | |
33 for (int32_t i = 0; i < iCount; i++) { | |
34 CFWL_ListItem* hItem = GetItem(this, i); | |
35 CFX_WideString wsText; | |
36 GetItemText(this, hItem, wsText); | |
37 FX_STRSIZE pos = wsText.Find(wsMatch.c_str()); | |
38 if (!pos) | |
39 return i; | |
40 } | |
41 return -1; | |
42 } | |
43 | |
44 void IFWL_ComboList::ChangeSelected(int32_t iSel) { | |
45 CFWL_ListItem* hItem = GetItem(this, iSel); | |
46 CFX_RectF rtInvalidate; | |
47 rtInvalidate.Reset(); | |
48 CFWL_ListItem* hOld = GetSelItem(0); | |
49 int32_t iOld = GetItemIndex(this, hOld); | |
50 if (iOld == iSel) | |
51 return; | |
52 if (iOld > -1) { | |
53 CFWL_ListItem* hItem = GetItem(this, iOld); | |
54 GetItemRect(this, hItem, rtInvalidate); | |
55 SetSelItem(hOld, false); | |
56 } | |
57 if (hItem) { | |
58 CFX_RectF rect; | |
59 CFWL_ListItem* hItem = GetItem(this, iSel); | |
60 GetItemRect(this, hItem, rect); | |
61 rtInvalidate.Union(rect); | |
62 CFWL_ListItem* hSel = GetItem(this, iSel); | |
63 SetSelItem(hSel, true); | |
64 } | |
65 if (!rtInvalidate.IsEmpty()) | |
66 Repaint(&rtInvalidate); | |
67 } | |
68 | |
69 void IFWL_ComboList::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) { | |
70 fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top; | |
71 IFWL_Widget* pOwner = GetOwner(); | |
72 if (!pOwner) | |
73 return; | |
74 pOwner->TransformTo(m_pOuter, fx, fy); | |
75 } | |
76 | |
77 void IFWL_ComboList::OnProcessMessage(CFWL_Message* pMessage) { | |
78 if (!pMessage) | |
79 return; | |
80 | |
81 CFWL_MessageType dwHashCode = pMessage->GetClassID(); | |
82 bool backDefault = true; | |
83 if (dwHashCode == CFWL_MessageType::SetFocus || | |
84 dwHashCode == CFWL_MessageType::KillFocus) { | |
85 OnDropListFocusChanged(pMessage, dwHashCode == CFWL_MessageType::SetFocus); | |
86 } else if (dwHashCode == CFWL_MessageType::Mouse) { | |
87 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); | |
88 IFWL_ScrollBar* vertSB = GetVertScrollBar(); | |
89 if (IsShowScrollBar(true) && vertSB) { | |
90 CFX_RectF rect; | |
91 vertSB->GetWidgetRect(rect); | |
92 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { | |
93 pMsg->m_fx -= rect.left; | |
94 pMsg->m_fy -= rect.top; | |
95 vertSB->GetDelegate()->OnProcessMessage(pMsg); | |
96 return; | |
97 } | |
98 } | |
99 switch (pMsg->m_dwCmd) { | |
100 case FWL_MouseCommand::Move: { | |
101 backDefault = false; | |
102 OnDropListMouseMove(pMsg); | |
103 break; | |
104 } | |
105 case FWL_MouseCommand::LeftButtonDown: { | |
106 backDefault = false; | |
107 OnDropListLButtonDown(pMsg); | |
108 break; | |
109 } | |
110 case FWL_MouseCommand::LeftButtonUp: { | |
111 backDefault = false; | |
112 OnDropListLButtonUp(pMsg); | |
113 break; | |
114 } | |
115 default: | |
116 break; | |
117 } | |
118 } else if (dwHashCode == CFWL_MessageType::Key) { | |
119 backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage)); | |
120 } | |
121 if (backDefault) | |
122 IFWL_ListBox::OnProcessMessage(pMessage); | |
123 } | |
124 | |
125 void IFWL_ComboList::OnDropListFocusChanged(CFWL_Message* pMsg, bool bSet) { | |
126 if (bSet) | |
127 return; | |
128 | |
129 CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg); | |
130 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
131 if (pKill->m_pSetFocus == m_pOuter || | |
132 pKill->m_pSetFocus == pOuter->GetComboEdit()) { | |
133 pOuter->ShowDropList(false); | |
134 } | |
135 } | |
136 | |
137 void IFWL_ComboList::OnDropListMouseMove(CFWL_MsgMouse* pMsg) { | |
138 if (GetRTClient().Contains(pMsg->m_fx, pMsg->m_fy)) { | |
139 if (m_bNotifyOwner) | |
140 m_bNotifyOwner = false; | |
141 | |
142 IFWL_ScrollBar* vertSB = GetVertScrollBar(); | |
143 if (IsShowScrollBar(true) && vertSB) { | |
144 CFX_RectF rect; | |
145 vertSB->GetWidgetRect(rect); | |
146 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) | |
147 return; | |
148 } | |
149 | |
150 CFWL_ListItem* hItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); | |
151 if (!hItem) | |
152 return; | |
153 | |
154 ChangeSelected(GetItemIndex(this, hItem)); | |
155 } else if (m_bNotifyOwner) { | |
156 ClientToOuter(pMsg->m_fx, pMsg->m_fy); | |
157 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
158 pOuter->GetDelegate()->OnProcessMessage(pMsg); | |
159 } | |
160 } | |
161 | |
162 void IFWL_ComboList::OnDropListLButtonDown(CFWL_MsgMouse* pMsg) { | |
163 if (GetRTClient().Contains(pMsg->m_fx, pMsg->m_fy)) | |
164 return; | |
165 | |
166 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
167 pOuter->ShowDropList(false); | |
168 } | |
169 | |
170 void IFWL_ComboList::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) { | |
171 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
172 if (m_bNotifyOwner) { | |
173 ClientToOuter(pMsg->m_fx, pMsg->m_fy); | |
174 pOuter->GetDelegate()->OnProcessMessage(pMsg); | |
175 return; | |
176 } | |
177 | |
178 IFWL_ScrollBar* vertSB = GetVertScrollBar(); | |
179 if (IsShowScrollBar(true) && vertSB) { | |
180 CFX_RectF rect; | |
181 vertSB->GetWidgetRect(rect); | |
182 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) | |
183 return; | |
184 } | |
185 pOuter->ShowDropList(false); | |
186 | |
187 CFWL_ListItem* hItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); | |
188 if (hItem) | |
189 pOuter->ProcessSelChanged(true); | |
190 } | |
191 | |
192 bool IFWL_ComboList::OnDropListKey(CFWL_MsgKey* pKey) { | |
193 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
194 bool bPropagate = false; | |
195 if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown) { | |
196 uint32_t dwKeyCode = pKey->m_dwKeyCode; | |
197 switch (dwKeyCode) { | |
198 case FWL_VKEY_Return: | |
199 case FWL_VKEY_Escape: { | |
200 pOuter->ShowDropList(false); | |
201 return true; | |
202 } | |
203 case FWL_VKEY_Up: | |
204 case FWL_VKEY_Down: { | |
205 OnDropListKeyDown(pKey); | |
206 pOuter->ProcessSelChanged(false); | |
207 return true; | |
208 } | |
209 default: { | |
210 bPropagate = true; | |
211 break; | |
212 } | |
213 } | |
214 } else if (pKey->m_dwCmd == FWL_KeyCommand::Char) { | |
215 bPropagate = true; | |
216 } | |
217 if (bPropagate) { | |
218 pKey->m_pDstTarget = m_pOuter; | |
219 pOuter->GetDelegate()->OnProcessMessage(pKey); | |
220 return true; | |
221 } | |
222 return false; | |
223 } | |
224 | |
225 void IFWL_ComboList::OnDropListKeyDown(CFWL_MsgKey* pKey) { | |
226 uint32_t dwKeyCode = pKey->m_dwKeyCode; | |
227 switch (dwKeyCode) { | |
228 case FWL_VKEY_Up: | |
229 case FWL_VKEY_Down: | |
230 case FWL_VKEY_Home: | |
231 case FWL_VKEY_End: { | |
232 IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter); | |
233 CFWL_ListItem* hItem = GetItem(this, pOuter->GetCurrentSelection()); | |
234 hItem = GetListItem(hItem, dwKeyCode); | |
235 if (!hItem) | |
236 break; | |
237 | |
238 SetSelection(hItem, hItem, true); | |
239 ScrollToVisible(hItem); | |
240 CFX_RectF rtInvalidate; | |
241 rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width, | |
242 m_pProperties->m_rtWidget.height); | |
243 Repaint(&rtInvalidate); | |
244 break; | |
245 } | |
246 default: | |
247 break; | |
248 } | |
249 } | |
OLD | NEW |