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