OLD | NEW |
| (Empty) |
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 "xfa/fwl/core/ifwl_edit.h" | |
8 | |
9 #include <algorithm> | |
10 #include <memory> | |
11 #include <utility> | |
12 #include <vector> | |
13 | |
14 #include "third_party/base/ptr_util.h" | |
15 #include "third_party/base/stl_util.h" | |
16 #include "xfa/fde/cfde_txtedtengine.h" | |
17 #include "xfa/fde/fde_gedevice.h" | |
18 #include "xfa/fde/fde_render.h" | |
19 #include "xfa/fde/ifde_txtedtpage.h" | |
20 #include "xfa/fgas/font/cfgas_gefont.h" | |
21 #include "xfa/fwl/core/cfwl_app.h" | |
22 #include "xfa/fwl/core/cfwl_caret.h" | |
23 #include "xfa/fwl/core/cfwl_evtcheckword.h" | |
24 #include "xfa/fwl/core/cfwl_evttextchanged.h" | |
25 #include "xfa/fwl/core/cfwl_evttextfull.h" | |
26 #include "xfa/fwl/core/cfwl_evtvalidate.h" | |
27 #include "xfa/fwl/core/cfwl_msgkey.h" | |
28 #include "xfa/fwl/core/cfwl_msgmouse.h" | |
29 #include "xfa/fwl/core/cfwl_themebackground.h" | |
30 #include "xfa/fwl/core/cfwl_themepart.h" | |
31 #include "xfa/fwl/core/cfwl_widgetmgr.h" | |
32 #include "xfa/fwl/core/ifwl_themeprovider.h" | |
33 #include "xfa/fxfa/xfa_ffdoc.h" | |
34 #include "xfa/fxfa/xfa_ffwidget.h" | |
35 #include "xfa/fxgraphics/cfx_path.h" | |
36 | |
37 namespace { | |
38 | |
39 const int kEditMargin = 3; | |
40 | |
41 bool FX_EDIT_ISLATINWORD(FX_WCHAR c) { | |
42 return c == 0x2D || (c <= 0x005A && c >= 0x0041) || | |
43 (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) || | |
44 c == 0x0027; | |
45 } | |
46 | |
47 void AddSquigglyPath(CFX_Path* pPathData, | |
48 FX_FLOAT fStartX, | |
49 FX_FLOAT fEndX, | |
50 FX_FLOAT fY, | |
51 FX_FLOAT fStep) { | |
52 pPathData->MoveTo(fStartX, fY); | |
53 int i = 1; | |
54 for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i) | |
55 pPathData->LineTo(fx, fY + (i & 1) * fStep); | |
56 } | |
57 | |
58 } // namespace | |
59 | |
60 IFWL_Edit::IFWL_Edit(const CFWL_App* app, | |
61 std::unique_ptr<CFWL_WidgetProperties> properties, | |
62 IFWL_Widget* pOuter) | |
63 : IFWL_Widget(app, std::move(properties), pOuter), | |
64 m_fVAlignOffset(0.0f), | |
65 m_fScrollOffsetX(0.0f), | |
66 m_fScrollOffsetY(0.0f), | |
67 m_bLButtonDown(false), | |
68 m_nSelStart(0), | |
69 m_nLimit(-1), | |
70 m_fFontSize(0), | |
71 m_bSetRange(false), | |
72 m_iMax(0xFFFFFFF), | |
73 m_iCurRecord(-1), | |
74 m_iMaxRecord(128) { | |
75 m_rtClient.Reset(); | |
76 m_rtEngine.Reset(); | |
77 m_rtStatic.Reset(); | |
78 | |
79 InitCaret(); | |
80 } | |
81 | |
82 IFWL_Edit::~IFWL_Edit() { | |
83 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) | |
84 ShowCaret(false); | |
85 ClearRecord(); | |
86 } | |
87 | |
88 FWL_Type IFWL_Edit::GetClassID() const { | |
89 return FWL_Type::Edit; | |
90 } | |
91 | |
92 void IFWL_Edit::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) { | |
93 if (!bAutoSize) { | |
94 rect = m_pProperties->m_rtWidget; | |
95 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
96 if (IsShowScrollBar(true)) { | |
97 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
98 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
99 rect.width += *pfWidth; | |
100 rect.width += kEditMargin; | |
101 } | |
102 if (IsShowScrollBar(false)) { | |
103 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
104 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
105 rect.height += *pfWidth; | |
106 rect.height += kEditMargin; | |
107 } | |
108 } | |
109 return; | |
110 } | |
111 | |
112 rect.Set(0, 0, 0, 0); | |
113 | |
114 int32_t iTextLen = m_EdtEngine.GetTextLength(); | |
115 if (iTextLen > 0) { | |
116 CFX_WideString wsText; | |
117 m_EdtEngine.GetText(wsText, 0); | |
118 CFX_SizeF sz = CalcTextSize( | |
119 wsText, m_pProperties->m_pThemeProvider, | |
120 !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine)); | |
121 rect.Set(0, 0, sz.x, sz.y); | |
122 } | |
123 IFWL_Widget::GetWidgetRect(rect, true); | |
124 } | |
125 | |
126 void IFWL_Edit::SetStates(uint32_t dwStates, bool bSet) { | |
127 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) || | |
128 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
129 ShowCaret(false); | |
130 } | |
131 IFWL_Widget::SetStates(dwStates, bSet); | |
132 } | |
133 | |
134 void IFWL_Edit::Update() { | |
135 if (IsLocked()) | |
136 return; | |
137 if (!m_pProperties->m_pThemeProvider) | |
138 m_pProperties->m_pThemeProvider = GetAvailableTheme(); | |
139 | |
140 Layout(); | |
141 if (m_rtClient.IsEmpty()) | |
142 return; | |
143 | |
144 UpdateEditEngine(); | |
145 UpdateVAlignment(); | |
146 UpdateScroll(); | |
147 InitCaret(); | |
148 } | |
149 | |
150 FWL_WidgetHit IFWL_Edit::HitTest(FX_FLOAT fx, FX_FLOAT fy) { | |
151 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
152 if (IsShowScrollBar(true)) { | |
153 CFX_RectF rect; | |
154 m_pVertScrollBar->GetWidgetRect(rect); | |
155 if (rect.Contains(fx, fy)) | |
156 return FWL_WidgetHit::VScrollBar; | |
157 } | |
158 if (IsShowScrollBar(false)) { | |
159 CFX_RectF rect; | |
160 m_pHorzScrollBar->GetWidgetRect(rect); | |
161 if (rect.Contains(fx, fy)) | |
162 return FWL_WidgetHit::HScrollBar; | |
163 } | |
164 } | |
165 if (m_rtClient.Contains(fx, fy)) | |
166 return FWL_WidgetHit::Edit; | |
167 return FWL_WidgetHit::Unknown; | |
168 } | |
169 | |
170 void IFWL_Edit::AddSpellCheckObj(CFX_Path& PathData, | |
171 int32_t nStart, | |
172 int32_t nCount, | |
173 FX_FLOAT fOffSetX, | |
174 FX_FLOAT fOffSetY) { | |
175 FX_FLOAT fStartX = 0.0f; | |
176 FX_FLOAT fEndX = 0.0f; | |
177 FX_FLOAT fY = 0.0f; | |
178 FX_FLOAT fStep = 0.0f; | |
179 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
180 CFX_RectFArray rectArray; | |
181 CFX_RectF rectText; | |
182 const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams(); | |
183 FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) * | |
184 txtEdtParams->fFontSize / 1000; | |
185 pPage->CalcRangeRectArray(nStart, nCount, rectArray); | |
186 | |
187 for (int i = 0; i < rectArray.GetSize(); i++) { | |
188 rectText = rectArray.GetAt(i); | |
189 fY = rectText.top + fAsent + fOffSetY; | |
190 fStep = txtEdtParams->fFontSize / 16.0f; | |
191 fStartX = rectText.left + fOffSetX; | |
192 fEndX = fStartX + rectText.Width(); | |
193 AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep); | |
194 } | |
195 } | |
196 | |
197 void IFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics, | |
198 const CFX_Matrix* pMatrix) { | |
199 pGraphics->SaveGraphState(); | |
200 if (pMatrix) | |
201 pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix)); | |
202 | |
203 CFX_Color crLine(0xFFFF0000); | |
204 CFWL_EvtCheckWord checkWordEvent; | |
205 checkWordEvent.m_pSrcTarget = this; | |
206 | |
207 CFX_ByteString sLatinWord; | |
208 CFX_Path pathSpell; | |
209 pathSpell.Create(); | |
210 | |
211 int32_t nStart = 0; | |
212 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
213 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
214 | |
215 CFX_WideString wsSpell; | |
216 GetText(wsSpell); | |
217 int32_t nContentLen = wsSpell.GetLength(); | |
218 for (int i = 0; i < nContentLen; i++) { | |
219 if (FX_EDIT_ISLATINWORD(wsSpell[i])) { | |
220 if (sLatinWord.IsEmpty()) | |
221 nStart = i; | |
222 sLatinWord += (FX_CHAR)wsSpell[i]; | |
223 continue; | |
224 } | |
225 checkWordEvent.bsWord = sLatinWord; | |
226 checkWordEvent.bCheckWord = true; | |
227 DispatchEvent(&checkWordEvent); | |
228 | |
229 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { | |
230 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, | |
231 fOffSetY); | |
232 } | |
233 sLatinWord.clear(); | |
234 } | |
235 | |
236 checkWordEvent.bsWord = sLatinWord; | |
237 checkWordEvent.bCheckWord = true; | |
238 DispatchEvent(&checkWordEvent); | |
239 | |
240 if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) { | |
241 AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX, | |
242 fOffSetY); | |
243 } | |
244 if (!pathSpell.IsEmpty()) { | |
245 CFX_RectF rtClip = m_rtEngine; | |
246 CFX_Matrix mt; | |
247 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); | |
248 if (pMatrix) { | |
249 pMatrix->TransformRect(rtClip); | |
250 mt.Concat(*pMatrix); | |
251 } | |
252 pGraphics->SetClipRect(rtClip); | |
253 pGraphics->SetStrokeColor(&crLine); | |
254 pGraphics->SetLineWidth(0); | |
255 pGraphics->StrokePath(&pathSpell, nullptr); | |
256 } | |
257 pGraphics->RestoreGraphState(); | |
258 } | |
259 | |
260 void IFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) { | |
261 if (!pGraphics) | |
262 return; | |
263 if (!m_pProperties->m_pThemeProvider) | |
264 return; | |
265 if (m_rtClient.IsEmpty()) | |
266 return; | |
267 | |
268 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; | |
269 if (!m_pWidgetMgr->IsFormDisabled()) | |
270 DrawTextBk(pGraphics, pTheme, pMatrix); | |
271 DrawContent(pGraphics, pTheme, pMatrix); | |
272 | |
273 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && | |
274 !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) { | |
275 DrawSpellCheck(pGraphics, pMatrix); | |
276 } | |
277 if (HasBorder()) | |
278 DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix); | |
279 if (HasEdge()) | |
280 DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix); | |
281 } | |
282 | |
283 void IFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { | |
284 if (!pThemeProvider) | |
285 return; | |
286 if (m_pHorzScrollBar) | |
287 m_pHorzScrollBar->SetThemeProvider(pThemeProvider); | |
288 if (m_pVertScrollBar) | |
289 m_pVertScrollBar->SetThemeProvider(pThemeProvider); | |
290 if (m_pCaret) | |
291 m_pCaret->SetThemeProvider(pThemeProvider); | |
292 m_pProperties->m_pThemeProvider = pThemeProvider; | |
293 } | |
294 | |
295 void IFWL_Edit::SetText(const CFX_WideString& wsText) { | |
296 m_EdtEngine.SetText(wsText); | |
297 } | |
298 | |
299 int32_t IFWL_Edit::GetTextLength() const { | |
300 return m_EdtEngine.GetTextLength(); | |
301 } | |
302 | |
303 void IFWL_Edit::GetText(CFX_WideString& wsText, | |
304 int32_t nStart, | |
305 int32_t nCount) const { | |
306 m_EdtEngine.GetText(wsText, nStart, nCount); | |
307 } | |
308 | |
309 void IFWL_Edit::ClearText() { | |
310 m_EdtEngine.ClearText(); | |
311 } | |
312 | |
313 void IFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) { | |
314 m_EdtEngine.AddSelRange(nStart, nCount); | |
315 } | |
316 | |
317 int32_t IFWL_Edit::CountSelRanges() const { | |
318 return m_EdtEngine.CountSelRanges(); | |
319 } | |
320 | |
321 int32_t IFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) const { | |
322 return m_EdtEngine.GetSelRange(nIndex, nStart); | |
323 } | |
324 | |
325 void IFWL_Edit::ClearSelections() { | |
326 m_EdtEngine.ClearSelection(); | |
327 } | |
328 | |
329 int32_t IFWL_Edit::GetLimit() const { | |
330 return m_nLimit; | |
331 } | |
332 | |
333 void IFWL_Edit::SetLimit(int32_t nLimit) { | |
334 m_nLimit = nLimit; | |
335 m_EdtEngine.SetLimit(nLimit); | |
336 } | |
337 | |
338 void IFWL_Edit::SetAliasChar(FX_WCHAR wAlias) { | |
339 m_EdtEngine.SetAliasChar(wAlias); | |
340 } | |
341 | |
342 bool IFWL_Edit::Copy(CFX_WideString& wsCopy) { | |
343 int32_t nCount = m_EdtEngine.CountSelRanges(); | |
344 if (nCount == 0) | |
345 return false; | |
346 | |
347 wsCopy.clear(); | |
348 CFX_WideString wsTemp; | |
349 int32_t nStart, nLength; | |
350 for (int32_t i = 0; i < nCount; i++) { | |
351 nLength = m_EdtEngine.GetSelRange(i, nStart); | |
352 m_EdtEngine.GetText(wsTemp, nStart, nLength); | |
353 wsCopy += wsTemp; | |
354 wsTemp.clear(); | |
355 } | |
356 return true; | |
357 } | |
358 | |
359 bool IFWL_Edit::Cut(CFX_WideString& wsCut) { | |
360 int32_t nCount = m_EdtEngine.CountSelRanges(); | |
361 if (nCount == 0) | |
362 return false; | |
363 | |
364 wsCut.clear(); | |
365 CFX_WideString wsTemp; | |
366 int32_t nStart, nLength; | |
367 for (int32_t i = 0; i < nCount; i++) { | |
368 nLength = m_EdtEngine.GetSelRange(i, nStart); | |
369 m_EdtEngine.GetText(wsTemp, nStart, nLength); | |
370 wsCut += wsTemp; | |
371 wsTemp.clear(); | |
372 } | |
373 m_EdtEngine.Delete(0); | |
374 return true; | |
375 } | |
376 | |
377 bool IFWL_Edit::Paste(const CFX_WideString& wsPaste) { | |
378 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
379 int32_t iError = | |
380 m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength()); | |
381 if (iError < 0) { | |
382 ProcessInsertError(iError); | |
383 return false; | |
384 } | |
385 return true; | |
386 } | |
387 | |
388 bool IFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) { | |
389 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) | |
390 return true; | |
391 return m_EdtEngine.Redo(pRecord); | |
392 } | |
393 | |
394 bool IFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) { | |
395 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo) | |
396 return true; | |
397 return m_EdtEngine.Undo(pRecord); | |
398 } | |
399 | |
400 bool IFWL_Edit::Undo() { | |
401 if (!CanUndo()) | |
402 return false; | |
403 return Undo(m_DoRecords[m_iCurRecord--].get()); | |
404 } | |
405 | |
406 bool IFWL_Edit::Redo() { | |
407 if (!CanRedo()) | |
408 return false; | |
409 return Redo(m_DoRecords[++m_iCurRecord].get()); | |
410 } | |
411 | |
412 bool IFWL_Edit::CanUndo() { | |
413 return m_iCurRecord >= 0; | |
414 } | |
415 | |
416 bool IFWL_Edit::CanRedo() { | |
417 return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; | |
418 } | |
419 | |
420 void IFWL_Edit::SetOuter(IFWL_Widget* pOuter) { | |
421 m_pOuter = pOuter; | |
422 } | |
423 | |
424 void IFWL_Edit::On_CaretChanged(CFDE_TxtEdtEngine* pEdit, | |
425 int32_t nPage, | |
426 bool bVisible) { | |
427 if (m_rtEngine.IsEmpty()) | |
428 return; | |
429 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) | |
430 return; | |
431 | |
432 bool bRepaintContent = UpdateOffset(); | |
433 UpdateCaret(); | |
434 CFX_RectF rtInvalid; | |
435 rtInvalid.Set(0, 0, 0, 0); | |
436 bool bRepaintScroll = false; | |
437 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { | |
438 CFWL_ScrollBar* pScroll = UpdateScroll(); | |
439 if (pScroll) { | |
440 pScroll->GetWidgetRect(rtInvalid); | |
441 bRepaintScroll = true; | |
442 } | |
443 } | |
444 if (bRepaintContent || bRepaintScroll) { | |
445 if (bRepaintContent) | |
446 rtInvalid.Union(m_rtEngine); | |
447 Repaint(&rtInvalid); | |
448 } | |
449 } | |
450 | |
451 void IFWL_Edit::On_TextChanged(CFDE_TxtEdtEngine* pEdit, | |
452 FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) { | |
453 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask) | |
454 UpdateVAlignment(); | |
455 | |
456 CFX_RectF rtTemp; | |
457 GetClientRect(rtTemp); | |
458 | |
459 CFWL_EvtTextChanged event; | |
460 event.m_pSrcTarget = this; | |
461 event.nChangeType = ChangeInfo.nChangeType; | |
462 event.wsInsert = ChangeInfo.wsInsert; | |
463 event.wsDelete = ChangeInfo.wsDelete; | |
464 event.wsPrevText = ChangeInfo.wsPrevText; | |
465 DispatchEvent(&event); | |
466 | |
467 LayoutScrollBar(); | |
468 Repaint(&rtTemp); | |
469 } | |
470 | |
471 void IFWL_Edit::On_SelChanged(CFDE_TxtEdtEngine* pEdit) { | |
472 CFX_RectF rtTemp; | |
473 GetClientRect(rtTemp); | |
474 Repaint(&rtTemp); | |
475 } | |
476 | |
477 bool IFWL_Edit::On_PageLoad(CFDE_TxtEdtEngine* pEdit, | |
478 int32_t nPageIndex, | |
479 int32_t nPurpose) { | |
480 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); | |
481 if (!pPage) | |
482 return false; | |
483 | |
484 pPage->LoadPage(nullptr, nullptr); | |
485 return true; | |
486 } | |
487 | |
488 bool IFWL_Edit::On_PageUnload(CFDE_TxtEdtEngine* pEdit, | |
489 int32_t nPageIndex, | |
490 int32_t nPurpose) { | |
491 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex); | |
492 if (!pPage) | |
493 return false; | |
494 | |
495 pPage->UnloadPage(nullptr); | |
496 return true; | |
497 } | |
498 | |
499 void IFWL_Edit::On_AddDoRecord(CFDE_TxtEdtEngine* pEdit, | |
500 IFDE_TxtEdtDoRecord* pRecord) { | |
501 AddDoRecord(pRecord); | |
502 } | |
503 | |
504 bool IFWL_Edit::On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText) { | |
505 IFWL_Widget* pDst = GetOuter(); | |
506 if (!pDst) | |
507 pDst = this; | |
508 | |
509 CFWL_EvtValidate event; | |
510 event.pDstWidget = pDst; | |
511 event.m_pSrcTarget = this; | |
512 event.wsInsert = wsText; | |
513 event.bValidate = true; | |
514 DispatchEvent(&event); | |
515 return event.bValidate; | |
516 } | |
517 | |
518 void IFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) { | |
519 m_fScrollOffsetY = fScrollOffset; | |
520 } | |
521 | |
522 void IFWL_Edit::DrawTextBk(CFX_Graphics* pGraphics, | |
523 IFWL_ThemeProvider* pTheme, | |
524 const CFX_Matrix* pMatrix) { | |
525 CFWL_ThemeBackground param; | |
526 param.m_pWidget = this; | |
527 param.m_iPart = CFWL_Part::Background; | |
528 param.m_bStaticBackground = false; | |
529 param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly | |
530 ? CFWL_PartState_ReadOnly | |
531 : CFWL_PartState_Normal; | |
532 uint32_t dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled); | |
533 if (dwStates) | |
534 param.m_dwStates = CFWL_PartState_Disabled; | |
535 param.m_pGraphics = pGraphics; | |
536 param.m_matrix = *pMatrix; | |
537 param.m_rtPart = m_rtClient; | |
538 pTheme->DrawBackground(¶m); | |
539 | |
540 if (!IsShowScrollBar(true) || !IsShowScrollBar(false)) | |
541 return; | |
542 | |
543 CFX_RectF rtScorll; | |
544 m_pHorzScrollBar->GetWidgetRect(rtScorll); | |
545 | |
546 CFX_RectF rtStatic; | |
547 rtStatic.Set(m_rtClient.right() - rtScorll.height, | |
548 m_rtClient.bottom() - rtScorll.height, rtScorll.height, | |
549 rtScorll.height); | |
550 param.m_bStaticBackground = true; | |
551 param.m_bMaximize = true; | |
552 param.m_rtPart = rtStatic; | |
553 pTheme->DrawBackground(¶m); | |
554 } | |
555 | |
556 void IFWL_Edit::DrawContent(CFX_Graphics* pGraphics, | |
557 IFWL_ThemeProvider* pTheme, | |
558 const CFX_Matrix* pMatrix) { | |
559 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
560 if (!pPage) | |
561 return; | |
562 | |
563 pGraphics->SaveGraphState(); | |
564 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) | |
565 pGraphics->SaveGraphState(); | |
566 | |
567 CFX_RectF rtClip = m_rtEngine; | |
568 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
569 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
570 CFX_Matrix mt; | |
571 mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY); | |
572 if (pMatrix) { | |
573 pMatrix->TransformRect(rtClip); | |
574 mt.Concat(*pMatrix); | |
575 } | |
576 | |
577 bool bShowSel = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) || | |
578 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); | |
579 if (bShowSel) { | |
580 IFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(this); | |
581 if (pForm) { | |
582 bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) != | |
583 FWL_WGTSTATE_Deactivated; | |
584 } | |
585 } | |
586 | |
587 int32_t nSelCount = m_EdtEngine.CountSelRanges(); | |
588 if (bShowSel && nSelCount > 0) { | |
589 int32_t nPageCharStart = pPage->GetCharStart(); | |
590 int32_t nPageCharCount = pPage->GetCharCount(); | |
591 int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1; | |
592 int32_t nCharCount; | |
593 int32_t nCharStart; | |
594 CFX_RectFArray rectArr; | |
595 int32_t i = 0; | |
596 for (i = 0; i < nSelCount; i++) { | |
597 nCharCount = m_EdtEngine.GetSelRange(i, nCharStart); | |
598 int32_t nCharEnd = nCharStart + nCharCount - 1; | |
599 if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd) | |
600 continue; | |
601 | |
602 int32_t nBgn = std::max(nCharStart, nPageCharStart); | |
603 int32_t nEnd = std::min(nCharEnd, nPageCharEnd); | |
604 pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1, | |
605 rectArr); | |
606 } | |
607 | |
608 int32_t nCount = rectArr.GetSize(); | |
609 CFX_Path path; | |
610 path.Create(); | |
611 for (i = 0; i < nCount; i++) { | |
612 rectArr[i].left += fOffSetX; | |
613 rectArr[i].top += fOffSetY; | |
614 path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width, | |
615 rectArr[i].height); | |
616 } | |
617 pGraphics->SetClipRect(rtClip); | |
618 | |
619 CFWL_ThemeBackground param; | |
620 param.m_pGraphics = pGraphics; | |
621 param.m_matrix = *pMatrix; | |
622 param.m_pWidget = this; | |
623 param.m_iPart = CFWL_Part::Background; | |
624 param.m_pPath = &path; | |
625 pTheme->DrawBackground(¶m); | |
626 } | |
627 | |
628 CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice(); | |
629 if (!pRenderDev) | |
630 return; | |
631 | |
632 std::unique_ptr<CFDE_RenderDevice> pRenderDevice( | |
633 new CFDE_RenderDevice(pRenderDev, false)); | |
634 std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext); | |
635 pRenderDevice->SetClipRect(rtClip); | |
636 pRenderContext->StartRender(pRenderDevice.get(), pPage, mt); | |
637 pRenderContext->DoRender(nullptr); | |
638 | |
639 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) { | |
640 pGraphics->RestoreGraphState(); | |
641 CFX_Path path; | |
642 path.Create(); | |
643 int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1; | |
644 FX_FLOAT fStep = m_rtEngine.width / iLimit; | |
645 FX_FLOAT fLeft = m_rtEngine.left + 1; | |
646 for (int32_t i = 1; i < iLimit; i++) { | |
647 fLeft += fStep; | |
648 path.AddLine(fLeft, m_rtClient.top, fLeft, m_rtClient.bottom()); | |
649 } | |
650 | |
651 CFWL_ThemeBackground param; | |
652 param.m_pGraphics = pGraphics; | |
653 param.m_matrix = *pMatrix; | |
654 param.m_pWidget = this; | |
655 param.m_iPart = CFWL_Part::CombTextLine; | |
656 param.m_pPath = &path; | |
657 pTheme->DrawBackground(¶m); | |
658 } | |
659 pGraphics->RestoreGraphState(); | |
660 } | |
661 | |
662 void IFWL_Edit::UpdateEditEngine() { | |
663 UpdateEditParams(); | |
664 UpdateEditLayout(); | |
665 if (m_nLimit > -1) | |
666 m_EdtEngine.SetLimit(m_nLimit); | |
667 } | |
668 | |
669 void IFWL_Edit::UpdateEditParams() { | |
670 FDE_TXTEDTPARAMS params; | |
671 params.nHorzScale = 100; | |
672 params.fPlateWidth = m_rtEngine.width; | |
673 params.fPlateHeight = m_rtEngine.height; | |
674 if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout) | |
675 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL; | |
676 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout) | |
677 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical; | |
678 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars) | |
679 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial; | |
680 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine) | |
681 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve; | |
682 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes) | |
683 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes; | |
684 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab) | |
685 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab; | |
686 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) | |
687 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText; | |
688 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight) | |
689 params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight; | |
690 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate) | |
691 params.dwMode |= FDE_TEXTEDITMODE_Validate; | |
692 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password) | |
693 params.dwMode |= FDE_TEXTEDITMODE_Password; | |
694 | |
695 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) { | |
696 case FWL_STYLEEXT_EDT_HNear: { | |
697 params.dwAlignment |= FDE_TEXTEDITALIGN_Left; | |
698 break; | |
699 } | |
700 case FWL_STYLEEXT_EDT_HCenter: { | |
701 params.dwAlignment |= FDE_TEXTEDITALIGN_Center; | |
702 break; | |
703 } | |
704 case FWL_STYLEEXT_EDT_HFar: { | |
705 params.dwAlignment |= FDE_TEXTEDITALIGN_Right; | |
706 break; | |
707 } | |
708 default: | |
709 break; | |
710 } | |
711 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) { | |
712 case FWL_STYLEEXT_EDT_Justified: { | |
713 params.dwAlignment |= FDE_TEXTEDITALIGN_Justified; | |
714 break; | |
715 } | |
716 case FWL_STYLEEXT_EDT_Distributed: { | |
717 params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed; | |
718 break; | |
719 } | |
720 default: { | |
721 params.dwAlignment |= FDE_TEXTEDITALIGN_Normal; | |
722 break; | |
723 } | |
724 } | |
725 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) { | |
726 params.dwMode |= FDE_TEXTEDITMODE_MultiLines; | |
727 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 && | |
728 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) { | |
729 params.dwMode |= | |
730 FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz; | |
731 } | |
732 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 && | |
733 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) { | |
734 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert; | |
735 } else { | |
736 params.fPlateHeight = 0x00FFFFFF; | |
737 } | |
738 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == | |
739 0) { | |
740 params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz; | |
741 } | |
742 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
743 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
744 params.dwMode |= FDE_TEXTEDITMODE_ReadOnly; | |
745 } | |
746 | |
747 FX_FLOAT* pFontSize = | |
748 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize)); | |
749 if (!pFontSize) | |
750 return; | |
751 | |
752 m_fFontSize = *pFontSize; | |
753 uint32_t* pFontColor = | |
754 static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor)); | |
755 if (!pFontColor) | |
756 return; | |
757 | |
758 params.dwFontColor = *pFontColor; | |
759 FX_FLOAT* pLineHeight = | |
760 static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight)); | |
761 if (!pLineHeight) | |
762 return; | |
763 | |
764 params.fLineSpace = *pLineHeight; | |
765 CFGAS_GEFont* pFont = | |
766 static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font)); | |
767 if (!pFont) | |
768 return; | |
769 | |
770 params.pFont = pFont; | |
771 params.fFontSize = m_fFontSize; | |
772 params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace); | |
773 if (params.nLineCount <= 0) | |
774 params.nLineCount = 1; | |
775 params.fTabWidth = params.fFontSize * 1; | |
776 params.bTabEquidistant = true; | |
777 params.wLineBreakChar = L'\n'; | |
778 params.nCharRotation = 0; | |
779 params.pEventSink = this; | |
780 m_EdtEngine.SetEditParams(params); | |
781 } | |
782 | |
783 void IFWL_Edit::UpdateEditLayout() { | |
784 if (m_EdtEngine.GetTextLength() <= 0) | |
785 m_EdtEngine.SetTextByStream(nullptr); | |
786 | |
787 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
788 if (pPage) | |
789 pPage->UnloadPage(nullptr); | |
790 | |
791 m_EdtEngine.StartLayout(); | |
792 m_EdtEngine.DoLayout(nullptr); | |
793 m_EdtEngine.EndLayout(); | |
794 pPage = m_EdtEngine.GetPage(0); | |
795 if (pPage) | |
796 pPage->LoadPage(nullptr, nullptr); | |
797 } | |
798 | |
799 bool IFWL_Edit::UpdateOffset() { | |
800 CFX_RectF rtCaret; | |
801 m_EdtEngine.GetCaretRect(rtCaret); | |
802 FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX; | |
803 FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset; | |
804 rtCaret.Offset(fOffSetX, fOffSetY); | |
805 const CFX_RectF& rtEidt = m_rtEngine; | |
806 if (rtEidt.Contains(rtCaret)) { | |
807 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
808 if (!pPage) | |
809 return false; | |
810 | |
811 CFX_RectF rtFDE = pPage->GetContentsBox(); | |
812 rtFDE.Offset(fOffSetX, fOffSetY); | |
813 if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) { | |
814 m_fScrollOffsetX += rtFDE.right() - rtEidt.right(); | |
815 m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f); | |
816 } | |
817 if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) { | |
818 m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom(); | |
819 m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f); | |
820 } | |
821 return false; | |
822 } | |
823 | |
824 FX_FLOAT offsetX = 0.0; | |
825 FX_FLOAT offsetY = 0.0; | |
826 if (rtCaret.left < rtEidt.left) | |
827 offsetX = rtCaret.left - rtEidt.left; | |
828 if (rtCaret.right() > rtEidt.right()) | |
829 offsetX = rtCaret.right() - rtEidt.right(); | |
830 if (rtCaret.top < rtEidt.top) | |
831 offsetY = rtCaret.top - rtEidt.top; | |
832 if (rtCaret.bottom() > rtEidt.bottom()) | |
833 offsetY = rtCaret.bottom() - rtEidt.bottom(); | |
834 m_fScrollOffsetX += offsetX; | |
835 m_fScrollOffsetY += offsetY; | |
836 if (m_fFontSize > m_rtEngine.height) | |
837 m_fScrollOffsetY = 0; | |
838 return true; | |
839 } | |
840 | |
841 bool IFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) { | |
842 if (pScrollBar == m_pHorzScrollBar.get()) | |
843 m_fScrollOffsetX += fPosChanged; | |
844 else | |
845 m_fScrollOffsetY += fPosChanged; | |
846 return true; | |
847 } | |
848 | |
849 void IFWL_Edit::UpdateVAlignment() { | |
850 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
851 if (!pPage) | |
852 return; | |
853 | |
854 const CFX_RectF& rtFDE = pPage->GetContentsBox(); | |
855 FX_FLOAT fOffsetY = 0.0f; | |
856 FX_FLOAT fSpaceAbove = 0.0f; | |
857 FX_FLOAT fSpaceBelow = 0.0f; | |
858 CFX_SizeF* pSpace = static_cast<CFX_SizeF*>( | |
859 GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow)); | |
860 if (pSpace) { | |
861 fSpaceAbove = pSpace->x; | |
862 fSpaceBelow = pSpace->y; | |
863 } | |
864 if (fSpaceAbove < 0.1f) | |
865 fSpaceAbove = 0; | |
866 if (fSpaceBelow < 0.1f) | |
867 fSpaceBelow = 0; | |
868 | |
869 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) { | |
870 fOffsetY = (m_rtEngine.height - rtFDE.height) / 2; | |
871 if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 && | |
872 fSpaceAbove < fSpaceBelow) { | |
873 return; | |
874 } | |
875 fOffsetY += (fSpaceAbove - fSpaceBelow) / 2; | |
876 } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) { | |
877 fOffsetY = (m_rtEngine.height - rtFDE.height); | |
878 fOffsetY -= fSpaceBelow; | |
879 } else { | |
880 fOffsetY += fSpaceAbove; | |
881 } | |
882 m_fVAlignOffset = std::max(fOffsetY, 0.0f); | |
883 } | |
884 | |
885 void IFWL_Edit::UpdateCaret() { | |
886 CFX_RectF rtFDE; | |
887 m_EdtEngine.GetCaretRect(rtFDE); | |
888 | |
889 rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX, | |
890 m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset); | |
891 CFX_RectF rtCaret; | |
892 rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height); | |
893 | |
894 CFX_RectF rtClient; | |
895 GetClientRect(rtClient); | |
896 rtCaret.Intersect(rtClient); | |
897 | |
898 if (rtCaret.left > rtClient.right()) { | |
899 FX_FLOAT right = rtCaret.right(); | |
900 rtCaret.left = rtClient.right() - 1; | |
901 rtCaret.width = right - rtCaret.left; | |
902 } | |
903 | |
904 bool bShow = | |
905 m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty(); | |
906 ShowCaret(bShow, &rtCaret); | |
907 } | |
908 | |
909 CFWL_ScrollBar* IFWL_Edit::UpdateScroll() { | |
910 bool bShowHorz = | |
911 m_pHorzScrollBar && | |
912 ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); | |
913 bool bShowVert = | |
914 m_pVertScrollBar && | |
915 ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0); | |
916 if (!bShowHorz && !bShowVert) | |
917 return nullptr; | |
918 | |
919 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
920 if (!pPage) | |
921 return nullptr; | |
922 | |
923 const CFX_RectF& rtFDE = pPage->GetContentsBox(); | |
924 CFWL_ScrollBar* pRepaint = nullptr; | |
925 if (bShowHorz) { | |
926 CFX_RectF rtScroll; | |
927 m_pHorzScrollBar->GetWidgetRect(rtScroll); | |
928 if (rtScroll.width < rtFDE.width) { | |
929 m_pHorzScrollBar->LockUpdate(); | |
930 FX_FLOAT fRange = rtFDE.width - rtScroll.width; | |
931 m_pHorzScrollBar->SetRange(0.0f, fRange); | |
932 | |
933 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetX, 0.0f), fRange); | |
934 m_pHorzScrollBar->SetPos(fPos); | |
935 m_pHorzScrollBar->SetTrackPos(fPos); | |
936 m_pHorzScrollBar->SetPageSize(rtScroll.width); | |
937 m_pHorzScrollBar->SetStepSize(rtScroll.width / 10); | |
938 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, false); | |
939 m_pHorzScrollBar->UnlockUpdate(); | |
940 m_pHorzScrollBar->Update(); | |
941 pRepaint = m_pHorzScrollBar.get(); | |
942 } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { | |
943 m_pHorzScrollBar->LockUpdate(); | |
944 m_pHorzScrollBar->SetRange(0, -1); | |
945 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, true); | |
946 m_pHorzScrollBar->UnlockUpdate(); | |
947 m_pHorzScrollBar->Update(); | |
948 pRepaint = m_pHorzScrollBar.get(); | |
949 } | |
950 } | |
951 | |
952 if (bShowVert) { | |
953 CFX_RectF rtScroll; | |
954 m_pVertScrollBar->GetWidgetRect(rtScroll); | |
955 if (rtScroll.height < rtFDE.height) { | |
956 m_pVertScrollBar->LockUpdate(); | |
957 FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace; | |
958 FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep); | |
959 | |
960 m_pVertScrollBar->SetRange(0.0f, fRange); | |
961 FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange); | |
962 m_pVertScrollBar->SetPos(fPos); | |
963 m_pVertScrollBar->SetTrackPos(fPos); | |
964 m_pVertScrollBar->SetPageSize(rtScroll.height); | |
965 m_pVertScrollBar->SetStepSize(fStep); | |
966 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, false); | |
967 m_pVertScrollBar->UnlockUpdate(); | |
968 m_pVertScrollBar->Update(); | |
969 pRepaint = m_pVertScrollBar.get(); | |
970 } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) { | |
971 m_pVertScrollBar->LockUpdate(); | |
972 m_pVertScrollBar->SetRange(0, -1); | |
973 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, true); | |
974 m_pVertScrollBar->UnlockUpdate(); | |
975 m_pVertScrollBar->Update(); | |
976 pRepaint = m_pVertScrollBar.get(); | |
977 } | |
978 } | |
979 return pRepaint; | |
980 } | |
981 | |
982 bool IFWL_Edit::IsShowScrollBar(bool bVert) { | |
983 bool bShow = | |
984 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) | |
985 ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == | |
986 FWL_WGTSTATE_Focused | |
987 : true; | |
988 if (bVert) { | |
989 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) && | |
990 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) && | |
991 IsContentHeightOverflow(); | |
992 } | |
993 return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) && | |
994 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine); | |
995 } | |
996 | |
997 bool IFWL_Edit::IsContentHeightOverflow() { | |
998 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
999 if (!pPage) | |
1000 return false; | |
1001 return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f; | |
1002 } | |
1003 | |
1004 int32_t IFWL_Edit::AddDoRecord(IFDE_TxtEdtDoRecord* pRecord) { | |
1005 int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords); | |
1006 if (m_iCurRecord == nCount - 1) { | |
1007 if (nCount == m_iMaxRecord) { | |
1008 m_DoRecords.pop_front(); | |
1009 m_iCurRecord--; | |
1010 } | |
1011 } else { | |
1012 m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1, | |
1013 m_DoRecords.end()); | |
1014 } | |
1015 | |
1016 m_DoRecords.push_back(std::unique_ptr<IFDE_TxtEdtDoRecord>(pRecord)); | |
1017 m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1; | |
1018 return m_iCurRecord; | |
1019 } | |
1020 | |
1021 void IFWL_Edit::Layout() { | |
1022 GetClientRect(m_rtClient); | |
1023 m_rtEngine = m_rtClient; | |
1024 FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>( | |
1025 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
1026 if (!pfWidth) | |
1027 return; | |
1028 | |
1029 FX_FLOAT fWidth = *pfWidth; | |
1030 if (!m_pOuter) { | |
1031 CFX_RectF* pUIMargin = static_cast<CFX_RectF*>( | |
1032 GetThemeCapacity(CFWL_WidgetCapacity::UIMargin)); | |
1033 if (pUIMargin) { | |
1034 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, | |
1035 pUIMargin->height); | |
1036 } | |
1037 } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) { | |
1038 CFWL_ThemePart part; | |
1039 part.m_pWidget = m_pOuter; | |
1040 CFX_RectF* pUIMargin = | |
1041 static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity( | |
1042 &part, CFWL_WidgetCapacity::UIMargin)); | |
1043 if (pUIMargin) { | |
1044 m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, | |
1045 pUIMargin->height); | |
1046 } | |
1047 } | |
1048 | |
1049 bool bShowVertScrollbar = IsShowScrollBar(true); | |
1050 bool bShowHorzScrollbar = IsShowScrollBar(false); | |
1051 if (bShowVertScrollbar) { | |
1052 InitScrollBar(); | |
1053 | |
1054 CFX_RectF rtVertScr; | |
1055 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
1056 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth, | |
1057 m_rtClient.height); | |
1058 } else { | |
1059 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, | |
1060 m_rtClient.height); | |
1061 if (bShowHorzScrollbar) | |
1062 rtVertScr.height -= fWidth; | |
1063 m_rtEngine.width -= fWidth; | |
1064 } | |
1065 | |
1066 m_pVertScrollBar->SetWidgetRect(rtVertScr); | |
1067 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, false); | |
1068 m_pVertScrollBar->Update(); | |
1069 } else if (m_pVertScrollBar) { | |
1070 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true); | |
1071 } | |
1072 | |
1073 if (bShowHorzScrollbar) { | |
1074 InitScrollBar(false); | |
1075 | |
1076 CFX_RectF rtHoriScr; | |
1077 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
1078 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin, | |
1079 m_rtClient.width, fWidth); | |
1080 } else { | |
1081 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, | |
1082 m_rtClient.width, fWidth); | |
1083 if (bShowVertScrollbar) | |
1084 rtHoriScr.width -= fWidth; | |
1085 m_rtEngine.height -= fWidth; | |
1086 } | |
1087 m_pHorzScrollBar->SetWidgetRect(rtHoriScr); | |
1088 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, false); | |
1089 m_pHorzScrollBar->Update(); | |
1090 } else if (m_pHorzScrollBar) { | |
1091 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true); | |
1092 } | |
1093 } | |
1094 | |
1095 void IFWL_Edit::LayoutScrollBar() { | |
1096 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) == | |
1097 0) { | |
1098 return; | |
1099 } | |
1100 | |
1101 FX_FLOAT* pfWidth = nullptr; | |
1102 bool bShowVertScrollbar = IsShowScrollBar(true); | |
1103 bool bShowHorzScrollbar = IsShowScrollBar(false); | |
1104 if (bShowVertScrollbar) { | |
1105 if (!m_pVertScrollBar) { | |
1106 pfWidth = static_cast<FX_FLOAT*>( | |
1107 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
1108 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; | |
1109 InitScrollBar(); | |
1110 CFX_RectF rtVertScr; | |
1111 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
1112 rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth, | |
1113 m_rtClient.height); | |
1114 } else { | |
1115 rtVertScr.Set(m_rtClient.right() - fWidth, m_rtClient.top, fWidth, | |
1116 m_rtClient.height); | |
1117 if (bShowHorzScrollbar) | |
1118 rtVertScr.height -= fWidth; | |
1119 } | |
1120 m_pVertScrollBar->SetWidgetRect(rtVertScr); | |
1121 m_pVertScrollBar->Update(); | |
1122 } | |
1123 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, false); | |
1124 } else if (m_pVertScrollBar) { | |
1125 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true); | |
1126 } | |
1127 | |
1128 if (bShowHorzScrollbar) { | |
1129 if (!m_pHorzScrollBar) { | |
1130 if (!pfWidth) { | |
1131 pfWidth = static_cast<FX_FLOAT*>( | |
1132 GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth)); | |
1133 } | |
1134 | |
1135 FX_FLOAT fWidth = pfWidth ? *pfWidth : 0; | |
1136 InitScrollBar(false); | |
1137 CFX_RectF rtHoriScr; | |
1138 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) { | |
1139 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin, | |
1140 m_rtClient.width, fWidth); | |
1141 } else { | |
1142 rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() - fWidth, | |
1143 m_rtClient.width, fWidth); | |
1144 if (bShowVertScrollbar) | |
1145 rtHoriScr.width -= (fWidth); | |
1146 } | |
1147 m_pHorzScrollBar->SetWidgetRect(rtHoriScr); | |
1148 m_pHorzScrollBar->Update(); | |
1149 } | |
1150 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, false); | |
1151 } else if (m_pHorzScrollBar) { | |
1152 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true); | |
1153 } | |
1154 if (bShowVertScrollbar || bShowHorzScrollbar) | |
1155 UpdateScroll(); | |
1156 } | |
1157 | |
1158 void IFWL_Edit::DeviceToEngine(CFX_PointF& pt) { | |
1159 pt.x += m_fScrollOffsetX - m_rtEngine.left; | |
1160 pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset; | |
1161 } | |
1162 | |
1163 void IFWL_Edit::InitScrollBar(bool bVert) { | |
1164 if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) | |
1165 return; | |
1166 | |
1167 auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>(); | |
1168 prop->m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz; | |
1169 prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible; | |
1170 prop->m_pParent = this; | |
1171 prop->m_pThemeProvider = m_pProperties->m_pThemeProvider; | |
1172 | |
1173 CFWL_ScrollBar* sb = new CFWL_ScrollBar(m_pOwnerApp, std::move(prop), this); | |
1174 if (bVert) | |
1175 m_pVertScrollBar.reset(sb); | |
1176 else | |
1177 m_pHorzScrollBar.reset(sb); | |
1178 } | |
1179 | |
1180 bool FWL_ShowCaret(IFWL_Widget* pWidget, | |
1181 bool bVisible, | |
1182 const CFX_RectF* pRtAnchor) { | |
1183 CXFA_FFWidget* pXFAWidget = | |
1184 static_cast<CXFA_FFWidget*>(pWidget->GetLayoutItem()); | |
1185 if (!pXFAWidget) | |
1186 return false; | |
1187 | |
1188 IXFA_DocEnvironment* pDocEnvironment = | |
1189 pXFAWidget->GetDoc()->GetDocEnvironment(); | |
1190 if (!pDocEnvironment) | |
1191 return false; | |
1192 | |
1193 if (bVisible) { | |
1194 CFX_Matrix mt; | |
1195 pXFAWidget->GetRotateMatrix(mt); | |
1196 CFX_RectF rt(*pRtAnchor); | |
1197 mt.TransformRect(rt); | |
1198 pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, &rt); | |
1199 return true; | |
1200 } | |
1201 | |
1202 pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, pRtAnchor); | |
1203 return true; | |
1204 } | |
1205 | |
1206 void IFWL_Edit::ShowCaret(bool bVisible, CFX_RectF* pRect) { | |
1207 if (m_pCaret) { | |
1208 m_pCaret->ShowCaret(bVisible); | |
1209 if (bVisible && !pRect->IsEmpty()) | |
1210 m_pCaret->SetWidgetRect(*pRect); | |
1211 Repaint(&m_rtEngine); | |
1212 return; | |
1213 } | |
1214 | |
1215 IFWL_Widget* pOuter = this; | |
1216 if (bVisible) { | |
1217 pRect->Offset(m_pProperties->m_rtWidget.left, | |
1218 m_pProperties->m_rtWidget.top); | |
1219 } | |
1220 while (pOuter->GetOuter()) { | |
1221 pOuter = pOuter->GetOuter(); | |
1222 if (bVisible) { | |
1223 CFX_RectF rtOuter; | |
1224 pOuter->GetWidgetRect(rtOuter); | |
1225 pRect->Offset(rtOuter.left, rtOuter.top); | |
1226 } | |
1227 } | |
1228 FWL_ShowCaret(pOuter, bVisible, pRect); | |
1229 } | |
1230 | |
1231 bool IFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) { | |
1232 if (!m_bSetRange) | |
1233 return true; | |
1234 | |
1235 CFX_WideString wsOld, wsText; | |
1236 m_EdtEngine.GetText(wsText, 0); | |
1237 if (wsText.IsEmpty()) { | |
1238 if (cNum == L'0') | |
1239 return false; | |
1240 return true; | |
1241 } | |
1242 | |
1243 int32_t caretPos = m_EdtEngine.GetCaretPos(); | |
1244 if (CountSelRanges() == 0) { | |
1245 if (cNum == L'0' && caretPos == 0) | |
1246 return false; | |
1247 | |
1248 int32_t nLen = wsText.GetLength(); | |
1249 CFX_WideString l = wsText.Mid(0, caretPos); | |
1250 CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos); | |
1251 CFX_WideString wsNew = l + cNum + r; | |
1252 if (wsNew.GetInteger() <= m_iMax) | |
1253 return true; | |
1254 return false; | |
1255 } | |
1256 | |
1257 if (wsText.GetInteger() <= m_iMax) | |
1258 return true; | |
1259 return false; | |
1260 } | |
1261 | |
1262 void IFWL_Edit::InitCaret() { | |
1263 if (!m_pCaret) { | |
1264 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) { | |
1265 m_pCaret.reset(new CFWL_Caret( | |
1266 m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this)); | |
1267 m_pCaret->SetParent(this); | |
1268 m_pCaret->SetStates(m_pProperties->m_dwStates); | |
1269 } | |
1270 } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) == | |
1271 0) { | |
1272 m_pCaret.reset(); | |
1273 } | |
1274 } | |
1275 | |
1276 void IFWL_Edit::ClearRecord() { | |
1277 m_iCurRecord = -1; | |
1278 m_DoRecords.clear(); | |
1279 } | |
1280 | |
1281 void IFWL_Edit::ProcessInsertError(int32_t iError) { | |
1282 if (iError != -2) | |
1283 return; | |
1284 | |
1285 CFWL_EvtTextFull textFullEvent; | |
1286 textFullEvent.m_pSrcTarget = this; | |
1287 DispatchEvent(&textFullEvent); | |
1288 } | |
1289 | |
1290 void IFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) { | |
1291 if (!pMessage) | |
1292 return; | |
1293 | |
1294 CFWL_MessageType dwMsgCode = pMessage->GetClassID(); | |
1295 switch (dwMsgCode) { | |
1296 case CFWL_MessageType::SetFocus: | |
1297 case CFWL_MessageType::KillFocus: | |
1298 OnFocusChanged(pMessage, dwMsgCode == CFWL_MessageType::SetFocus); | |
1299 break; | |
1300 case CFWL_MessageType::Mouse: { | |
1301 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); | |
1302 switch (pMsg->m_dwCmd) { | |
1303 case FWL_MouseCommand::LeftButtonDown: | |
1304 OnLButtonDown(pMsg); | |
1305 break; | |
1306 case FWL_MouseCommand::LeftButtonUp: | |
1307 OnLButtonUp(pMsg); | |
1308 break; | |
1309 case FWL_MouseCommand::LeftButtonDblClk: | |
1310 OnButtonDblClk(pMsg); | |
1311 break; | |
1312 case FWL_MouseCommand::Move: | |
1313 OnMouseMove(pMsg); | |
1314 break; | |
1315 case FWL_MouseCommand::RightButtonDown: | |
1316 DoButtonDown(pMsg); | |
1317 break; | |
1318 default: | |
1319 break; | |
1320 } | |
1321 break; | |
1322 } | |
1323 case CFWL_MessageType::Key: { | |
1324 CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); | |
1325 if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown) | |
1326 OnKeyDown(pKey); | |
1327 else if (pKey->m_dwCmd == FWL_KeyCommand::Char) | |
1328 OnChar(pKey); | |
1329 break; | |
1330 } | |
1331 default: | |
1332 break; | |
1333 } | |
1334 IFWL_Widget::OnProcessMessage(pMessage); | |
1335 } | |
1336 | |
1337 void IFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) { | |
1338 if (!pEvent) | |
1339 return; | |
1340 if (pEvent->GetClassID() != CFWL_EventType::Scroll) | |
1341 return; | |
1342 | |
1343 IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; | |
1344 if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) || | |
1345 (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) { | |
1346 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); | |
1347 OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget), | |
1348 pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos); | |
1349 } | |
1350 } | |
1351 | |
1352 void IFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics, | |
1353 const CFX_Matrix* pMatrix) { | |
1354 DrawWidget(pGraphics, pMatrix); | |
1355 } | |
1356 | |
1357 void IFWL_Edit::DoButtonDown(CFWL_MsgMouse* pMsg) { | |
1358 if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) | |
1359 SetFocus(true); | |
1360 | |
1361 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
1362 if (!pPage) | |
1363 return; | |
1364 | |
1365 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
1366 DeviceToEngine(pt); | |
1367 bool bBefore = true; | |
1368 int32_t nIndex = pPage->GetCharIndex(pt, bBefore); | |
1369 if (nIndex < 0) | |
1370 nIndex = 0; | |
1371 | |
1372 m_EdtEngine.SetCaretPos(nIndex, bBefore); | |
1373 } | |
1374 | |
1375 void IFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) { | |
1376 uint32_t dwStyleEx = GetStylesEx(); | |
1377 bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret); | |
1378 if (bSet) { | |
1379 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; | |
1380 | |
1381 UpdateVAlignment(); | |
1382 UpdateOffset(); | |
1383 UpdateCaret(); | |
1384 } else if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) { | |
1385 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; | |
1386 ShowCaret(false); | |
1387 if ((dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) { | |
1388 int32_t nSel = CountSelRanges(); | |
1389 if (nSel > 0) { | |
1390 ClearSelections(); | |
1391 bRepaint = true; | |
1392 } | |
1393 m_EdtEngine.SetCaretPos(0, true); | |
1394 UpdateOffset(); | |
1395 } | |
1396 ClearRecord(); | |
1397 } | |
1398 | |
1399 LayoutScrollBar(); | |
1400 if (!bRepaint) | |
1401 return; | |
1402 | |
1403 CFX_RectF rtInvalidate; | |
1404 rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width, | |
1405 m_pProperties->m_rtWidget.height); | |
1406 Repaint(&rtInvalidate); | |
1407 } | |
1408 | |
1409 void IFWL_Edit::OnLButtonDown(CFWL_MsgMouse* pMsg) { | |
1410 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) | |
1411 return; | |
1412 | |
1413 m_bLButtonDown = true; | |
1414 SetGrab(true); | |
1415 DoButtonDown(pMsg); | |
1416 int32_t nIndex = m_EdtEngine.GetCaretPos(); | |
1417 bool bRepaint = false; | |
1418 if (m_EdtEngine.CountSelRanges() > 0) { | |
1419 m_EdtEngine.ClearSelection(); | |
1420 bRepaint = true; | |
1421 } | |
1422 | |
1423 if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) { | |
1424 int32_t iStart = std::min(m_nSelStart, nIndex); | |
1425 int32_t iEnd = std::max(m_nSelStart, nIndex); | |
1426 m_EdtEngine.AddSelRange(iStart, iEnd - iStart); | |
1427 bRepaint = true; | |
1428 } else { | |
1429 m_nSelStart = nIndex; | |
1430 } | |
1431 if (bRepaint) | |
1432 Repaint(&m_rtEngine); | |
1433 } | |
1434 | |
1435 void IFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) { | |
1436 m_bLButtonDown = false; | |
1437 SetGrab(false); | |
1438 } | |
1439 | |
1440 void IFWL_Edit::OnButtonDblClk(CFWL_MsgMouse* pMsg) { | |
1441 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
1442 if (!pPage) | |
1443 return; | |
1444 | |
1445 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
1446 DeviceToEngine(pt); | |
1447 int32_t nCount = 0; | |
1448 int32_t nIndex = pPage->SelectWord(pt, nCount); | |
1449 if (nIndex < 0) | |
1450 return; | |
1451 | |
1452 m_EdtEngine.AddSelRange(nIndex, nCount); | |
1453 m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false); | |
1454 Repaint(&m_rtEngine); | |
1455 } | |
1456 | |
1457 void IFWL_Edit::OnMouseMove(CFWL_MsgMouse* pMsg) { | |
1458 if (m_nSelStart == -1 || !m_bLButtonDown) | |
1459 return; | |
1460 | |
1461 IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0); | |
1462 if (!pPage) | |
1463 return; | |
1464 | |
1465 CFX_PointF pt(pMsg->m_fx, pMsg->m_fy); | |
1466 DeviceToEngine(pt); | |
1467 bool bBefore = true; | |
1468 int32_t nIndex = pPage->GetCharIndex(pt, bBefore); | |
1469 m_EdtEngine.SetCaretPos(nIndex, bBefore); | |
1470 nIndex = m_EdtEngine.GetCaretPos(); | |
1471 m_EdtEngine.ClearSelection(); | |
1472 | |
1473 if (nIndex == m_nSelStart) | |
1474 return; | |
1475 | |
1476 int32_t nLen = m_EdtEngine.GetTextLength(); | |
1477 if (m_nSelStart >= nLen) | |
1478 m_nSelStart = nLen; | |
1479 | |
1480 m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex), | |
1481 FXSYS_abs(nIndex - m_nSelStart)); | |
1482 } | |
1483 | |
1484 void IFWL_Edit::OnKeyDown(CFWL_MsgKey* pMsg) { | |
1485 FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone; | |
1486 bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift); | |
1487 bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl); | |
1488 uint32_t dwKeyCode = pMsg->m_dwKeyCode; | |
1489 switch (dwKeyCode) { | |
1490 case FWL_VKEY_Left: { | |
1491 MoveCaret = MC_Left; | |
1492 break; | |
1493 } | |
1494 case FWL_VKEY_Right: { | |
1495 MoveCaret = MC_Right; | |
1496 break; | |
1497 } | |
1498 case FWL_VKEY_Up: { | |
1499 MoveCaret = MC_Up; | |
1500 break; | |
1501 } | |
1502 case FWL_VKEY_Down: { | |
1503 MoveCaret = MC_Down; | |
1504 break; | |
1505 } | |
1506 case FWL_VKEY_Home: { | |
1507 MoveCaret = bCtrl ? MC_Home : MC_LineStart; | |
1508 break; | |
1509 } | |
1510 case FWL_VKEY_End: { | |
1511 MoveCaret = bCtrl ? MC_End : MC_LineEnd; | |
1512 break; | |
1513 } | |
1514 case FWL_VKEY_Insert: | |
1515 break; | |
1516 case FWL_VKEY_Delete: { | |
1517 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
1518 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
1519 break; | |
1520 } | |
1521 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
1522 #if (_FX_OS_ == _FX_MACOSX_) | |
1523 m_EdtEngine.Delete(nCaret, true); | |
1524 #else | |
1525 m_EdtEngine.Delete(nCaret); | |
1526 #endif | |
1527 break; | |
1528 } | |
1529 case FWL_VKEY_F2: | |
1530 break; | |
1531 case FWL_VKEY_Tab: { | |
1532 DispatchKeyEvent(pMsg); | |
1533 break; | |
1534 } | |
1535 default: | |
1536 break; | |
1537 } | |
1538 if (MoveCaret != MC_MoveNone) | |
1539 m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl); | |
1540 } | |
1541 | |
1542 void IFWL_Edit::OnChar(CFWL_MsgKey* pMsg) { | |
1543 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) || | |
1544 (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) { | |
1545 return; | |
1546 } | |
1547 | |
1548 int32_t iError = 0; | |
1549 FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode); | |
1550 int32_t nCaret = m_EdtEngine.GetCaretPos(); | |
1551 switch (c) { | |
1552 case FWL_VKEY_Back: | |
1553 m_EdtEngine.Delete(nCaret, true); | |
1554 break; | |
1555 case FWL_VKEY_NewLine: | |
1556 case FWL_VKEY_Escape: | |
1557 break; | |
1558 case FWL_VKEY_Tab: { | |
1559 iError = m_EdtEngine.Insert(nCaret, L"\t", 1); | |
1560 break; | |
1561 } | |
1562 case FWL_VKEY_Return: { | |
1563 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) { | |
1564 iError = m_EdtEngine.Insert(nCaret, L"\n", 1); | |
1565 } | |
1566 break; | |
1567 } | |
1568 default: { | |
1569 if (!m_pWidgetMgr->IsFormDisabled()) { | |
1570 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) { | |
1571 if (((pMsg->m_dwKeyCode < FWL_VKEY_0) && | |
1572 (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) || | |
1573 pMsg->m_dwKeyCode > FWL_VKEY_9) { | |
1574 break; | |
1575 } | |
1576 if (!ValidateNumberChar(c)) | |
1577 break; | |
1578 } | |
1579 } | |
1580 #if (_FX_OS_ == _FX_MACOSX_) | |
1581 if (pMsg->m_dwFlags & FWL_KEYFLAG_Command) | |
1582 #else | |
1583 if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) | |
1584 #endif | |
1585 { | |
1586 break; | |
1587 } | |
1588 iError = m_EdtEngine.Insert(nCaret, &c, 1); | |
1589 break; | |
1590 } | |
1591 } | |
1592 if (iError < 0) | |
1593 ProcessInsertError(iError); | |
1594 } | |
1595 | |
1596 bool IFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar, | |
1597 FWL_SCBCODE dwCode, | |
1598 FX_FLOAT fPos) { | |
1599 CFX_SizeF fs; | |
1600 pScrollBar->GetRange(&fs.x, &fs.y); | |
1601 FX_FLOAT iCurPos = pScrollBar->GetPos(); | |
1602 FX_FLOAT fStep = pScrollBar->GetStepSize(); | |
1603 switch (dwCode) { | |
1604 case FWL_SCBCODE::Min: { | |
1605 fPos = fs.x; | |
1606 break; | |
1607 } | |
1608 case FWL_SCBCODE::Max: { | |
1609 fPos = fs.y; | |
1610 break; | |
1611 } | |
1612 case FWL_SCBCODE::StepBackward: { | |
1613 fPos -= fStep; | |
1614 if (fPos < fs.x + fStep / 2) { | |
1615 fPos = fs.x; | |
1616 } | |
1617 break; | |
1618 } | |
1619 case FWL_SCBCODE::StepForward: { | |
1620 fPos += fStep; | |
1621 if (fPos > fs.y - fStep / 2) { | |
1622 fPos = fs.y; | |
1623 } | |
1624 break; | |
1625 } | |
1626 case FWL_SCBCODE::PageBackward: { | |
1627 fPos -= pScrollBar->GetPageSize(); | |
1628 if (fPos < fs.x) { | |
1629 fPos = fs.x; | |
1630 } | |
1631 break; | |
1632 } | |
1633 case FWL_SCBCODE::PageForward: { | |
1634 fPos += pScrollBar->GetPageSize(); | |
1635 if (fPos > fs.y) { | |
1636 fPos = fs.y; | |
1637 } | |
1638 break; | |
1639 } | |
1640 case FWL_SCBCODE::Pos: | |
1641 case FWL_SCBCODE::TrackPos: | |
1642 case FWL_SCBCODE::None: | |
1643 break; | |
1644 case FWL_SCBCODE::EndScroll: | |
1645 return false; | |
1646 } | |
1647 if (iCurPos == fPos) | |
1648 return true; | |
1649 | |
1650 pScrollBar->SetPos(fPos); | |
1651 pScrollBar->SetTrackPos(fPos); | |
1652 UpdateOffset(pScrollBar, fPos - iCurPos); | |
1653 UpdateCaret(); | |
1654 | |
1655 CFX_RectF rect; | |
1656 GetWidgetRect(rect); | |
1657 CFX_RectF rtInvalidate; | |
1658 rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2); | |
1659 Repaint(&rtInvalidate); | |
1660 return true; | |
1661 } | |
OLD | NEW |