diff --git a/Import/CMakeLists.txt b/Import/CMakeLists.txt index 2ed1782c..fc9310e1 100644 --- a/Import/CMakeLists.txt +++ b/Import/CMakeLists.txt @@ -170,7 +170,6 @@ if (WORKFLOW_COMPILER) endif() if (GACUI_CORE) - install(FILES VlppParser.h DESTINATION include) install(FILES GacUI.h DESTINATION include) install(FILES GacUI.UnitTest.h DESTINATION include) install(FILES GacUI.UnitTest.UI.h DESTINATION include) diff --git a/Import/GacUI.UnitTest.UI.cpp b/Import/GacUI.UnitTest.UI.cpp index 1dc3c50a..987fea45 100644 --- a/Import/GacUI.UnitTest.UI.cpp +++ b/Import/GacUI.UnitTest.UI.cpp @@ -1573,7 +1573,7 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor) ::vl::__vwsn::This(this->__vwsn_precompile_27)->SetVerticalAlwaysVisible(false); } { - ::vl::__vwsn::This(this->__vwsn_precompile_27)->SetReadonly(true); + ::vl::__vwsn::This(this->__vwsn_precompile_27)->SetEditMode(::vl::presentation::controls::GuiDocumentEditMode::Selectable); } (this->__vwsn_precompile_28 = ::vl::__vwsn::This(this->__vwsn_precompile_27)->GetBoundsComposition()); { @@ -1602,7 +1602,7 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor) ::vl::__vwsn::This(this->__vwsn_precompile_30)->SetVerticalAlwaysVisible(false); } { - ::vl::__vwsn::This(this->__vwsn_precompile_30)->SetReadonly(true); + ::vl::__vwsn::This(this->__vwsn_precompile_30)->SetEditMode(::vl::presentation::controls::GuiDocumentEditMode::Selectable); } (this->__vwsn_precompile_31 = ::vl::__vwsn::This(this->__vwsn_precompile_30)->GetBoundsComposition()); { @@ -1654,7 +1654,7 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor) ::vl::__vwsn::This(this->__vwsn_precompile_33)->SetVerticalAlwaysVisible(false); } { - ::vl::__vwsn::This(this->__vwsn_precompile_33)->SetReadonly(true); + ::vl::__vwsn::This(this->__vwsn_precompile_33)->SetEditMode(::vl::presentation::controls::GuiDocumentEditMode::Selectable); } (this->__vwsn_precompile_34 = ::vl::__vwsn::This(this->__vwsn_precompile_33)->GetBoundsComposition()); { @@ -1683,7 +1683,7 @@ Class (::gaclib_controls::UnitTestSnapshotViewerWindowConstructor) ::vl::__vwsn::This(this->__vwsn_precompile_36)->SetVerticalAlwaysVisible(false); } { - ::vl::__vwsn::This(this->__vwsn_precompile_36)->SetReadonly(true); + ::vl::__vwsn::This(this->__vwsn_precompile_36)->SetEditMode(::vl::presentation::controls::GuiDocumentEditMode::Selectable); } (this->__vwsn_precompile_37 = ::vl::__vwsn::This(this->__vwsn_precompile_36)->GetBoundsComposition()); { diff --git a/Import/GacUI.Windows.cpp b/Import/GacUI.Windows.cpp index a1d1a494..8ade843b 100644 --- a/Import/GacUI.Windows.cpp +++ b/Import/GacUI.Windows.cpp @@ -1979,7 +1979,10 @@ WindowsController } } - asyncService.ExecuteAsyncTasks(); + if (uMsg == WM_MOVING || uMsg == WM_SIZING) + { + asyncService.ExecuteAsyncTasks(); + } return skipDefaultProcedure; } @@ -5504,269 +5507,6 @@ GuiDirect2DElementRenderer } } -/*********************************************************************** -.\DIRECT2D\RENDERERS\GUIGRAPHICSTEXTRENDERERSWINDOWSDIRECT2D.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace elements_windows_d2d - { - using namespace collections; - -/*********************************************************************** -GuiColorizedTextElementRenderer -***********************************************************************/ - - void GuiColorizedTextElementRenderer::CreateTextBrush(IWindowsDirect2DRenderTarget* _renderTarget) - { - if(_renderTarget) - { - colors.Resize(element->GetColors().Count()); - // TODO: (enumerable) foreach:indexed - for(vint i=0;iGetColors().Get(i); - ColorEntryResource newEntry; - - newEntry.normal.text=entry.normal.text; - newEntry.normal.textBrush=_renderTarget->CreateDirect2DBrush(newEntry.normal.text); - newEntry.normal.background=entry.normal.background; - newEntry.normal.backgroundBrush=_renderTarget->CreateDirect2DBrush(newEntry.normal.background); - newEntry.selectedFocused.text=entry.selectedFocused.text; - newEntry.selectedFocused.textBrush=_renderTarget->CreateDirect2DBrush(newEntry.selectedFocused.text); - newEntry.selectedFocused.background=entry.selectedFocused.background; - newEntry.selectedFocused.backgroundBrush=_renderTarget->CreateDirect2DBrush(newEntry.selectedFocused.background); - newEntry.selectedUnfocused.text=entry.selectedUnfocused.text; - newEntry.selectedUnfocused.textBrush=_renderTarget->CreateDirect2DBrush(newEntry.selectedUnfocused.text); - newEntry.selectedUnfocused.background=entry.selectedUnfocused.background; - newEntry.selectedUnfocused.backgroundBrush=_renderTarget->CreateDirect2DBrush(newEntry.selectedUnfocused.background); - colors[i]=newEntry; - } - } - } - - void GuiColorizedTextElementRenderer::DestroyTextBrush(IWindowsDirect2DRenderTarget* _renderTarget) - { - if(_renderTarget) - { - // TODO: (enumerable) foreach - for(vint i=0;iDestroyDirect2DBrush(colors[i].normal.text); - _renderTarget->DestroyDirect2DBrush(colors[i].normal.background); - _renderTarget->DestroyDirect2DBrush(colors[i].selectedFocused.text); - _renderTarget->DestroyDirect2DBrush(colors[i].selectedFocused.background); - _renderTarget->DestroyDirect2DBrush(colors[i].selectedUnfocused.text); - _renderTarget->DestroyDirect2DBrush(colors[i].selectedUnfocused.background); - } - colors.Resize(0); - } - } - - void GuiColorizedTextElementRenderer::CreateCaretBrush(IWindowsDirect2DRenderTarget* _renderTarget) - { - if(_renderTarget) - { - oldCaretColor=element->GetCaretColor(); - caretBrush=_renderTarget->CreateDirect2DBrush(oldCaretColor); - } - } - - void GuiColorizedTextElementRenderer::DestroyCaretBrush(IWindowsDirect2DRenderTarget* _renderTarget) - { - if(_renderTarget) - { - if(caretBrush) - { - _renderTarget->DestroyDirect2DBrush(oldCaretColor); - caretBrush=0; - } - } - } - - void GuiColorizedTextElementRenderer::ColorChanged() - { - DestroyTextBrush(renderTarget); - CreateTextBrush(renderTarget); - } - - void GuiColorizedTextElementRenderer::FontChanged() - { - IWindowsDirect2DResourceManager* resourceManager = GetWindowsDirect2DResourceManager(); - if (textFormat) - { - element->GetLines().SetCharMeasurer(nullptr); - resourceManager->DestroyDirect2DTextFormat(oldFont); - resourceManager->DestroyDirect2DCharMeasurer(oldFont); - } - oldFont = element->GetFont(); - if (oldFont.fontFamily == L"") oldFont.fontFamily = windows::GetWindowsNativeController()->ResourceService()->GetDefaultFont().fontFamily; - if (oldFont.size == 0) oldFont.size = 12; - - textFormat = resourceManager->CreateDirect2DTextFormat(oldFont); - element->GetLines().SetCharMeasurer(resourceManager->CreateDirect2DCharMeasurer(oldFont).Obj()); - } - - text::CharMeasurer* GuiColorizedTextElementRenderer::GetCharMeasurer() - { - return 0; - } - - void GuiColorizedTextElementRenderer::InitializeInternal() - { - textFormat=0; - caretBrush=0; - element->SetCallback(this); - } - - void GuiColorizedTextElementRenderer::FinalizeInternal() - { - element->SetCallback(nullptr); - DestroyTextBrush(renderTarget); - DestroyCaretBrush(renderTarget); - - IWindowsDirect2DResourceManager* resourceManager=GetWindowsDirect2DResourceManager(); - if(textFormat) - { - resourceManager->DestroyDirect2DTextFormat(oldFont); - resourceManager->DestroyDirect2DCharMeasurer(oldFont); - } - } - - void GuiColorizedTextElementRenderer::RenderTargetChangedInternal(IWindowsDirect2DRenderTarget* oldRenderTarget, IWindowsDirect2DRenderTarget* newRenderTarget) - { - DestroyTextBrush(oldRenderTarget); - DestroyCaretBrush(oldRenderTarget); - CreateTextBrush(newRenderTarget); - CreateCaretBrush(newRenderTarget); - element->GetLines().SetRenderTarget(newRenderTarget); - } - - void GuiColorizedTextElementRenderer::Render(Rect bounds) - { - if (renderTarget) - { - ID2D1RenderTarget* d2dRenderTarget = renderTarget->GetDirect2DRenderTarget(); - wchar_t passwordChar = element->GetPasswordChar(); - Point viewPosition = element->GetViewPosition(); - Rect viewBounds(viewPosition, bounds.GetSize()); - vint startRow = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x1, viewBounds.y1)).row; - vint endRow = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x2, viewBounds.y2)).row; - TextPos selectionBegin = element->GetCaretBegin() < element->GetCaretEnd() ? element->GetCaretBegin() : element->GetCaretEnd(); - TextPos selectionEnd = element->GetCaretBegin() > element->GetCaretEnd() ? element->GetCaretBegin() : element->GetCaretEnd(); - bool focused = element->GetFocused(); - - renderTarget->SetTextAntialias(oldFont.antialias, oldFont.verticalAntialias); - - for (vint row = startRow; row <= endRow; row++) - { - Rect startRect = element->GetLines().GetRectFromTextPos(TextPos(row, 0)); - Point startPoint = startRect.LeftTop(); - vint startColumn = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x1, startPoint.y)).column; - vint endColumn = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x2, startPoint.y)).column; - - text::TextLine& line = element->GetLines().GetLine(row); - if (endColumn + 1 < line.dataLength && text::UTF16SPFirst(line.text[endColumn]) && text::UTF16SPSecond(line.text[startColumn + 1])) - { - endColumn++; - } - - vint x = startColumn == 0 ? 0 : line.att[startColumn - 1].rightOffset; - for (vint column = startColumn; column <= endColumn; column++) - { - bool inSelection = false; - if (selectionBegin.row == selectionEnd.row) - { - inSelection = (row == selectionBegin.row && selectionBegin.column <= column && column < selectionEnd.column); - } - else if (row == selectionBegin.row) - { - inSelection = selectionBegin.column <= column; - } - else if (row == selectionEnd.row) - { - inSelection = column < selectionEnd.column; - } - else - { - inSelection = selectionBegin.row < row && row < selectionEnd.row; - } - - bool crlf = column == line.dataLength; - vint colorIndex = crlf ? 0 : line.att[column].colorIndex; - if (colorIndex >= colors.Count()) - { - colorIndex = 0; - } - ColorItemResource& color = - !inSelection ? colors[colorIndex].normal : - focused ? colors[colorIndex].selectedFocused : - colors[colorIndex].selectedUnfocused; - vint x2 = crlf ? x + startRect.Height() / 2 : line.att[column].rightOffset; - vint tx = x - viewPosition.x + bounds.x1; - vint ty = startPoint.y - viewPosition.y + bounds.y1; - - if (color.background.a > 0) - { - d2dRenderTarget->FillRectangle(D2D1::RectF((FLOAT)tx, (FLOAT)ty, (FLOAT)(tx + (x2 - x)), (FLOAT)(ty + startRect.Height())), color.backgroundBrush); - } - if (!crlf) - { - UINT32 count = text::UTF16SPFirst(line.text[column]) && column + 1 < line.dataLength && text::UTF16SPSecond(line.text[column + 1]) ? 2 : 1; - d2dRenderTarget->DrawText( - (passwordChar ? &passwordChar : &line.text[column]), - count, - textFormat->textFormat.Obj(), - D2D1::RectF((FLOAT)tx, (FLOAT)ty, (FLOAT)tx + 1, (FLOAT)ty + 1), - color.textBrush, - D2D1_DRAW_TEXT_OPTIONS_NO_SNAP, - DWRITE_MEASURING_MODE_GDI_NATURAL - ); - if (count == 2) column++; - } - x = x2; - } - } - - if (element->GetCaretVisible() && element->GetLines().IsAvailable(element->GetCaretEnd())) - { - Point caretPoint = element->GetLines().GetPointFromTextPos(element->GetCaretEnd()); - vint height = element->GetLines().GetRowHeight(); - Point p1(caretPoint.x - viewPosition.x + bounds.x1, caretPoint.y - viewPosition.y + bounds.y1 + 1); - Point p2(caretPoint.x - viewPosition.x + bounds.x1, caretPoint.y + height - viewPosition.y + bounds.y1 - 1); - d2dRenderTarget->DrawLine( - D2D1::Point2F((FLOAT)p1.x + 0.5f, (FLOAT)p1.y), - D2D1::Point2F((FLOAT)p2.x + 0.5f, (FLOAT)p2.y), - caretBrush - ); - d2dRenderTarget->DrawLine( - D2D1::Point2F((FLOAT)p1.x - 0.5f, (FLOAT)p1.y), - D2D1::Point2F((FLOAT)p2.x - 0.5f, (FLOAT)p2.y), - caretBrush - ); - } - } - } - - void GuiColorizedTextElementRenderer::OnElementStateChanged() - { - if(renderTarget) - { - Color caretColor=element->GetCaretColor(); - if(oldCaretColor!=caretColor) - { - DestroyCaretBrush(renderTarget); - CreateCaretBrush(renderTarget); - } - } - } - } - } -} - /*********************************************************************** .\DIRECT2D\RENDERERS\GUIGRAPHICSWINDOWSDIRECT2D.CPP ***********************************************************************/ @@ -5958,64 +5698,6 @@ CachedResourceAllocator } }; - class CachedCharMeasurerAllocator : public GuiCachedResourceAllocatorBase> - { - protected: - class Direct2DCharMeasurer : public text::CharMeasurer - { - protected: - ComPtr font; - vint size; - - Size MeasureInternal(text::UnicodeCodePoint codePoint, IGuiGraphicsRenderTarget* renderTarget) - { - Size charSize(0, 0); - IDWriteTextLayout* textLayout = 0; - - UINT32 count = text::UTF16SPFirst(codePoint.characters[0]) && text::UTF16SPSecond(codePoint.characters[1]) ? 2 : 1; - HRESULT hr = GetWindowsDirect2DObjectProvider()->GetDirectWriteFactory()->CreateTextLayout( - codePoint.characters, - count, - font.Obj(), - 0, - 0, - &textLayout); - CHECK_ERROR(SUCCEEDED(hr), L"You should check HRESULT to see why it failed."); - - DWRITE_TEXT_METRICS metrics; - hr = textLayout->GetMetrics(&metrics); - if (!FAILED(hr)) - { - charSize = Size((vint)ceil(metrics.widthIncludingTrailingWhitespace), (vint)ceil(metrics.height)); - } - textLayout->Release(); - return charSize; - } - - vint MeasureWidthInternal(text::UnicodeCodePoint codePoint, IGuiGraphicsRenderTarget* renderTarget) - { - return MeasureInternal(codePoint, renderTarget).x; - } - - vint GetRowHeightInternal(IGuiGraphicsRenderTarget* renderTarget) - { - return MeasureInternal({ L' ' }, renderTarget).y; - } - public: - Direct2DCharMeasurer(ComPtr _font, vint _size) - :text::CharMeasurer(_size) - ,size(_size) - ,font(_font) - { - } - }; - public: - Ptr CreateInternal(const FontProperties& value) - { - return Ptr(new Direct2DCharMeasurer(CachedTextFormatAllocator::CreateDirect2DFont(value), value.size)); - } - }; - /*********************************************************************** WindowsDirect2DRenderTarget ***********************************************************************/ @@ -6367,7 +6049,6 @@ WindowsGDIResourceManager Ptr layoutProvider; CachedTextFormatAllocator textFormats; - CachedCharMeasurerAllocator charMeasurers; public: WindowsDirect2DResourceManager() { @@ -6424,16 +6105,6 @@ WindowsGDIResourceManager { textFormats.Destroy(fontProperties); } - - Ptr CreateDirect2DCharMeasurer(const FontProperties& fontProperties)override - { - return charMeasurers.Create(fontProperties); - } - - void DestroyDirect2DCharMeasurer(const FontProperties& fontProperties)override - { - charMeasurers.Destroy(fontProperties); - } }; } @@ -6505,9 +6176,8 @@ void RendererMainDirect2D(GuiHostedController* hostedController, bool raw) elements_windows_d2d::GuiSolidLabelElementRenderer::Register(); elements_windows_d2d::GuiImageFrameElementRenderer::Register(); elements_windows_d2d::GuiPolygonElementRenderer::Register(); - elements_windows_d2d::GuiColorizedTextElementRenderer::Register(); elements_windows_d2d::GuiDirect2DElementRenderer::Register(); - elements::GuiDocumentElement::GuiDocumentElementRenderer::Register(); + elements::GuiDocumentElementRenderer::Register(); if (hostedController) hostedController->Initialize(); if (raw) @@ -9991,219 +9661,6 @@ GuiGDIElementRenderer } } -/*********************************************************************** -.\GDI\RENDERERS\GUIGRAPHICSTEXTRENDERERSWINDOWSGDI.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace elements_windows_gdi - { - using namespace windows; - using namespace collections; - -/*********************************************************************** -GuiColorizedTextElementRenderer -***********************************************************************/ - - void GuiColorizedTextElementRenderer::DestroyColors() - { - auto resourceManager=GetWindowsGDIResourceManager(); - // TODO: (enumerable) foreach - for(vint i=0;iDestroyGdiBrush(colors[i].normal.background); - resourceManager->DestroyGdiBrush(colors[i].selectedFocused.background); - resourceManager->DestroyGdiBrush(colors[i].selectedUnfocused.background); - } - } - - void GuiColorizedTextElementRenderer::ColorChanged() - { - auto resourceManager=GetWindowsGDIResourceManager(); - ColorArray newColors; - newColors.Resize(element->GetColors().Count()); - // TODO: (enumerable) foreach:indexed - for(vint i=0;iGetColors().Get(i); - ColorEntryResource newEntry; - - newEntry.normal.text=entry.normal.text; - newEntry.normal.background=entry.normal.background; - newEntry.normal.backgroundBrush=resourceManager->CreateGdiBrush(newEntry.normal.background); - newEntry.selectedFocused.text=entry.selectedFocused.text; - newEntry.selectedFocused.background=entry.selectedFocused.background; - newEntry.selectedFocused.backgroundBrush=resourceManager->CreateGdiBrush(newEntry.selectedFocused.background); - newEntry.selectedUnfocused.text=entry.selectedUnfocused.text; - newEntry.selectedUnfocused.background=entry.selectedUnfocused.background; - newEntry.selectedUnfocused.backgroundBrush=resourceManager->CreateGdiBrush(newEntry.selectedUnfocused.background); - newColors[i]=newEntry; - } - - DestroyColors(); - CopyFrom(colors, newColors); - } - - void GuiColorizedTextElementRenderer::FontChanged() - { - auto resourceManager = GetWindowsGDIResourceManager(); - if (font) - { - element->GetLines().SetCharMeasurer(nullptr); - resourceManager->DestroyGdiFont(oldFont); - resourceManager->DestroyCharMeasurer(oldFont); - font = nullptr; - } - oldFont = element->GetFont(); - font = resourceManager->CreateGdiFont(oldFont); - element->GetLines().SetCharMeasurer(resourceManager->CreateCharMeasurer(oldFont).Obj()); - } - - void GuiColorizedTextElementRenderer::InitializeInternal() - { - auto resourceManager=GetWindowsGDIResourceManager(); - oldCaretColor=element->GetCaretColor(); - caretPen=resourceManager->CreateGdiPen(oldCaretColor); - element->SetCallback(this); - } - - void GuiColorizedTextElementRenderer::FinalizeInternal() - { - element->SetCallback(nullptr); - auto resourceManager=GetWindowsGDIResourceManager(); - if(font) - { - resourceManager->DestroyGdiFont(oldFont); - resourceManager->DestroyCharMeasurer(oldFont); - } - resourceManager->DestroyGdiPen(oldCaretColor); - DestroyColors(); - } - - void GuiColorizedTextElementRenderer::RenderTargetChangedInternal(IWindowsGDIRenderTarget* oldRenderTarget, IWindowsGDIRenderTarget* newRenderTarget) - { - element->GetLines().SetRenderTarget(newRenderTarget); - } - - void GuiColorizedTextElementRenderer::Render(Rect bounds) - { - if (renderTarget) - { - WinDC* dc = renderTarget->GetDC(); - dc->SetFont(font); - - wchar_t passwordChar = element->GetPasswordChar(); - Point viewPosition = element->GetViewPosition(); - Rect viewBounds(viewPosition, bounds.GetSize()); - vint startRow = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x1, viewBounds.y1)).row; - vint endRow = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x2, viewBounds.y2)).row; - TextPos selectionBegin = element->GetCaretBegin() < element->GetCaretEnd() ? element->GetCaretBegin() : element->GetCaretEnd(); - TextPos selectionEnd = element->GetCaretBegin() > element->GetCaretEnd() ? element->GetCaretBegin() : element->GetCaretEnd(); - bool focused = element->GetFocused(); - Ptr lastBrush = 0; - - for (vint row = startRow; row <= endRow; row++) - { - Rect startRect = element->GetLines().GetRectFromTextPos(TextPos(row, 0)); - Point startPoint = startRect.LeftTop(); - vint startColumn = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x1, startPoint.y)).column; - vint endColumn = element->GetLines().GetTextPosFromPoint(Point(viewBounds.x2, startPoint.y)).column; - - text::TextLine& line = element->GetLines().GetLine(row); - if (text::UTF16SPFirst(line.text[endColumn]) && endColumn + 1 < line.dataLength && text::UTF16SPSecond(line.text[startColumn + 1])) - { - endColumn++; - } - - vint x = startColumn == 0 ? 0 : line.att[startColumn - 1].rightOffset; - for (vint column = startColumn; column <= endColumn; column++) - { - bool inSelection = false; - if (selectionBegin.row == selectionEnd.row) - { - inSelection = (row == selectionBegin.row && selectionBegin.column <= column && column < selectionEnd.column); - } - else if (row == selectionBegin.row) - { - inSelection = selectionBegin.column <= column; - } - else if (row == selectionEnd.row) - { - inSelection = column < selectionEnd.column; - } - else - { - inSelection = selectionBegin.row < row && row < selectionEnd.row; - } - - bool crlf = column == line.dataLength; - vint colorIndex = crlf ? 0 : line.att[column].colorIndex; - if (colorIndex >= colors.Count()) - { - colorIndex = 0; - } - ColorItemResource& color = - !inSelection ? colors[colorIndex].normal : - focused ? colors[colorIndex].selectedFocused : - colors[colorIndex].selectedUnfocused; - vint x2 = crlf ? x + startRect.Height() / 2 : line.att[column].rightOffset; - vint tx = x - viewPosition.x + bounds.x1; - vint ty = startPoint.y - viewPosition.y + bounds.y1; - - if (color.background.a) - { - if (lastBrush != color.backgroundBrush) - { - lastBrush = color.backgroundBrush; - dc->SetBrush(lastBrush); - } - dc->FillRect(tx, ty, tx + (x2 - x), ty + startRect.Height()); - } - if (!crlf) - { - vint count = text::UTF16SPFirst(line.text[column]) && column + 1 < line.dataLength && text::UTF16SPSecond(line.text[column + 1]) ? 2 : 1; - if (color.text.a) - { - dc->SetTextColor(RGB(color.text.r, color.text.g, color.text.b)); - dc->DrawBuffer(tx, ty, (passwordChar ? &passwordChar : &line.text[column]), count); - } - if (count == 2) column++; - } - x = x2; - } - } - - if (element->GetCaretVisible() && element->GetLines().IsAvailable(element->GetCaretEnd())) - { - Point caretPoint = element->GetLines().GetPointFromTextPos(element->GetCaretEnd()); - vint height = element->GetLines().GetRowHeight(); - dc->SetPen(caretPen); - dc->MoveTo(caretPoint.x - viewPosition.x + bounds.x1, caretPoint.y - viewPosition.y + bounds.y1 + 1); - dc->LineTo(caretPoint.x - viewPosition.x + bounds.x1, caretPoint.y + height - viewPosition.y + bounds.y1 - 1); - dc->MoveTo(caretPoint.x - 1 - viewPosition.x + bounds.x1, caretPoint.y - viewPosition.y + bounds.y1 + 1); - dc->LineTo(caretPoint.x - 1 - viewPosition.x + bounds.x1, caretPoint.y + height - viewPosition.y + bounds.y1 - 1); - } - } - } - - void GuiColorizedTextElementRenderer::OnElementStateChanged() - { - Color caretColor=element->GetCaretColor(); - if(oldCaretColor!=caretColor) - { - auto resourceManager=GetWindowsGDIResourceManager(); - resourceManager->DestroyGdiPen(oldCaretColor); - oldCaretColor=caretColor; - caretPen=resourceManager->CreateGdiPen(oldCaretColor); - } - } - } - } -} - /*********************************************************************** .\GDI\RENDERERS\GUIGRAPHICSUNISCRIBE.CPP ***********************************************************************/ @@ -12918,64 +12375,6 @@ CachedResourceAllocator } }; - class CachedCharMeasurerAllocator : public GuiCachedResourceAllocatorBase> - { - protected: - class GdiCharMeasurer : public text::CharMeasurer - { - protected: - Ptr font; - vint size; - - Size MeasureInternal(text::UnicodeCodePoint codePoint, IGuiGraphicsRenderTarget* renderTarget) - { - if (renderTarget) - { - WindowsGDIRenderTarget* gdiRenderTarget = dynamic_cast(renderTarget); - WinDC* dc = gdiRenderTarget->GetDC(); - dc->SetFont(font); - - vint count = text::UTF16SPFirst(codePoint.characters[0]) && text::UTF16SPSecond(codePoint.characters[1]) ? 2 : 1; - SIZE size = dc->MeasureBuffer(codePoint.characters, count, -1); - return Size(size.cx, size.cy); - } - else - { - return Size(0, 0); - } - } - - vint MeasureWidthInternal(text::UnicodeCodePoint codePoint, IGuiGraphicsRenderTarget* renderTarget) - { - return MeasureInternal(codePoint, renderTarget).x; - } - - vint GetRowHeightInternal(IGuiGraphicsRenderTarget* renderTarget) - { - if (renderTarget) - { - return MeasureInternal({ L' ' }, renderTarget).y; - } - else - { - return size; - } - } - public: - GdiCharMeasurer(Ptr _font, vint _size) - : text::CharMeasurer(_size) - , size(_size) - , font(_font) - { - } - }; - public: - Ptr CreateInternal(const FontProperties& value) - { - return Ptr(new GdiCharMeasurer(CachedFontAllocator::CreateGdiFont(value), value.size)); - } - }; - /*********************************************************************** WindowsGDIResourceManager ***********************************************************************/ @@ -13069,7 +12468,6 @@ WindowsGDIResourceManager CachedPenAllocator pens; CachedBrushAllocator brushes; CachedFontAllocator fonts; - CachedCharMeasurerAllocator charMeasurers; ImageCacheList imageCaches; public: WindowsGDIResourceManager() @@ -13154,16 +12552,6 @@ WindowsGDIResourceManager fonts.Destroy(fontProperties); } - Ptr CreateCharMeasurer(const FontProperties& fontProperties)override - { - return charMeasurers.Create(fontProperties); - } - - void DestroyCharMeasurer(const FontProperties& fontProperties)override - { - charMeasurers.Destroy(fontProperties); - } - Ptr GetBitmap(INativeImageFrame* frame, bool enabled)override { Ptr cache = frame->GetCache(this); @@ -13260,9 +12648,8 @@ void RendererMainGDI(GuiHostedController* hostedController, bool raw) elements_windows_gdi::GuiSolidLabelElementRenderer::Register(); elements_windows_gdi::GuiImageFrameElementRenderer::Register(); elements_windows_gdi::GuiPolygonElementRenderer::Register(); - elements_windows_gdi::GuiColorizedTextElementRenderer::Register(); elements_windows_gdi::GuiGDIElementRenderer::Register(); - elements::GuiDocumentElement::GuiDocumentElementRenderer::Register(); + elements::GuiDocumentElementRenderer::Register(); if (hostedController) hostedController->Initialize(); if (raw) diff --git a/Import/GacUI.Windows.h b/Import/GacUI.Windows.h index cbd4af98..79b65851 100644 --- a/Import/GacUI.Windows.h +++ b/Import/GacUI.Windows.h @@ -195,8 +195,6 @@ Functionality public: virtual Direct2DTextFormatPackage* CreateDirect2DTextFormat(const FontProperties& fontProperties)=0; virtual void DestroyDirect2DTextFormat(const FontProperties& fontProperties)=0; - virtual Ptr CreateDirect2DCharMeasurer(const FontProperties& fontProperties)=0; - virtual void DestroyDirect2DCharMeasurer(const FontProperties& fontProperties)=0; }; extern IWindowsDirect2DResourceManager* GetWindowsDirect2DResourceManager(); @@ -503,85 +501,6 @@ Renderers #endif -/*********************************************************************** -.\DIRECT2D\RENDERERS\GUIGRAPHICSTEXTRENDERERSWINDOWSDIRECT2D.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Native Window::Direct2D Provider for Windows Implementation::Renderer - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTRENDERERSWINDOWSDIRECT2D -#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTRENDERERSWINDOWSDIRECT2D - - -namespace vl -{ - namespace presentation - { - namespace elements_windows_d2d - { - -/*********************************************************************** -Renderers -***********************************************************************/ - - class GuiColorizedTextElementRenderer : public GuiElementRendererBase, protected GuiColorizedTextElement::ICallback - { - friend class GuiElementRendererBase; - - public: - struct ColorItemResource - { - Color text; - ID2D1SolidColorBrush* textBrush; - Color background; - ID2D1SolidColorBrush* backgroundBrush; - }; - - struct ColorEntryResource - { - ColorItemResource normal; - ColorItemResource selectedFocused; - ColorItemResource selectedUnfocused; - - std::partial_ordering operator<=>(const ColorEntryResource&) const { return std::partial_ordering::unordered; } - bool operator==(const ColorEntryResource& value) const { return false; } - }; - - typedef collections::Array ColorArray; - protected: - FontProperties oldFont; - Direct2DTextFormatPackage* textFormat; - ColorArray colors; - Color oldCaretColor; - ID2D1SolidColorBrush* caretBrush; - - void CreateTextBrush(IWindowsDirect2DRenderTarget* _renderTarget); - void DestroyTextBrush(IWindowsDirect2DRenderTarget* _renderTarget); - void CreateCaretBrush(IWindowsDirect2DRenderTarget* _renderTarget); - void DestroyCaretBrush(IWindowsDirect2DRenderTarget* _renderTarget); - - void ColorChanged(); - void FontChanged(); - text::CharMeasurer* GetCharMeasurer(); - - void InitializeInternal(); - void FinalizeInternal(); - void RenderTargetChangedInternal(IWindowsDirect2DRenderTarget* oldRenderTarget, IWindowsDirect2DRenderTarget* newRenderTarget); - public: - void Render(Rect bounds)override; - void OnElementStateChanged()override; - }; - } - } -} - -#endif - /*********************************************************************** .\GDI\WINGDI.H ***********************************************************************/ @@ -1265,10 +1184,6 @@ UniscribeRun virtual void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)=0; }; -/*********************************************************************** -UniscribeTextRun -***********************************************************************/ - class UniscribeTextRun : public UniscribeRun { public: @@ -1293,10 +1208,6 @@ UniscribeTextRun void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)override; }; -/*********************************************************************** -UniscribeElementRun -***********************************************************************/ - class UniscribeEmbeddedObjectRun : public UniscribeRun { public: @@ -1337,6 +1248,21 @@ UniscribeVirtualLine /*********************************************************************** UniscribeLine + +Styles and embedded objects cut the whole line into multiple UniscribeFragment +Uniscribe cut the whole line into multiple UniscribeItem +Both of them making multiple UniscribeRun +Any UniscribeTextRun will not cross multiple UniscribeFragment or UniscribeItem +Any UniscribeEmbeddedObjectRun will be exactly one UniscribeFragment + +During layout given wrapLine/availableWidth/alignment +Multiple UniscribeVirtualLine will be created +One UniscribeTextRun may cross multiple UniscribeVirtualLine when a long word is broken into lines +UniscribeEmbeddedObjectRun will not cross multiple UniscribeVirtualLine + +In UniscribeTextRun, wchar_t and glyph are in multiple-to-multiple relationship +After generating glyphs, which are things to render, layout is performed on glyphs +UniscribeEmbeddedObjectRun will be treated as a single glyph ***********************************************************************/ class UniscribeLine : public Object @@ -1515,8 +1441,6 @@ Functionality virtual void DestroyGdiBrush(Color color)=0; virtual Ptr CreateGdiFont(const FontProperties& fontProperties)=0; virtual void DestroyGdiFont(const FontProperties& fontProperties)=0; - virtual Ptr CreateCharMeasurer(const FontProperties& fontProperties)=0; - virtual void DestroyCharMeasurer(const FontProperties& fontProperties)=0; virtual Ptr GetBitmap(INativeImageFrame* frame, bool enabled)=0; virtual void DestroyBitmapCache(INativeImageFrame* frame)=0; @@ -1765,79 +1689,6 @@ Renderers #endif -/*********************************************************************** -.\GDI\RENDERERS\GUIGRAPHICSTEXTRENDERERSWINDOWSGDI.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Native Window::GDI Provider for Windows Implementation::Renderer - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTRENDERERSWINDOWSGDI -#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTRENDERERSWINDOWSGDI - - -namespace vl -{ - namespace presentation - { - namespace elements_windows_gdi - { - -/*********************************************************************** -Renderers -***********************************************************************/ - - class GuiColorizedTextElementRenderer : public GuiElementRendererBase, protected GuiColorizedTextElement::ICallback - { - friend class GuiElementRendererBase; - - public: - struct ColorItemResource - { - Color text; - Color background; - Ptr backgroundBrush; - }; - - struct ColorEntryResource - { - ColorItemResource normal; - ColorItemResource selectedFocused; - ColorItemResource selectedUnfocused; - - std::partial_ordering operator<=>(const ColorEntryResource&) const { return std::partial_ordering::unordered; } - bool operator==(const ColorEntryResource& value){return false;} - }; - - typedef collections::Array ColorArray; - protected: - FontProperties oldFont; - Ptr font; - ColorArray colors; - Color oldCaretColor; - Ptr caretPen; - - void DestroyColors(); - void ColorChanged(); - void FontChanged(); - - void InitializeInternal(); - void FinalizeInternal(); - void RenderTargetChangedInternal(IWindowsGDIRenderTarget* oldRenderTarget, IWindowsGDIRenderTarget* newRenderTarget); - public: - void Render(Rect bounds)override; - void OnElementStateChanged()override; - }; - } - } -} - -#endif - /*********************************************************************** .\SERVICESIMPL\WINDOWSCLIPBOARDSERVICE.H ***********************************************************************/ diff --git a/Import/GacUI.cpp b/Import/GacUI.cpp index ce045a82..54c75905 100644 --- a/Import/GacUI.cpp +++ b/Import/GacUI.cpp @@ -130,15 +130,6 @@ External Functions (Basic) return GetGuiGraphicsResourceManager()->CreateRawElement(); } -/*********************************************************************** -External Functions (Elements) -***********************************************************************/ - - text::TextLines* GuiColorizedTextElement_GetLines(GuiColorizedTextElement* thisObject) - { - return &thisObject->GetLines(); - } - /*********************************************************************** External Functions (Compositions) ***********************************************************************/ @@ -18009,7 +18000,7 @@ namespace vl } /*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTVIEWER.CPP +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTCOMMONINTERFACE.CPP ***********************************************************************/ namespace vl @@ -18022,75 +18013,6 @@ namespace vl using namespace elements; using namespace compositions; -/*********************************************************************** -GuiDocumentConfig -***********************************************************************/ - - GuiDocumentConfig GuiDocumentConfig::GetDocumentLabelDefaultConfig() - { - GuiDocumentConfig config; - config.autoExpand = true; - config.pasteAsPlainText = false; - config.wrapLine = true; - config.paragraphMode = GuiDocumentParagraphMode::Paragraph; - config.paragraphPadding = true; - config.doubleLineBreaksBetweenParagraph = true; - config.spaceForFlattenedLineBreak = false; - return config; - } - - GuiDocumentConfig GuiDocumentConfig::GetDocumentViewerDefaultConfig() - { - GuiDocumentConfig config; - config.autoExpand = false; - config.pasteAsPlainText = false; - config.wrapLine = true; - config.paragraphMode = GuiDocumentParagraphMode::Paragraph; - config.paragraphPadding = true; - config.doubleLineBreaksBetweenParagraph = true; - config.spaceForFlattenedLineBreak = false; - return config; - } - - GuiDocumentConfig GuiDocumentConfig::GetSinglelineTextBoxDefaultConfig() - { - GuiDocumentConfig config; - config.autoExpand = false; - config.pasteAsPlainText = true; - config.wrapLine = false; - config.paragraphMode = GuiDocumentParagraphMode::Singleline; - config.paragraphPadding = false; - config.doubleLineBreaksBetweenParagraph = false; - config.spaceForFlattenedLineBreak = false; - return config; - } - - GuiDocumentConfig GuiDocumentConfig::GetMultilineTextBoxDefaultConfig() - { - GuiDocumentConfig config; - config.autoExpand = false; - config.pasteAsPlainText = true; - config.wrapLine = false; - config.paragraphMode = GuiDocumentParagraphMode::Multiline; - config.paragraphPadding = false; - config.doubleLineBreaksBetweenParagraph = false; - config.spaceForFlattenedLineBreak = false; - return config; - } - - GuiDocumentConfig GuiDocumentConfig::OverrideConfig(const GuiDocumentConfig& toOverride, const GuiDocumentConfig& newConfig) - { - GuiDocumentConfig result = toOverride; - if (newConfig.autoExpand) result.autoExpand = newConfig.autoExpand; - if (newConfig.pasteAsPlainText) result.pasteAsPlainText = newConfig.pasteAsPlainText; - if (newConfig.wrapLine) result.wrapLine = newConfig.wrapLine; - if (newConfig.paragraphMode) result.paragraphMode = newConfig.paragraphMode; - if (newConfig.paragraphPadding) result.paragraphPadding = newConfig.paragraphPadding; - if (newConfig.doubleLineBreaksBetweenParagraph) result.doubleLineBreaksBetweenParagraph = newConfig.doubleLineBreaksBetweenParagraph; - if (newConfig.spaceForFlattenedLineBreak) result.spaceForFlattenedLineBreak = newConfig.spaceForFlattenedLineBreak; - return result; - } - /*********************************************************************** GuiDocumentItem ***********************************************************************/ @@ -18306,7 +18228,7 @@ GuiDocumentCommonInterface documentComposition = new GuiBoundsComposition; documentComposition->SetOwnedElement(Ptr(documentElement)); documentComposition->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElement); - documentComposition->SetAlignmentToParent(Margin(5, 5, 5, 5)); + documentComposition->SetAlignmentToParent(Margin(2, 2, 2, 2)); _container->AddChild(documentComposition); ReplaceMouseArea(_mouseArea); @@ -19529,6 +19451,120 @@ GuiDocumentCommonInterface return false; } } + } + } +} + + +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTCONFIG.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { +/*********************************************************************** +GuiDocumentConfig +***********************************************************************/ + + GuiDocumentConfig GuiDocumentConfig::GetDocumentLabelDefaultConfig() + { + GuiDocumentConfig config; + config.autoExpand = true; + config.pasteAsPlainText = false; + config.wrapLine = true; + config.paragraphMode = GuiDocumentParagraphMode::Paragraph; + config.paragraphPadding = true; + config.doubleLineBreaksBetweenParagraph = true; + config.spaceForFlattenedLineBreak = false; + return config; + } + + GuiDocumentConfig GuiDocumentConfig::GetDocumentViewerDefaultConfig() + { + GuiDocumentConfig config; + config.autoExpand = false; + config.pasteAsPlainText = false; + config.wrapLine = true; + config.paragraphMode = GuiDocumentParagraphMode::Paragraph; + config.paragraphPadding = true; + config.doubleLineBreaksBetweenParagraph = true; + config.spaceForFlattenedLineBreak = false; + return config; + } + + GuiDocumentConfig GuiDocumentConfig::GetSinglelineTextBoxDefaultConfig() + { + GuiDocumentConfig config; + config.autoExpand = false; + config.pasteAsPlainText = true; + config.wrapLine = false; + config.paragraphMode = GuiDocumentParagraphMode::Singleline; + config.paragraphPadding = false; + config.doubleLineBreaksBetweenParagraph = false; + config.spaceForFlattenedLineBreak = false; + return config; + } + + GuiDocumentConfig GuiDocumentConfig::GetMultilineTextBoxDefaultConfig() + { + GuiDocumentConfig config; + config.autoExpand = false; + config.pasteAsPlainText = true; + config.wrapLine = false; + config.paragraphMode = GuiDocumentParagraphMode::Multiline; + config.paragraphPadding = false; + config.doubleLineBreaksBetweenParagraph = false; + config.spaceForFlattenedLineBreak = false; + return config; + } + + GuiDocumentConfig GuiDocumentConfig::OverrideConfig(const GuiDocumentConfig& toOverride, const GuiDocumentConfig& newConfig) + { + GuiDocumentConfig result = toOverride; + if (newConfig.autoExpand) result.autoExpand = newConfig.autoExpand; + if (newConfig.pasteAsPlainText) result.pasteAsPlainText = newConfig.pasteAsPlainText; + if (newConfig.wrapLine) result.wrapLine = newConfig.wrapLine; + if (newConfig.paragraphMode) result.paragraphMode = newConfig.paragraphMode; + if (newConfig.paragraphPadding) result.paragraphPadding = newConfig.paragraphPadding; + if (newConfig.doubleLineBreaksBetweenParagraph) result.doubleLineBreaksBetweenParagraph = newConfig.doubleLineBreaksBetweenParagraph; + if (newConfig.spaceForFlattenedLineBreak) result.spaceForFlattenedLineBreak = newConfig.spaceForFlattenedLineBreak; + return result; + } + +/*********************************************************************** +GuiDocumentConfigEvaluated +***********************************************************************/ + + GuiDocumentConfigEvaluated::GuiDocumentConfigEvaluated(const GuiDocumentConfig& config) + : autoExpand(config.autoExpand.Value()) + , pasteAsPlainText(config.pasteAsPlainText.Value()) + , wrapLine(config.wrapLine.Value()) + , paragraphMode(config.paragraphMode.Value()) + , paragraphPadding(config.paragraphPadding.Value()) + , doubleLineBreaksBetweenParagraph(config.doubleLineBreaksBetweenParagraph.Value()) + , spaceForFlattenedLineBreak(config.spaceForFlattenedLineBreak.Value()) + { + } + } + } +} + + +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTVIEWER.CPP +***********************************************************************/ + +namespace vl +{ + namespace presentation + { + namespace controls + { + using namespace compositions; /*********************************************************************** GuiDocumentViewer @@ -19635,6 +19671,20 @@ GuiDocumentViewer SetSelectionText(value); } +/*********************************************************************** +GuiMultilineTextBox +***********************************************************************/ + + GuiMultilineTextBox::GuiMultilineTextBox(theme::ThemeName themeName, const GuiDocumentConfig& _config) + : GuiDocumentViewer(themeName, FixConfig(GuiDocumentConfig::OverrideConfig(GuiDocumentConfig::GetMultilineTextBoxDefaultConfig(), _config))) + { + SetEditMode(GuiDocumentEditMode::Editable); + } + + GuiMultilineTextBox::~GuiMultilineTextBox() + { + } + /*********************************************************************** GuiDocumentLabel ***********************************************************************/ @@ -19778,2063 +19828,34 @@ GuiDocumentLabel SelectAll(); SetSelectionText(value); } - } - } -} - - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUITEXTCOMMONINTERFACE.CPP -***********************************************************************/ -#include - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace elements::text; - using namespace compositions; - -/*********************************************************************** -GuiTextBoxCommonInterface::DefaultCallback -***********************************************************************/ - - GuiTextBoxCommonInterface::DefaultCallback::DefaultCallback(elements::GuiColorizedTextElement* _textElement, compositions::GuiGraphicsComposition* _textComposition) - :textElement(_textElement) - ,textComposition(_textComposition) - { - } - - GuiTextBoxCommonInterface::DefaultCallback::~DefaultCallback() - { - } - - TextPos GuiTextBoxCommonInterface::DefaultCallback::GetLeftWord(TextPos pos) - { - return pos; - } - - TextPos GuiTextBoxCommonInterface::DefaultCallback::GetRightWord(TextPos pos) - { - return pos; - } - - void GuiTextBoxCommonInterface::DefaultCallback::GetWord(TextPos pos, TextPos& begin, TextPos& end) - { - begin=pos; - end=pos; - } - - vint GuiTextBoxCommonInterface::DefaultCallback::GetPageRows() - { - return textComposition->GetCachedBounds().Height()/textElement->GetLines().GetRowHeight(); - } - - bool GuiTextBoxCommonInterface::DefaultCallback::BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText) - { - return true; - } - -/*********************************************************************** -GuiTextBoxCommonInterface -***********************************************************************/ - - void GuiTextBoxCommonInterface::InvokeUndoRedoChanged() - { - UndoRedoChanged.Execute(textControl->GetNotifyEventArguments()); - } - - void GuiTextBoxCommonInterface::InvokeModifiedChanged() - { - ModifiedChanged.Execute(textControl->GetNotifyEventArguments()); - } - - void GuiTextBoxCommonInterface::UpdateCaretPoint() - { - GuiGraphicsHost* host=textComposition->GetRelatedGraphicsHost(); - if(host) - { - Rect caret=textElement->GetLines().GetRectFromTextPos(textElement->GetCaretEnd()); - Point view=textElement->GetViewPosition(); - vint x=caret.x1-view.x; - vint y=caret.y2-view.y; - host->SetCaretPoint(Point(x, y), textComposition); - } - } - - void GuiTextBoxCommonInterface::Move(TextPos pos, bool shift) - { - TextPos oldBegin = textElement->GetCaretBegin(); - TextPos oldEnd = textElement->GetCaretEnd(); - -#if defined VCZH_MSVC - if (0 <= pos.row && pos.row < textElement->GetLines().GetCount()) - { - TextLine& line = textElement->GetLines().GetLine(pos.row); - if (pos.column > 0 && UTF16SPFirst(line.text[pos.column - 1]) && UTF16SPSecond(line.text[pos.column])) - { - if (pos < oldBegin) - { - pos.column--; - } - else if (pos > oldBegin) - { - pos.column++; - } - } - } -#endif - - pos = textElement->GetLines().Normalize(pos); - if (!shift) - { - textElement->SetCaretBegin(pos); - } - textElement->SetCaretEnd(pos); - if (textControl) - { - GuiGraphicsHost* host = textComposition->GetRelatedGraphicsHost(); - if (host) - { - if (host->GetFocusedComposition() == textControl->GetFocusableComposition()) - { - textElement->SetCaretVisible(true); - } - } - } - - Rect bounds = textElement->GetLines().GetRectFromTextPos(pos); - Rect view = Rect(textElement->GetViewPosition(), textComposition->GetCachedBounds().GetSize()); - Point viewPoint = view.LeftTop(); - - if (view.x2 > view.x1 && view.y2 > view.y1) - { - if (bounds.x1 < view.x1) - { - viewPoint.x = bounds.x1; - } - else if (bounds.x2 > view.x2) - { - viewPoint.x = bounds.x2 - view.Width(); - } - if (bounds.y1 < view.y1) - { - viewPoint.y = bounds.y1; - } - else if (bounds.y2 > view.y2) - { - viewPoint.y = bounds.y2 - view.Height(); - } - } - - callback->ScrollToView(viewPoint); - UpdateCaretPoint(); - - TextPos newBegin = textElement->GetCaretBegin(); - TextPos newEnd = textElement->GetCaretEnd(); - if (oldBegin != newBegin || oldEnd != newEnd) - { - ICommonTextEditCallback::TextCaretChangedStruct arguments; - arguments.oldBegin = oldBegin; - arguments.oldEnd = oldEnd; - arguments.newBegin = newBegin; - arguments.newEnd = newEnd; - arguments.editVersion = editVersion; - // TODO: (enumerable) foreach - for (vint i = 0; i < textEditCallbacks.Count(); i++) - { - textEditCallbacks[i]->TextCaretChanged(arguments); - } - SelectionChanged.Execute(textControl->GetNotifyEventArguments()); - } - } - - void GuiTextBoxCommonInterface::Modify(TextPos start, TextPos end, const WString& input, bool asKeyInput) - { - if(start>end) - { - TextPos temp=start; - start=end; - end=temp; - } - TextPos originalStart=start; - TextPos originalEnd=end; - WString originalText=textElement->GetLines().GetText(start, end); - WString inputText=input; - if(callback->BeforeModify(start, end, originalText, inputText)) - { - { - ICommonTextEditCallback::TextEditPreviewStruct arguments; - arguments.originalStart=originalStart; - arguments.originalEnd=originalEnd; - arguments.originalText=originalText; - arguments.inputText=inputText; - arguments.editVersion=editVersion; - arguments.keyInput=asKeyInput; - // TODO: (enumerable) foreach - for(vint i=0;iTextEditPreview(arguments); - } - - inputText=arguments.inputText; - if(originalStart!=arguments.originalStart || originalEnd!=arguments.originalEnd) - { - originalStart=arguments.originalStart; - originalEnd=arguments.originalEnd; - originalText=textElement->GetLines().GetText(originalStart, originalEnd); - start=originalStart; - end=originalEnd; - } - } - - SPIN_LOCK(elementModifyLock) - { - end=textElement->GetLines().Modify(start, end, inputText); - } - callback->AfterModify(originalStart, originalEnd, originalText, start, end, inputText); - - editVersion++; - { - ICommonTextEditCallback::TextEditNotifyStruct arguments; - arguments.originalStart=originalStart; - arguments.originalEnd=originalEnd; - arguments.originalText=originalText; - arguments.inputStart=start; - arguments.inputEnd=end; - arguments.inputText=inputText; - arguments.editVersion=editVersion; - arguments.keyInput=asKeyInput; - // TODO: (enumerable) foreach - for(vint i=0;iTextEditNotify(arguments); - } - } - - Move(end, false); - - // TODO: (enumerable) foreach - for(vint i=0;iTextEditFinished(editVersion); - } - - textControl->TextChanged.Execute(textControl->GetNotifyEventArguments()); - } - } - - bool GuiTextBoxCommonInterface::ProcessKey(VKEY code, bool shift, bool ctrl) - { - if(IGuiShortcutKeyItem* item=internalShortcutKeyManager->TryGetShortcut(ctrl, shift, false, code)) - { - GuiEventArgs arguments(textControl->GetBoundsComposition()); - item->Executed.Execute(arguments); - return true; - } - - TextPos begin=textElement->GetCaretBegin(); - TextPos end=textElement->GetCaretEnd(); - switch(code) - { - case VKEY::KEY_ESCAPE: - if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) - { - autoComplete->CloseList(); - return true; - } - break; - case VKEY::KEY_RETURN: - if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) - { - if(autoComplete->ApplySelectedListItem()) - { - preventEnterDueToAutoComplete=true; - return true; - } - } - break; - case VKEY::KEY_UP: - if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) - { - autoComplete->SelectPreviousListItem(); - } - else - { - end.row--; - Move(end, shift); - } - return true; - case VKEY::KEY_DOWN: - if(autoComplete && autoComplete->IsListOpening() && !shift && !ctrl) - { - autoComplete->SelectNextListItem(); - } - else - { - end.row++; - Move(end, shift); - } - return true; - case VKEY::KEY_LEFT: - { - if(ctrl) - { - Move(callback->GetLeftWord(end), shift); - } - else - { - if(end.column==0) - { - if(end.row>0) - { - end.row--; - end=textElement->GetLines().Normalize(end); - end.column=textElement->GetLines().GetLine(end.row).dataLength; - } - } - else - { - end.column--; - } - Move(end, shift); - } - } - return true; - case VKEY::KEY_RIGHT: - { - if(ctrl) - { - Move(callback->GetRightWord(end), shift); - } - else - { - if(end.column==textElement->GetLines().GetLine(end.row).dataLength) - { - if(end.rowGetLines().GetCount()-1) - { - end.row++; - end.column=0; - } - } - else - { - end.column++; - } - Move(end, shift); - } - } - return true; - case VKEY::KEY_HOME: - { - if(ctrl) - { - Move(TextPos(0, 0), shift); - } - else - { - end.column=0; - Move(end, shift); - } - } - return true; - case VKEY::KEY_END: - { - if(ctrl) - { - end.row=textElement->GetLines().GetCount()-1; - } - end.column=textElement->GetLines().GetLine(end.row).dataLength; - Move(end, shift); - } - return true; - case VKEY::KEY_PRIOR: - { - end.row-=callback->GetPageRows(); - Move(end, shift); - } - return true; - case VKEY::KEY_NEXT: - { - end.row+=callback->GetPageRows(); - Move(end, shift); - } - return true; - case VKEY::KEY_BACK: - if(!readonly) - { - if(ctrl && !shift) - { - ProcessKey(VKEY::KEY_LEFT, true, true); - ProcessKey(VKEY::KEY_BACK, false, false); - } - else if(!ctrl && shift) - { - ProcessKey(VKEY::KEY_UP, true, false); - ProcessKey(VKEY::KEY_BACK, false, false); - } - else - { - if(begin==end) - { - ProcessKey(VKEY::KEY_LEFT, true, false); - } - SetSelectionTextAsKeyInput(L""); - } - return true; - } - break; - case VKEY::KEY_DELETE: - if(!readonly) - { - if(ctrl && !shift) - { - ProcessKey(VKEY::KEY_RIGHT, true, true); - ProcessKey(VKEY::KEY_DELETE, false, false); - } - else if(!ctrl && shift) - { - ProcessKey(VKEY::KEY_DOWN, true, false); - ProcessKey(VKEY::KEY_DELETE, false, false); - } - else - { - if(begin==end) - { - ProcessKey(VKEY::KEY_RIGHT, true, false); - } - SetSelectionTextAsKeyInput(L""); - } - return true; - } - break; - default:; - } - return false; - } - - void GuiTextBoxCommonInterface::OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - textElement->SetFocused(true); - textElement->SetCaretVisible(true); - UpdateCaretPoint(); - } - - void GuiTextBoxCommonInterface::OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - textElement->SetFocused(false); - textElement->SetCaretVisible(false); - } - - void GuiTextBoxCommonInterface::OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments) - { - textElement->SetCaretVisible(!textElement->GetCaretVisible()); - } - - void GuiTextBoxCommonInterface::OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) - { - dragging=true; - TextPos pos=GetNearestTextPos(Point(arguments.x, arguments.y)); - Move(pos, arguments.shift); - } - } - - void GuiTextBoxCommonInterface::OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) - { - dragging=false; - } - } - - void GuiTextBoxCommonInterface::OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) - { - if(dragging) - { - TextPos pos=GetNearestTextPos(Point(arguments.x, arguments.y)); - Move(pos, true); - } - } - } - - void GuiTextBoxCommonInterface::OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments) - { - if(textControl->GetVisuallyEnabled() && arguments.compositionSource==arguments.eventSource) - { - if(ProcessKey(arguments.code, arguments.shift, arguments.ctrl)) - { - arguments.handled=true; - } - } - } - - void GuiTextBoxCommonInterface::OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments) - { - if (preventEnterDueToAutoComplete) - { - preventEnterDueToAutoComplete = false; - if (arguments.code == (wchar_t)VKEY::KEY_RETURN) - { - return; - } - } - if (textControl->GetVisuallyEnabled() && arguments.compositionSource == arguments.eventSource) - { - if (!readonly && - arguments.code != (wchar_t)VKEY::KEY_ESCAPE && - arguments.code != (wchar_t)VKEY::KEY_BACK && - (arguments.code != (wchar_t)VKEY::KEY_TAB || textControl->GetAcceptTabInput()) && - !arguments.ctrl) - { - SetSelectionTextAsKeyInput(WString::FromChar(arguments.code)); - } - } - } - - void GuiTextBoxCommonInterface::Install( - elements::GuiColorizedTextElement* _textElement, - compositions::GuiGraphicsComposition* _textComposition, - GuiControl* _textControl, - compositions::GuiGraphicsComposition* eventComposition, - compositions::GuiGraphicsComposition* focusableComposition - ) - { - textElement=_textElement; - textComposition=_textComposition; - textControl=_textControl; - textComposition->SetAssociatedCursor(GetCurrentController()->ResourceService()->GetSystemCursor(INativeCursor::IBeam)); - SelectionChanged.SetAssociatedComposition(eventComposition); - UndoRedoChanged.SetAssociatedComposition(eventComposition); - ModifiedChanged.SetAssociatedComposition(eventComposition); - - undoRedoProcessor->UndoRedoChanged.Add(this, &GuiTextBoxCommonInterface::InvokeUndoRedoChanged); - undoRedoProcessor->ModifiedChanged.Add(this, &GuiTextBoxCommonInterface::InvokeModifiedChanged); - - focusableComposition->GetEventReceiver()->gotFocus.AttachMethod(this, &GuiTextBoxCommonInterface::OnGotFocus); - focusableComposition->GetEventReceiver()->lostFocus.AttachMethod(this, &GuiTextBoxCommonInterface::OnLostFocus); - focusableComposition->GetEventReceiver()->caretNotify.AttachMethod(this, &GuiTextBoxCommonInterface::OnCaretNotify); - textComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiTextBoxCommonInterface::OnLeftButtonDown); - textComposition->GetEventReceiver()->leftButtonUp.AttachMethod(this, &GuiTextBoxCommonInterface::OnLeftButtonUp); - textComposition->GetEventReceiver()->mouseMove.AttachMethod(this, &GuiTextBoxCommonInterface::OnMouseMove); - focusableComposition->GetEventReceiver()->keyDown.AttachMethod(this, &GuiTextBoxCommonInterface::OnKeyDown); - focusableComposition->GetEventReceiver()->charInput.AttachMethod(this, &GuiTextBoxCommonInterface::OnCharInput); - - // TODO: (enumerable) foreach - for(vint i=0;iAttach(textElement, elementModifyLock, textComposition ,editVersion); - } - } - - GuiTextBoxCommonInterface::ICallback* GuiTextBoxCommonInterface::GetCallback() - { - return callback; - } - - void GuiTextBoxCommonInterface::SetCallback(ICallback* value) - { - callback=value; - } - - bool GuiTextBoxCommonInterface::AttachTextEditCallback(Ptr value) - { - if(textEditCallbacks.Contains(value.Obj())) - { - return false; - } - else - { - textEditCallbacks.Add(value); - if(textElement) - { - value->Attach(textElement, elementModifyLock, textComposition, editVersion); - } - return true; - } - } - - bool GuiTextBoxCommonInterface::DetachTextEditCallback(Ptr value) - { - if(textEditCallbacks.Remove(value.Obj())) - { - value->Detach(); - return true; - } - else - { - return false; - } - } - - void GuiTextBoxCommonInterface::AddShortcutCommand(VKEY key, const Func& eventHandler) - { - IGuiShortcutKeyItem* item=internalShortcutKeyManager->CreateNewShortcut(true, false, false, key); - item->Executed.AttachLambda([=](GuiGraphicsComposition* sender, GuiEventArgs& arguments) - { - eventHandler(); - }); - } - - elements::GuiColorizedTextElement* GuiTextBoxCommonInterface::GetTextElement() - { - return textElement; - } - - void GuiTextBoxCommonInterface::UnsafeSetText(const WString& value) - { - if(textElement) - { - TextPos end; - if(textElement->GetLines().GetCount()>0) - { - end.row=textElement->GetLines().GetCount()-1; - end.column=textElement->GetLines().GetLine(end.row).dataLength; - } - Modify(TextPos(), end, value, false); - } - } - - GuiTextBoxCommonInterface::GuiTextBoxCommonInterface() - :textElement(0) - ,textComposition(0) - ,editVersion(0) - ,textControl(0) - ,callback(0) - ,dragging(false) - ,readonly(false) - ,preventEnterDueToAutoComplete(false) - { - undoRedoProcessor=Ptr(new GuiTextBoxUndoRedoProcessor); - AttachTextEditCallback(undoRedoProcessor); - - internalShortcutKeyManager=Ptr(new GuiShortcutKeyManager); - AddShortcutCommand(VKEY::KEY_Z, Func(this, &GuiTextBoxCommonInterface::Undo)); - AddShortcutCommand(VKEY::KEY_Y, Func(this, &GuiTextBoxCommonInterface::Redo)); - AddShortcutCommand(VKEY::KEY_A, Func(this, &GuiTextBoxCommonInterface::SelectAll)); - AddShortcutCommand(VKEY::KEY_X, Func(this, &GuiTextBoxCommonInterface::Cut)); - AddShortcutCommand(VKEY::KEY_C, Func(this, &GuiTextBoxCommonInterface::Copy)); - AddShortcutCommand(VKEY::KEY_V, Func(this, &GuiTextBoxCommonInterface::Paste)); - } - - GuiTextBoxCommonInterface::~GuiTextBoxCommonInterface() - { - if(colorizer) - { - DetachTextEditCallback(colorizer); - colorizer=0; - } - if(undoRedoProcessor) - { - DetachTextEditCallback(undoRedoProcessor); - undoRedoProcessor=0; - } - - // TODO: (enumerable) foreach - for(vint i=0;iDetach(); - } - textEditCallbacks.Clear(); - } - - //================ clipboard operations - - bool GuiTextBoxCommonInterface::CanCut() - { - return !readonly && textElement->GetCaretBegin()!=textElement->GetCaretEnd() && textElement->GetPasswordChar()==L'\0'; - } - - bool GuiTextBoxCommonInterface::CanCopy() - { - return textElement->GetCaretBegin()!=textElement->GetCaretEnd() && textElement->GetPasswordChar()==L'\0'; - } - - bool GuiTextBoxCommonInterface::CanPaste() - { - if (!readonly && textElement->GetPasswordChar() == L'\0') - { - auto reader = GetCurrentController()->ClipboardService()->ReadClipboard(); - return reader->ContainsText(); - } - return false; - } - - bool GuiTextBoxCommonInterface::Cut() - { - if (!CanCut()) return false; - auto writer = GetCurrentController()->ClipboardService()->WriteClipboard(); - writer->SetText(GetSelectionText()); - writer->Submit(); - SetSelectionText(L""); - return true; - } - - bool GuiTextBoxCommonInterface::Copy() - { - if (!CanCopy()) return false; - auto writer = GetCurrentController()->ClipboardService()->WriteClipboard(); - writer->SetText(GetSelectionText()); - writer->Submit(); - return true; - } - - bool GuiTextBoxCommonInterface::Paste() - { - if (!CanPaste()) return false; - auto reader = GetCurrentController()->ClipboardService()->ReadClipboard(); - SetSelectionText(reader->GetText()); - return true; - } - - //================ editing control - - bool GuiTextBoxCommonInterface::GetReadonly() - { - return readonly; - } - - void GuiTextBoxCommonInterface::SetReadonly(bool value) - { - readonly=value; - } - - //================ text operations - - void GuiTextBoxCommonInterface::Select(TextPos begin, TextPos end) - { - Move(begin, false); - Move(end, true); - } - - void GuiTextBoxCommonInterface::SelectAll() - { - vint row=textElement->GetLines().GetCount()-1; - Move(TextPos(0, 0), false); - Move(TextPos(row, textElement->GetLines().GetLine(row).dataLength), true); - } - - WString GuiTextBoxCommonInterface::GetSelectionText() - { - TextPos selectionBegin=textElement->GetCaretBegin()GetCaretEnd()?textElement->GetCaretBegin():textElement->GetCaretEnd(); - TextPos selectionEnd=textElement->GetCaretBegin()>textElement->GetCaretEnd()?textElement->GetCaretBegin():textElement->GetCaretEnd(); - return textElement->GetLines().GetText(selectionBegin, selectionEnd); - } - - void GuiTextBoxCommonInterface::SetSelectionText(const WString& value) - { - Modify(textElement->GetCaretBegin(), textElement->GetCaretEnd(), value, false); - } - - void GuiTextBoxCommonInterface::SetSelectionTextAsKeyInput(const WString& value) - { - Modify(textElement->GetCaretBegin(), textElement->GetCaretEnd(), value, true); - } - - WString GuiTextBoxCommonInterface::GetRowText(vint row) - { - TextPos start=textElement->GetLines().Normalize(TextPos(row, 0)); - TextPos end=TextPos(start.row, textElement->GetLines().GetLine(start.row).dataLength); - return GetFragmentText(start, end); - } - - vint GuiTextBoxCommonInterface::GetRowCount() - { - return textElement->GetLines().GetCount(); - } - - WString GuiTextBoxCommonInterface::GetFragmentText(TextPos start, TextPos end) - { - start=textElement->GetLines().Normalize(start); - end=textElement->GetLines().Normalize(end); - return textElement->GetLines().GetText(start, end); - } - - TextPos GuiTextBoxCommonInterface::GetCaretBegin() - { - return textElement->GetCaretBegin(); - } - - TextPos GuiTextBoxCommonInterface::GetCaretEnd() - { - return textElement->GetCaretEnd(); - } - - TextPos GuiTextBoxCommonInterface::GetCaretSmall() - { - TextPos c1=GetCaretBegin(); - TextPos c2=GetCaretEnd(); - return c1c2?c1:c2; - } - - //================ position query - - vint GuiTextBoxCommonInterface::GetRowWidth(vint row) - { - return textElement->GetLines().GetRowWidth(row); - } - - vint GuiTextBoxCommonInterface::GetRowHeight() - { - return textElement->GetLines().GetRowHeight(); - } - - vint GuiTextBoxCommonInterface::GetMaxWidth() - { - return textElement->GetLines().GetMaxWidth(); - } - - vint GuiTextBoxCommonInterface::GetMaxHeight() - { - return textElement->GetLines().GetMaxHeight(); - } - - TextPos GuiTextBoxCommonInterface::GetTextPosFromPoint(Point point) - { - Point view=textElement->GetViewPosition(); - return textElement->GetLines().GetTextPosFromPoint(Point(point.x+view.x, point.y+view.y)); - } - - Point GuiTextBoxCommonInterface::GetPointFromTextPos(TextPos pos) - { - Point view=textElement->GetViewPosition(); - Point result=textElement->GetLines().GetPointFromTextPos(pos); - return Point(result.x-view.x, result.y-view.y); - } - - Rect GuiTextBoxCommonInterface::GetRectFromTextPos(TextPos pos) - { - Point view=textElement->GetViewPosition(); - Rect result=textElement->GetLines().GetRectFromTextPos(pos); - return Rect(Point(result.x1-view.x, result.y1-view.y), result.GetSize()); - } - - TextPos GuiTextBoxCommonInterface::GetNearestTextPos(Point point) - { - Point viewPosition=textElement->GetViewPosition(); - Point mousePosition=Point(point.x+viewPosition.x, point.y+viewPosition.y); - TextPos pos=textElement->GetLines().GetTextPosFromPoint(mousePosition); - if(pos.columnGetLines().GetLine(pos.row).dataLength) - { - Rect rect=textElement->GetLines().GetRectFromTextPos(pos); - if(abs((int)(rect.x1-mousePosition.x))>=abs((int)(rect.x2-1-mousePosition.x))) - { - pos.column++; - } - } - return pos; - } - - //================ colorizing - - Ptr GuiTextBoxCommonInterface::GetColorizer() - { - return colorizer; - } - - void GuiTextBoxCommonInterface::SetColorizer(Ptr value) - { - if (!filledDefaultColors) - { - filledDefaultColors = true; - CopyFrom(defaultColors, GetTextElement()->GetColors()); - } - - if(colorizer) - { - DetachTextEditCallback(colorizer); - } - colorizer=value; - if(colorizer) - { - AttachTextEditCallback(colorizer); - GetTextElement()->SetColors(colorizer->GetColors()); - } - else - { - GetTextElement()->SetColors(defaultColors); - GetTextElement()->ResetTextColorIndex(0); - } - } - - //================ auto complete - - Ptr GuiTextBoxCommonInterface::GetAutoComplete() - { - return autoComplete; - } - - void GuiTextBoxCommonInterface::SetAutoComplete(Ptr value) - { - if(autoComplete) - { - DetachTextEditCallback(autoComplete); - } - autoComplete=value; - if(autoComplete) - { - AttachTextEditCallback(autoComplete); - } - } - - //================ undo redo control - - vuint GuiTextBoxCommonInterface::GetEditVersion() - { - return editVersion; - } - - bool GuiTextBoxCommonInterface::CanUndo() - { - return !readonly && undoRedoProcessor->CanUndo(); - } - - bool GuiTextBoxCommonInterface::CanRedo() - { - return !readonly && undoRedoProcessor->CanRedo(); - } - - void GuiTextBoxCommonInterface::ClearUndoRedo() - { - undoRedoProcessor->ClearUndoRedo(); - } - - bool GuiTextBoxCommonInterface::GetModified() - { - return undoRedoProcessor->GetModified(); - } - - void GuiTextBoxCommonInterface::NotifyModificationSaved() - { - undoRedoProcessor->NotifyModificationSaved(); - } - - bool GuiTextBoxCommonInterface::Undo() - { - if(CanUndo()) - { - return undoRedoProcessor->Undo(); - } - else - { - return false; - } - } - - bool GuiTextBoxCommonInterface::Redo() - { - if(CanRedo()) - { - return undoRedoProcessor->Redo(); - } - else - { - return false; - } - } - } - } -} - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUITEXTCONTROLS.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace elements::text; - using namespace compositions; - using namespace collections; - -/*********************************************************************** -GuiMultilineTextBox::DefaultTextElementOperatorCallback -***********************************************************************/ - - GuiMultilineTextBox::TextElementOperatorCallback::TextElementOperatorCallback(GuiMultilineTextBox* _textControl) - :GuiTextBoxCommonInterface::DefaultCallback( - _textControl->textElement, - _textControl->textComposition - ) - ,textControl(_textControl) - { - } - - void GuiMultilineTextBox::TextElementOperatorCallback::AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText) - { - textControl->CalculateView(); - } - - void GuiMultilineTextBox::TextElementOperatorCallback::ScrollToView(Point point) - { - point.x+=TextMargin; - point.y+=TextMargin; - Point oldPoint = textControl->GetViewPosition(); - vint marginX=0; - vint marginY=0; - if(oldPoint.xpoint.x) - { - marginX=-TextMargin; - } - if(oldPoint.ypoint.y) - { - marginY=-TextMargin; - } - textControl->SetViewPosition(Point(point.x + marginX, point.y + marginY)); - } - - vint GuiMultilineTextBox::TextElementOperatorCallback::GetTextMargin() - { - return TextMargin; - } - -/*********************************************************************** -GuiMultilineTextBox::CommandExecutor -***********************************************************************/ - - GuiMultilineTextBox::CommandExecutor::CommandExecutor(GuiMultilineTextBox* _textBox) - :textBox(_textBox) - { - } - - GuiMultilineTextBox::CommandExecutor::~CommandExecutor() - { - } - - void GuiMultilineTextBox::CommandExecutor::UnsafeSetText(const WString& value) - { - textBox->UnsafeSetText(value); - } - -/*********************************************************************** -GuiMultilineTextBox -***********************************************************************/ - - void GuiMultilineTextBox::BeforeControlTemplateUninstalled_() - { - auto ct = TypedControlTemplateObject(false); - if (!ct) return; - - ct->SetCommands(nullptr); - } - - void GuiMultilineTextBox::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - Array colors(1); - colors[0] = ct->GetTextColor(); - textElement->SetColors(colors); - textElement->SetCaretColor(ct->GetCaretColor()); - ct->SetCommands(commandExecutor.Obj()); - } - - void GuiMultilineTextBox::UpdateVisuallyEnabled() - { - GuiControl::UpdateVisuallyEnabled(); - textElement->SetVisuallyEnabled(GetVisuallyEnabled()); - } - - void GuiMultilineTextBox::UpdateDisplayFont() - { - GuiControl::UpdateDisplayFont(); - textElement->SetFont(GetDisplayFont()); - CalculateViewAndSetScroll(); - } - - void GuiMultilineTextBox::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) - { - CalculateViewAndSetScroll(); - GuiScrollView::OnRenderTargetChanged(renderTarget); - } - - Size GuiMultilineTextBox::QueryFullSize() - { - TextLines& lines = textElement->GetLines(); - return Size(lines.GetMaxWidth() + TextMargin * 2, lines.GetMaxHeight() + TextMargin * 2); - } - - void GuiMultilineTextBox::UpdateView(Rect viewBounds) - { - textElement->SetViewPosition(viewBounds.LeftTop() - Size(TextMargin, TextMargin)); - } - - void GuiMultilineTextBox::CalculateViewAndSetScroll() - { - auto ct = TypedControlTemplateObject(true); - CalculateView(); - vint smallMove = textElement->GetLines().GetRowHeight(); - vint bigMove = smallMove * 5; - - if (auto scroll = ct->GetHorizontalScroll()) - { - scroll->SetSmallMove(smallMove); - scroll->SetBigMove(bigMove); - } - - if (auto scroll = ct->GetVerticalScroll()) - { - scroll->SetSmallMove(smallMove); - scroll->SetBigMove(bigMove); - } - } - - void GuiMultilineTextBox::OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(GetVisuallyEnabled()) - { - SetFocused(); - } - } - - GuiMultilineTextBox::GuiMultilineTextBox(theme::ThemeName themeName) - :GuiScrollView(themeName) - { - textElement = GuiColorizedTextElement::Create(); - textElement->SetFont(GetDisplayFont()); - - textComposition = new GuiBoundsComposition; - textComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); - textComposition->SetOwnedElement(Ptr(textElement)); - containerComposition->AddChild(textComposition); - - callback = Ptr(new TextElementOperatorCallback(this)); - commandExecutor = Ptr(new CommandExecutor(this)); - - SetAcceptTabInput(true); - SetFocusableComposition(boundsComposition); - Install(textElement, textComposition, this, boundsComposition, focusableComposition); - SetCallback(callback.Obj()); - - boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); - boundsComposition->GetEventReceiver()->middleButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); - boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiMultilineTextBox::OnBoundsMouseButtonDown); - } - - GuiMultilineTextBox::~GuiMultilineTextBox() - { - } - - const WString& GuiMultilineTextBox::GetText() - { - text = textElement->GetLines().GetText(); - return text; - } - - void GuiMultilineTextBox::SetText(const WString& value) - { - UnsafeSetText(value); - textElement->SetCaretBegin(TextPos(0, 0)); - textElement->SetCaretEnd(TextPos(0, 0)); - CalculateView(); - } - -/*********************************************************************** -GuiSinglelineTextBox::DefaultTextElementOperatorCallback -***********************************************************************/ - - GuiSinglelineTextBox::TextElementOperatorCallback::TextElementOperatorCallback(GuiSinglelineTextBox* _textControl) - :GuiTextBoxCommonInterface::DefaultCallback( - _textControl->textElement, - _textControl->textComposition - ) - { - } - - bool GuiSinglelineTextBox::TextElementOperatorCallback::BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText) - { - vint length = inputText.Length(); - const wchar_t* input = inputText.Buffer(); - for (vint i = 0; i < length; i++) - { - if (*input == 0 || *input == L'\r' || *input == L'\n') - { - length = i; - break; - } - } - if (length != inputText.Length()) - { - if (length == 0) - { - // if the first line is empty after adjustment - // the input should just be canceled - // to prevent from making noise in undo - return false; - } - inputText = inputText.Left(length); - } - return true; - } - - void GuiSinglelineTextBox::TextElementOperatorCallback::AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText) - { - } - - void GuiSinglelineTextBox::TextElementOperatorCallback::ScrollToView(Point point) - { - vint newX=point.x; - vint oldX=textElement->GetViewPosition().x; - vint marginX=0; - if(oldXnewX) - { - marginX=-TextMargin; - } - - newX+=marginX; - vint minX=-TextMargin; - vint maxX=textElement->GetLines().GetMaxWidth()+TextMargin-textComposition->GetCachedBounds().Width(); - if(newX>=maxX) - { - newX=maxX-1; - } - if(newXSetViewPosition(Point(newX, -TextMargin)); - } - - vint GuiSinglelineTextBox::TextElementOperatorCallback::GetTextMargin() - { - return TextMargin; - } /*********************************************************************** GuiSinglelineTextBox ***********************************************************************/ - void GuiSinglelineTextBox::BeforeControlTemplateUninstalled_() + GuiSinglelineTextBox::GuiSinglelineTextBox(theme::ThemeName themeName, const GuiDocumentConfig& _config) + : GuiDocumentLabel(themeName, FixConfig(GuiDocumentConfig::OverrideConfig(GuiDocumentConfig::GetSinglelineTextBoxDefaultConfig(), _config))) { - } - - void GuiSinglelineTextBox::AfterControlTemplateInstalled_(bool initialize) - { - auto ct = TypedControlTemplateObject(true); - Array colors(1); - colors[0] = ct->GetTextColor(); - textElement->SetColors(colors); - textElement->SetCaretColor(ct->GetCaretColor()); - } - - void GuiSinglelineTextBox::UpdateVisuallyEnabled() - { - GuiControl::UpdateVisuallyEnabled(); - textElement->SetVisuallyEnabled(GetVisuallyEnabled()); - } - - void GuiSinglelineTextBox::UpdateDisplayFont() - { - GuiControl::UpdateDisplayFont(); - textElement->SetFont(GetDisplayFont()); - RearrangeTextElement(); - } - - void GuiSinglelineTextBox::RearrangeTextElement() - { - textCompositionTable->SetRowOption( - 1, - GuiCellOption::AbsoluteOption( - textElement->GetLines().GetRowHeight() + 2 * TextMargin) - ); - } - - void GuiSinglelineTextBox::OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget) - { - GuiControl::OnRenderTargetChanged(renderTarget); - RearrangeTextElement(); - } - - void GuiSinglelineTextBox::OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments) - { - if(GetVisuallyEnabled()) - { - SetFocused(); - } - } - - GuiSinglelineTextBox::GuiSinglelineTextBox(theme::ThemeName themeName) - :GuiControl(themeName) - { - textElement = GuiColorizedTextElement::Create(); - textElement->SetFont(GetDisplayFont()); - textElement->SetViewPosition(Point(-GuiSinglelineTextBox::TextMargin, -GuiSinglelineTextBox::TextMargin)); - - textCompositionTable = new GuiTableComposition; - textCompositionTable->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); - textCompositionTable->SetAlignmentToParent(Margin(0, 0, 0, 0)); - textCompositionTable->SetRowsAndColumns(3, 1); - textCompositionTable->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); - textCompositionTable->SetRowOption(1, GuiCellOption::AbsoluteOption(0)); - textCompositionTable->SetRowOption(2, GuiCellOption::PercentageOption(0.5)); - textCompositionTable->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); - containerComposition->AddChild(textCompositionTable); - - textComposition = new GuiCellComposition; - textComposition->SetOwnedElement(Ptr(textElement)); - textCompositionTable->AddChild(textComposition); - textComposition->SetSite(1, 0, 1, 1); - - callback = Ptr(new TextElementOperatorCallback(this)); - SetAcceptTabInput(true); - SetFocusableComposition(boundsComposition); - Install(textElement, textComposition, this, boundsComposition, focusableComposition); - SetCallback(callback.Obj()); - - boundsComposition->GetEventReceiver()->leftButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); - boundsComposition->GetEventReceiver()->middleButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); - boundsComposition->GetEventReceiver()->rightButtonDown.AttachMethod(this, &GuiSinglelineTextBox::OnBoundsMouseButtonDown); + SetEditMode(GuiDocumentEditMode::Editable); } GuiSinglelineTextBox::~GuiSinglelineTextBox() { } - const WString& GuiSinglelineTextBox::GetText() - { - text = textElement->GetLines().GetText(); - return text; - } - - void GuiSinglelineTextBox::SetText(const WString& value) - { - UnsafeSetText(value); - textElement->SetCaretBegin(TextPos(0, 0)); - textElement->SetCaretEnd(TextPos(0, 0)); - } - wchar_t GuiSinglelineTextBox::GetPasswordChar() { - return textElement->GetPasswordChar(); + return documentElement->GetPasswordChar(); } void GuiSinglelineTextBox::SetPasswordChar(wchar_t value) { - textElement->SetPasswordChar(value); + documentElement->SetPasswordChar(value); } } } } -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTAUTOCOMPLETE.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace collections; - -/*********************************************************************** -GuiTextBoxAutoCompleteBase::TextListControlProvider -***********************************************************************/ - - GuiTextBoxAutoCompleteBase::TextListControlProvider::TextListControlProvider(TemplateProperty controlTemplate) - { - autoCompleteList = new GuiTextList(theme::ThemeName::TextList); - if (controlTemplate) - { - autoCompleteList->SetControlTemplate(controlTemplate); - } - autoCompleteList->SetHorizontalAlwaysVisible(false); - autoCompleteList->SetVerticalAlwaysVisible(false); - } - - GuiTextBoxAutoCompleteBase::TextListControlProvider::~TextListControlProvider() - { - } - - GuiControl* GuiTextBoxAutoCompleteBase::TextListControlProvider::GetAutoCompleteControl() - { - return autoCompleteList; - } - - GuiSelectableListControl* GuiTextBoxAutoCompleteBase::TextListControlProvider::GetListControl() - { - return autoCompleteList; - } - - void GuiTextBoxAutoCompleteBase::TextListControlProvider::SetSortedContent(const collections::List& items) - { - autoCompleteList->GetItems().Clear(); - for (auto item : items) - { - autoCompleteList->GetItems().Add(Ptr(new list::TextItem(item.text))); - } - } - - vint GuiTextBoxAutoCompleteBase::TextListControlProvider::GetItemCount() - { - return autoCompleteList->GetItems().Count(); - } - - WString GuiTextBoxAutoCompleteBase::TextListControlProvider::GetItemText(vint index) - { - return autoCompleteList->GetItems()[index]->GetText(); - } - -/*********************************************************************** -GuiTextBoxAutoCompleteBase -***********************************************************************/ - - bool GuiTextBoxAutoCompleteBase::IsPrefix(const WString& prefix, const WString& candidate) - { - if(candidate.Length()>=prefix.Length()) - { - if(INVLOC.Compare(prefix, candidate.Sub(0, prefix.Length()), Locale::IgnoreCase)==0) - { - return true; - } - } - return false; - } - - GuiTextBoxAutoCompleteBase::GuiTextBoxAutoCompleteBase(Ptr _autoCompleteControlProvider) - :element(0) - , elementModifyLock(0) - , ownerComposition(0) - , autoCompleteControlProvider(_autoCompleteControlProvider) - { - if (!autoCompleteControlProvider) - { - autoCompleteControlProvider = Ptr(new TextListControlProvider); - } - autoCompleteControlProvider->GetAutoCompleteControl()->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); - - autoCompletePopup = new GuiPopup(theme::ThemeName::Menu); - autoCompletePopup->AddChild(autoCompleteControlProvider->GetAutoCompleteControl()); - } - - GuiTextBoxAutoCompleteBase::~GuiTextBoxAutoCompleteBase() - { - delete autoCompletePopup; - } - - void GuiTextBoxAutoCompleteBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - if(_element) - { - SPIN_LOCK(_elementModifyLock) - { - element=_element; - elementModifyLock=&_elementModifyLock; - ownerComposition=_ownerComposition; - } - } - } - - void GuiTextBoxAutoCompleteBase::Detach() - { - if(element && elementModifyLock) - { - SPIN_LOCK(*elementModifyLock) - { - element=0; - elementModifyLock=0; - } - } - } - - void GuiTextBoxAutoCompleteBase::TextEditPreview(TextEditPreviewStruct& arguments) - { - } - - void GuiTextBoxAutoCompleteBase::TextEditNotify(const TextEditNotifyStruct& arguments) - { - if(element && elementModifyLock) - { - if(IsListOpening()) - { - TextPos begin=GetListStartPosition(); - TextPos end=arguments.inputEnd; - WString editingText=element->GetLines().GetText(begin, end); - HighlightList(editingText); - } - } - } - - void GuiTextBoxAutoCompleteBase::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - } - - void GuiTextBoxAutoCompleteBase::TextEditFinished(vuint editVersion) - { - } - - bool GuiTextBoxAutoCompleteBase::IsListOpening() - { - return autoCompletePopup->GetOpening(); - } - - void GuiTextBoxAutoCompleteBase::OpenList(TextPos startPosition) - { - if(element && elementModifyLock) - { - autoCompleteStartPosition=startPosition; - Rect bounds=element->GetLines().GetRectFromTextPos(startPosition); - Point viewPosition=element->GetViewPosition(); - GuiControl* ownerControl=ownerComposition->GetRelatedControl(); - Rect compositionBounds=ownerComposition->GetGlobalBounds(); - Rect controlBounds=ownerControl->GetBoundsComposition()->GetGlobalBounds(); - vint px=compositionBounds.x1-controlBounds.x1-viewPosition.x; - vint py=compositionBounds.y1-controlBounds.y1-viewPosition.y; - bounds.x1+=px; - bounds.x2+=px; - bounds.y1+=py+5; - bounds.y2+=py+5; - autoCompletePopup->ShowPopup(ownerControl, bounds, true); - } - } - - void GuiTextBoxAutoCompleteBase::CloseList() - { - autoCompletePopup->Close(); - } - - void GuiTextBoxAutoCompleteBase::SetListContent(const collections::List& items) - { - if(items.Count()==0) - { - CloseList(); - } - - List sortedItems; - CopyFrom( - sortedItems, - From(items) - .OrderBy([](const AutoCompleteItem& a, const AutoCompleteItem& b) - { - return INVLOC.Compare(a.text, b.text, Locale::IgnoreCase) <=> 0; - }) - ); - - autoCompleteControlProvider->SetSortedContent(sortedItems); - autoCompleteControlProvider->GetAutoCompleteControl()->GetBoundsComposition()->SetPreferredMinSize(Size(200, 200)); - } - - TextPos GuiTextBoxAutoCompleteBase::GetListStartPosition() - { - return autoCompleteStartPosition; - } - - bool GuiTextBoxAutoCompleteBase::SelectPreviousListItem() - { - if(!IsListOpening()) return false; - if(autoCompleteControlProvider->GetListControl()->GetSelectedItems().Count()==0) - { - autoCompleteControlProvider->GetListControl()->SetSelected(0, true); - } - else - { - vint index=autoCompleteControlProvider->GetListControl()->GetSelectedItems()[0]; - if (index > 0) index--; - autoCompleteControlProvider->GetListControl()->SetSelected(index, true); - autoCompleteControlProvider->GetListControl()->EnsureItemVisible(index); - } - return true; - } - - bool GuiTextBoxAutoCompleteBase::SelectNextListItem() - { - if(!IsListOpening()) return false; - if (autoCompleteControlProvider->GetListControl()->GetSelectedItems().Count() == 0) - { - autoCompleteControlProvider->GetListControl()->SetSelected(0, true); - } - else - { - vint index = autoCompleteControlProvider->GetListControl()->GetSelectedItems()[0]; - if (index < autoCompleteControlProvider->GetItemCount() - 1) index++; - autoCompleteControlProvider->GetListControl()->SetSelected(index, true); - autoCompleteControlProvider->GetListControl()->EnsureItemVisible(index); - } - return true; - } - - bool GuiTextBoxAutoCompleteBase::ApplySelectedListItem() - { - if(!IsListOpening()) return false; - if(!ownerComposition) return false; - const auto& selectedItems = autoCompleteControlProvider->GetListControl()->GetSelectedItems(); - if (selectedItems.Count() == 0) return false; - GuiTextBoxCommonInterface* ci=dynamic_cast(ownerComposition->GetRelatedControl()); - if(!ci) return false; - - vint index = selectedItems[0]; - WString selectedItem = autoCompleteControlProvider->GetItemText(index); - TextPos begin = autoCompleteStartPosition; - TextPos end = ci->GetCaretEnd(); - ci->Select(begin, end); - ci->SetSelectionText(selectedItem); - CloseList(); - return true; - } - - WString GuiTextBoxAutoCompleteBase::GetSelectedListItem() - { - if(!IsListOpening()) return L""; - const auto& selectedItems = autoCompleteControlProvider->GetListControl()->GetSelectedItems(); - if (selectedItems.Count() == 0) return L""; - vint index = selectedItems[0]; - return autoCompleteControlProvider->GetItemText(index); - } - - void GuiTextBoxAutoCompleteBase::HighlightList(const WString& editingText) - { - if(IsListOpening()) - { - vint first=0; - vint last = autoCompleteControlProvider->GetItemCount() - 1; - vint selected=-1; - - while (first <= last) - { - vint middle = (first + last) / 2; - WString text = autoCompleteControlProvider->GetItemText(middle); - if (IsPrefix(editingText, text)) - { - selected = middle; - break; - } - - vint result = INVLOC.Compare(editingText, text, Locale::IgnoreCase); - if (result <= 0) - { - last = middle - 1; - } - else - { - first = middle + 1; - } - } - - while(selected>0) - { - WString text = autoCompleteControlProvider->GetItemText(selected - 1); - if (IsPrefix(editingText, text)) - { - selected--; - } - else - { - break; - } - } - - if(selected!=-1) - { - autoCompleteControlProvider->GetListControl()->SetSelected(selected, true); - autoCompleteControlProvider->GetListControl()->EnsureItemVisible(selected); - } - } - } - } - } -} - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTCOLORIZER.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace elements::text; - -/*********************************************************************** -GuiTextBoxColorizerBase -***********************************************************************/ - - void GuiTextBoxColorizerBase::ColorizerThreadProc(void* argument) - { - GuiTextBoxColorizerBase* colorizer=(GuiTextBoxColorizerBase*)argument; - while(!colorizer->isFinalizing) - { - vint lineIndex=-1; - wchar_t* text=0; - vuint32_t* colors=0; - vint length=0; - vint lexerState=-1; - vint contextState=-1; - - SPIN_LOCK(*colorizer->elementModifyLock) - { - if(colorizer->colorizedLineCount>=colorizer->element->GetLines().GetCount()) - { - colorizer->isColorizerRunning=false; - goto CANCEL_COLORIZING; - } - - lineIndex=colorizer->colorizedLineCount++; - TextLine& line=colorizer->element->GetLines().GetLine(lineIndex); - length=line.dataLength; - text=new wchar_t[length+2]; - colors=new vuint32_t[length+2]; - memcpy(text, line.text, sizeof(wchar_t)*length); - text[length]=L'\r'; - text[length+1]=L'\n'; - lexerState=lineIndex==0?colorizer->GetLexerStartState():colorizer->element->GetLines().GetLine(lineIndex-1).lexerFinalState; - contextState=lineIndex==0?colorizer->GetContextStartState():colorizer->element->GetLines().GetLine(lineIndex-1).contextFinalState; - } - - colorizer->ColorizeLineWithCRLF(lineIndex, text, colors, length+2, lexerState, contextState); - - SPIN_LOCK(*colorizer->elementModifyLock) - { - if(lineIndexcolorizedLineCount && lineIndexelement->GetLines().GetCount()) - { - TextLine& line=colorizer->element->GetLines().GetLine(lineIndex); - line.lexerFinalState=lexerState; - line.contextFinalState=contextState; - for(vint i=0;icolorizerRunningEvent.Leave(); - } - - void GuiTextBoxColorizerBase::StartColorizer() - { - if(!isColorizerRunning) - { - isColorizerRunning=true; - colorizerRunningEvent.Enter(); - ThreadPoolLite::Queue(&GuiTextBoxColorizerBase::ColorizerThreadProc, this); - } - } - - void GuiTextBoxColorizerBase::StopColorizer(bool forever) - { - isFinalizing=true; - colorizerRunningEvent.Enter(); - colorizerRunningEvent.Leave(); - colorizedLineCount=0; - if(!forever) - { - isFinalizing=false; - } - } - - void GuiTextBoxColorizerBase::StopColorizerForever() - { - StopColorizer(true); - } - - GuiTextBoxColorizerBase::GuiTextBoxColorizerBase() - :element(0) - ,elementModifyLock(0) - ,colorizedLineCount(0) - ,isColorizerRunning(false) - ,isFinalizing(false) - { - } - - GuiTextBoxColorizerBase::~GuiTextBoxColorizerBase() - { - StopColorizerForever(); - } - - void GuiTextBoxColorizerBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - if(_element) - { - SPIN_LOCK(_elementModifyLock) - { - element=_element; - elementModifyLock=&_elementModifyLock; - StartColorizer(); - } - } - } - - void GuiTextBoxColorizerBase::Detach() - { - if(element && elementModifyLock) - { - StopColorizer(false); - SPIN_LOCK(*elementModifyLock) - { - element=0; - elementModifyLock=0; - } - } - } - - void GuiTextBoxColorizerBase::TextEditPreview(TextEditPreviewStruct& arguments) - { - } - - void GuiTextBoxColorizerBase::TextEditNotify(const TextEditNotifyStruct& arguments) - { - if(element && elementModifyLock) - { - SPIN_LOCK(*elementModifyLock) - { - vint line - =arguments.originalStart.rowline) - { - colorizedLineCount=line; - } - StartColorizer(); - } - } - } - - void GuiTextBoxColorizerBase::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - } - - void GuiTextBoxColorizerBase::TextEditFinished(vuint editVersion) - { - } - - void GuiTextBoxColorizerBase::RestartColorizer() - { - if(element && elementModifyLock) - { - SPIN_LOCK(*elementModifyLock) - { - colorizedLineCount=0; - StartColorizer(); - } - } - } - -/*********************************************************************** -GuiTextBoxRegexColorizer -***********************************************************************/ - - struct GuiTextBoxRegexColorizerProcData - { - GuiTextBoxRegexColorizer* colorizer; - vint lineIndex; - const wchar_t* text; - vuint32_t* colors; - vint contextState; - }; - - void GuiTextBoxRegexColorizer::ColorizerProc(void* argument, vint start, vint length, vint token) - { - GuiTextBoxRegexColorizerProcData& data=**(GuiTextBoxRegexColorizerProcData**)argument; - data.colorizer->ColorizeTokenContextSensitive(data.lineIndex, data.text, start, length, token, data.contextState); - for(vint i=0;i& GuiTextBoxRegexColorizer::GetTokenRegexes() - { - return tokenRegexes; - } - - collections::List& GuiTextBoxRegexColorizer::GetTokenColors() - { - return tokenColors; - } - - collections::List& GuiTextBoxRegexColorizer::GetExtraTokenColors() - { - return extraTokenColors; - } - - vint GuiTextBoxRegexColorizer::GetExtraTokenIndexStart() - { - if(lexer) - { - return tokenColors.Count(); - } - else - { - return -1; - } - } - - bool GuiTextBoxRegexColorizer::SetDefaultColor(elements::text::ColorEntry value) - { - if(lexer) - { - return false; - } - else - { - defaultColor=value; - return true; - } - } - - vint GuiTextBoxRegexColorizer::AddToken(const WString& regex, elements::text::ColorEntry color) - { - if(lexer) - { - return -1; - } - else - { - tokenRegexes.Add(regex); - tokenColors.Add(color); - return tokenColors.Count()-1; - } - } - - vint GuiTextBoxRegexColorizer::AddExtraToken(elements::text::ColorEntry color) - { - if(lexer) - { - return -1; - } - else - { - extraTokenColors.Add(color); - return extraTokenColors.Count()-1; - } - } - - void GuiTextBoxRegexColorizer::ClearTokens() - { - tokenRegexes.Clear(); - tokenColors.Clear(); - extraTokenColors.Clear(); - lexer=0; - } - - void GuiTextBoxRegexColorizer::Setup() - { - if (lexer || tokenRegexes.Count() == 0) - { - colors.Resize(1); - colors[0] = defaultColor; - } - else - { - lexer = Ptr(new regex::RegexLexer(tokenRegexes)); - colors.Resize(1 + tokenRegexes.Count() + extraTokenColors.Count()); - colors[0] = defaultColor; - for (vint i = 0; i < tokenColors.Count(); i++) - { - colors[i + 1] = tokenColors[i]; - } - for (vint i = 0; i < extraTokenColors.Count(); i++) - { - colors[i + 1 + tokenColors.Count()] = extraTokenColors[i]; - } - { - regex::RegexProc proc; - proc.colorizeProc = &GuiTextBoxRegexColorizer::ColorizerProc; - proc.argument = colorizerArgument; - colorizer = Ptr(new regex::RegexLexerColorizer(lexer->Colorize(proc))); - } - } - } - - void GuiTextBoxRegexColorizer::ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState) - { - } - - vint GuiTextBoxRegexColorizer::GetLexerStartState() - { - return lexer?colorizer->GetStartState():-1; - } - - vint GuiTextBoxRegexColorizer::GetContextStartState() - { - return 0; - } - - void GuiTextBoxRegexColorizer::ColorizeLineWithCRLF(vint lineIndex, const wchar_t* text, vuint32_t* colors, vint length, vint& lexerState, vint& contextState) - { - memset(colors, 0, sizeof(*colors)*length); - if (lexer) - { - GuiTextBoxRegexColorizerProcData data; - data.colorizer = this; - data.lineIndex = lineIndex; - data.text = text; - data.colors = colors; - data.contextState = contextState; - - regex::RegexLexerColorizer::InternalState internalState; - internalState.currentState = lexerState; - colorizer->SetInternalState(internalState); - colorizerArgument[0] = &data; - colorizer->Colorize(text, length); - - lexerState = colorizer->GetInternalState().currentState; - contextState = data.contextState; - } - else - { - lexerState = -1; - contextState = -1; - } - } - - const GuiTextBoxRegexColorizer::ColorArray& GuiTextBoxRegexColorizer::GetColors() - { - return colors; - } - } - } -} /*********************************************************************** .\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTUNDOREDO.CPP @@ -21847,7 +19868,6 @@ namespace vl namespace controls { using namespace elements; - using namespace elements::text; using namespace compositions; /*********************************************************************** @@ -21945,75 +19965,6 @@ GuiGeneralUndoRedoProcessor return true; } -/*********************************************************************** -GuiTextBoxUndoRedoProcessor::EditStep -***********************************************************************/ - - void GuiTextBoxUndoRedoProcessor::EditStep::Undo() - { - GuiTextBoxCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); - if(ci) - { - ci->Select(arguments.inputStart, arguments.inputEnd); - ci->SetSelectionText(arguments.originalText); - ci->Select(arguments.originalStart, arguments.originalEnd); - } - } - - void GuiTextBoxUndoRedoProcessor::EditStep::Redo() - { - GuiTextBoxCommonInterface* ci=dynamic_cast(processor->ownerComposition->GetRelatedControl()); - if(ci) - { - ci->Select(arguments.originalStart, arguments.originalEnd); - ci->SetSelectionText(arguments.inputText); - ci->Select(arguments.inputStart, arguments.inputEnd); - } - } - -/*********************************************************************** -GuiTextBoxUndoRedoProcessor -***********************************************************************/ - - GuiTextBoxUndoRedoProcessor::GuiTextBoxUndoRedoProcessor() - :ownerComposition(0) - { - } - - GuiTextBoxUndoRedoProcessor::~GuiTextBoxUndoRedoProcessor() - { - } - - void GuiTextBoxUndoRedoProcessor::Attach(elements::GuiColorizedTextElement* element, SpinLock& elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - ownerComposition=_ownerComposition; - } - - void GuiTextBoxUndoRedoProcessor::Detach() - { - ClearUndoRedo(); - } - - void GuiTextBoxUndoRedoProcessor::TextEditPreview(TextEditPreviewStruct& arguments) - { - } - - void GuiTextBoxUndoRedoProcessor::TextEditNotify(const TextEditNotifyStruct& arguments) - { - auto step=Ptr(new EditStep); - step->processor=this; - step->arguments=arguments; - PushStep(step); - } - - void GuiTextBoxUndoRedoProcessor::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - } - - void GuiTextBoxUndoRedoProcessor::TextEditFinished(vuint editVersion) - { - } - /*********************************************************************** GuiDocumentUndoRedoProcessor::ReplaceModelStep ***********************************************************************/ @@ -22129,1807 +20080,6 @@ GuiDocumentUndoRedoProcessor } } -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEAUTOCOMPLETE.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace regex; - using namespace parsing; - using namespace parsing::tabling; - using namespace collections; - -/*********************************************************************** -GuiGrammarAutoComplete -***********************************************************************/ - - void GuiGrammarAutoComplete::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - GuiTextBoxAutoCompleteBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); - RepeatingParsingExecutor::CallbackBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); - } - - void GuiGrammarAutoComplete::Detach() - { - GuiTextBoxAutoCompleteBase::Detach(); - RepeatingParsingExecutor::CallbackBase::Detach(); - if(element && elementModifyLock) - { - EnsureAutoCompleteFinished(); - } - } - - void GuiGrammarAutoComplete::TextEditPreview(TextEditPreviewStruct& arguments) - { - GuiTextBoxAutoCompleteBase::TextEditPreview(arguments); - RepeatingParsingExecutor::CallbackBase::TextEditPreview(arguments); - - if(element && elementModifyLock) - { - if(IsListOpening() && arguments.keyInput && arguments.originalText==L"" && arguments.inputText!=L"") - { - WString selectedItem=GetSelectedListItem(); - if(selectedItem!=L"") - { - TextPos begin=GetListStartPosition(); - TextPos end=arguments.originalStart; - WString editingText=element->GetLines().GetText(begin, end); - editingText+=arguments.inputText; - if(grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(editingText)) - { - arguments.originalStart=begin; - arguments.inputText=selectedItem+arguments.inputText; - CloseList(); - } - } - } - } - } - - void GuiGrammarAutoComplete::TextEditNotify(const TextEditNotifyStruct& arguments) - { - GuiTextBoxAutoCompleteBase::TextEditNotify(arguments); - RepeatingParsingExecutor::CallbackBase::TextEditNotify(arguments); - if(element && elementModifyLock) - { - editing=true; - SPIN_LOCK(editTraceLock) - { - editTrace.Add(arguments); - } - } - } - - void GuiGrammarAutoComplete::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - GuiTextBoxAutoCompleteBase::TextCaretChanged(arguments); - RepeatingParsingExecutor::CallbackBase::TextCaretChanged(arguments); - if(element && elementModifyLock) - { - SPIN_LOCK(editTraceLock) - { - // queue a fake TextEditNotifyStruct - // a fake struct can be detected by (trace.originalText==L"" && trace.inputText==L"") - TextEditNotifyStruct trace; - trace.editVersion=arguments.editVersion; - trace.originalStart=arguments.oldBegin; - trace.originalEnd=arguments.oldEnd; - trace.inputStart=arguments.newBegin; - trace.inputEnd=arguments.newEnd; - - // ensure trace.originalStart<=trace.originalEnd - if(trace.originalStart>trace.originalEnd) - { - TextPos temp=trace.originalStart; - trace.originalStart=trace.originalEnd; - trace.originalEnd=temp; - } - // ensure trace.inputStart<=trace.inputEnd - if(trace.inputStart>trace.inputEnd) - { - TextPos temp=trace.inputStart; - trace.inputStart=trace.inputEnd; - trace.inputEnd=temp; - } - editTrace.Add(trace); - } - - SPIN_LOCK(contextLock) - { - if(context.input.node) - { - if(editing) - { - // if the current caret changing is caused by editing - // submit a task with valid editVersion and invalid node and code - RepeatingParsingOutput input; - input.editVersion=context.input.editVersion; - SubmitTask(input); - } - else if(context.input.editVersion == arguments.editVersion) - { - // if the current caret changing is not caused by editing - // submit a task with the previous input - SubmitTask(context.input); - } - } - } - } - } - - void GuiGrammarAutoComplete::TextEditFinished(vuint editVersion) - { - GuiTextBoxAutoCompleteBase::TextEditFinished(editVersion); - RepeatingParsingExecutor::CallbackBase::TextEditFinished(editVersion); - if(element && elementModifyLock) - { - editing=false; - } - } - - void GuiGrammarAutoComplete::OnParsingFinishedAsync(const RepeatingParsingOutput& arguments) - { - if(element && elementModifyLock) - { - GetApplication()->InvokeInMainThread(ownerComposition->GetRelatedControlHost(), [=, this]() - { - // submit a task if the RepeatingParsingExecutor notices a new parsing result - SubmitTask(arguments); - }); - } - } - - void GuiGrammarAutoComplete::CollectLeftRecursiveRules() - { - leftRecursiveRules.Clear(); - Ptr parser=parsingExecutor->GetParser(); - Ptr table=parser->GetTable(); - vint stateCount=table->GetStateCount(); - vint tokenCount=table->GetTokenCount(); - for(vint i=0;i bag=table->GetTransitionBag(i, j); - if(bag) - { - for (auto item : bag->transitionItems) - { - for (auto ins : item->instructions) - { - if(ins.instructionType==ParsingTable::Instruction::LeftRecursiveReduce) - { - if(!leftRecursiveRules.Contains(ins.creatorRule)) - { - leftRecursiveRules.Add(ins.creatorRule); - } - } - } - } - } - } - } - } - - vint GuiGrammarAutoComplete::UnsafeGetEditTraceIndex(vuint editVersion) - { - // get the index of the latest TextEditNotifyStruct of a specified edit version - // this function should be called inside SPIN_LOCK(editTraceLock) - // perform a binary search - vint start = 0; - vint end = editTrace.Count() - 1; - while (start <= end) - { - vint middle = (start + end) / 2; - TextEditNotifyStruct& trace = editTrace[middle]; - - if (editVersiontrace.editVersion) - { - start = middle + 1; - } - else - { - // if multiple TextEditNotifyStruct is found, choose the latest one - while (middle < editTrace.Count() - 1) - { - if (editTrace[middle + 1].editVersion == editTrace[middle].editVersion) - { - middle++; - } - else - { - break; - } - } - return middle; - } - } - return -1; - } - - TextPos GuiGrammarAutoComplete::ChooseCorrectTextPos(TextPos pos, const regex::RegexTokens& tokens) - { - Ptr table=grammarParser->GetTable(); - RegexToken lastToken; - lastToken.reading=0; - - for (auto token : tokens) - { - // we treat "class| Name" as editing the first token - if(TextPos(token.rowEnd, token.columnEnd+1)>=pos) - { - if(table->GetTableTokenIndex(token.token)!=-1 && lastToken.reading) - { - pos=TextPos(lastToken.rowStart, lastToken.columnStart); - } - break; - } - lastToken=token; - } - return pos; - } - - void GuiGrammarAutoComplete::ExecuteRefresh(AutoCompleteContext& newContext) - { - // process the input of a task is submitted not by text editing - // find the text selection by the edit version of the input - TextPos startPos, endPos; - { - SPIN_LOCK(editTraceLock) - { - vint traceIndex = UnsafeGetEditTraceIndex(newContext.input.editVersion); - if (traceIndex == -1) return; - - TextEditNotifyStruct& trace = editTrace[traceIndex]; - startPos = trace.inputStart; - endPos = trace.inputEnd; - } - - const RegexLexer& lexer = grammarParser->GetTable()->GetLexer(); - RegexTokens tokens = lexer.Parse(newContext.input.code); - startPos = ChooseCorrectTextPos(startPos, tokens); - } - - // locate the deepest node using the text selection - ParsingTextPos start(startPos.row, startPos.column); - ParsingTextPos end(endPos.row, endPos.column); - ParsingTextRange range(start, end); - ParsingTreeNode* found = newContext.input.node->FindDeepestNode(range); - ParsingTreeObject* selectedNode = 0; - - // if the location failed, choose the root node - if (!found || startPos == TextPos(0, 0)) - { - found = newContext.input.node.Obj(); - } - - if (!selectedNode) - { - // from the deepest node, traverse towards the root node - // find the deepest node whose created rule is a left recursive rule and whose parent is not - ParsingTreeObject* lrec = 0; - ParsingTreeNode* current = found; - while (current) - { - ParsingTreeObject* obj = dynamic_cast(current); - if (obj) - { - for (auto rule : obj->GetCreatorRules()) - { - if (leftRecursiveRules.Contains(rule)) - { - lrec = obj; - break; - } - } - if (obj && lrec && lrec != obj) - { - selectedNode = lrec; - break; - } - } - current = current->GetParent(); - } - } - - if (!selectedNode) - { - // if there is no left recursive rule that creates the deepest node and all indirect parents - // choose the deepest ParsingTreeObject - ParsingTreeNode* current = found; - while (current) - { - ParsingTreeObject* obj = dynamic_cast(current); - if (obj) - { - selectedNode = obj; - break; - } - current = current->GetParent(); - } - } - - if (selectedNode) - { - // get the code range of the selected node - start = selectedNode->GetCodeRange().start; - end = selectedNode->GetCodeRange().end; - - // get all properties from the selected node - newContext.rule = selectedNode->GetCreatorRules()[selectedNode->GetCreatorRules().Count() - 1]; - newContext.originalRange = selectedNode->GetCodeRange(); - newContext.originalNode = Ptr(selectedNode); - newContext.modifiedNode = newContext.originalNode; - newContext.modifiedEditVersion = newContext.input.editVersion; - - // get the corresponding code of the selected node - if (start.index >= 0 && end.index >= 0) - { - newContext.modifiedCode = newContext.input.code.Sub(start.index, end.index - start.index + 1).Buffer(); - } - } - } - - bool GuiGrammarAutoComplete::NormalizeTextPos(AutoCompleteContext& newContext, elements::text::TextLines& lines, TextPos& pos) - { - // get the start position - TextPos start(newContext.originalRange.start.row, newContext.originalRange.start.column); - - // get the end position of the end of lines - TextPos end - = lines.GetCount() <= 1 - ? TextPos(start.row, start.column + lines.GetLine(0).dataLength) - : TextPos(start.row + lines.GetCount() - 1, lines.GetLine(lines.GetCount() - 1).dataLength) - ; - - if (start <= pos && pos <= end) - { - // if the pos is inside the range - // normalize the pos to a new coordinate that the beginning position of lines is (row=0, column=0) - pos.row -= start.row; - if (pos.row == 0) - { - pos.column -= start.column; - } - return true; - } - else - { - return false; - } - } - - void GuiGrammarAutoComplete::ExecuteEdit(AutoCompleteContext& newContext) - { - // process the input of a task that is submitted by text editing - // this function make an approximiation to the context if the RepeatingParsingExecutor is not fast enough - // copy all TextEditNotifyStruct that is caused by a text editing before (and including) the edit version of the input - List usedTrace; - { - SPIN_LOCK(editTraceLock) - { - CopyFrom( - usedTrace, - From(editTrace) - .Where([&newContext](const TextEditNotifyStruct& value) - { - return (value.originalText != L"" || value.inputText != L"") && value.editVersion > newContext.modifiedEditVersion; - }) - ); - } - } - - // apply all modification to get the new modifiedCode - bool failed = false; - if (usedTrace.Count() > 0) - { - if (usedTrace[0].editVersion != newContext.modifiedEditVersion + 1) - { - // failed if any TextEditNotifyStruct is missing - failed = true; - } - else - { - // initialize a TextLines with the latest modifiedCode - text::TextLines lines(nullptr); - lines.SetText(newContext.modifiedCode); - for (auto trace : usedTrace) - { - // apply a modification to lines - TextPos start = trace.originalStart; - TextPos end = trace.originalEnd; - - // only if the modification is meaningful - if (NormalizeTextPos(newContext, lines, start) && NormalizeTextPos(newContext, lines, end)) - { - lines.Modify(start, end, trace.inputText); - } - else - { - // otherwise, failed - failed = true; - break; - } - } - - if (!failed) - { - newContext.modifiedCode = lines.GetText(); - } - } - } - - if (failed) - { - // clear originalNode to notify that the current context goes wrong - newContext.originalNode = 0; - } - - if (usedTrace.Count() > 0) - { - // update the edit version - newContext.modifiedEditVersion = usedTrace[usedTrace.Count() - 1].editVersion; - } - } - - void GuiGrammarAutoComplete::DeleteFutures(collections::List& futures) - { - // delete all futures and clear the list - for (auto future : futures) - { - delete future; - } - futures.Clear(); - } - - regex::RegexToken* GuiGrammarAutoComplete::TraverseTransitions( - parsing::tabling::ParsingState& state, - parsing::tabling::ParsingTransitionCollector& transitionCollector, - TextPos stopPosition, - collections::List& nonRecoveryFutures, - collections::List& recoveryFutures - ) - { - const List& transitions = transitionCollector.GetTransitions(); - for (vint index = 0; index < transitions.Count(); index++) - { - const ParsingState::TransitionResult& transition = transitions[index]; - switch (transition.transitionType) - { - case ParsingState::TransitionResult::AmbiguityBegin: - break; - case ParsingState::TransitionResult::AmbiguityBranch: - // ambiguity branches are not nested - // tokens in different braches are the same - // so we only need to run one branch, and skip the others - index = transitionCollector.GetAmbiguityEndFromBegin(transitionCollector.GetAmbiguityBeginFromBranch(index)); - break; - case ParsingState::TransitionResult::AmbiguityEnd: - break; - case ParsingState::TransitionResult::ExecuteInstructions: - { - // test does the token reach the stop position - if (transition.token) - { - // we treat "A|B" as editing A if token A is endless, otherwise treated as editing B - TextPos tokenEnd(transition.token->rowEnd, transition.token->columnEnd + 1); - - // if the caret is not at the end of the token - if (tokenEnd > stopPosition) - { - // stop the traversing and return the editing token - return transition.token; - } - else if (tokenEnd == stopPosition) - { - // if the caret is at the end of the token, and it is a closed token - // e.g. identifier is not a closed token, string is a closed token - if (!grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(transition.token->reading, transition.token->length)) - { - // stop the traversing and return the editing token - return transition.token; - } - } - } - - // traverse the PDA using the token specified in the current transition - vint tableTokenIndex = transition.tableTokenIndex; - List possibilities; - if (recoveryFutures.Count() > 0) - { - for (auto future : recoveryFutures) - { - state.Explore(tableTokenIndex, future, possibilities); - } - } - else - { - for (auto future : nonRecoveryFutures) - { - state.Explore(tableTokenIndex, future, possibilities); - } - } - - // delete duplicated futures - List selectedPossibilities; - for (vint i = 0; i < possibilities.Count(); i++) - { - ParsingState::Future* candidateFuture = possibilities[i]; - bool duplicated = false; - for (auto future : selectedPossibilities) - { - if ( - candidateFuture->currentState == future->currentState && - candidateFuture->reduceStateCount == future->reduceStateCount && - candidateFuture->shiftStates.Count() == future->shiftStates.Count() - ) - { - bool same = true; - for (vint j = 0; j < future->shiftStates.Count(); j++) - { - if (candidateFuture->shiftStates[i] != future->shiftStates[i]) - { - same = false; - break; - } - } - - if ((duplicated = same)) - { - break; - } - } - } - - if (duplicated) - { - delete candidateFuture; - } - else - { - selectedPossibilities.Add(candidateFuture); - } - } - - // step forward - if (transition.token || transition.tableTokenIndex == ParsingTable::TokenBegin) - { - DeleteFutures(nonRecoveryFutures); - DeleteFutures(recoveryFutures); - CopyFrom(nonRecoveryFutures, selectedPossibilities); - } - else - { - DeleteFutures(recoveryFutures); - CopyFrom(recoveryFutures, selectedPossibilities); - } - } - break; - default:; - } - } - return 0; - } - - regex::RegexToken* GuiGrammarAutoComplete::SearchValidInputToken( - parsing::tabling::ParsingState& state, - parsing::tabling::ParsingTransitionCollector& transitionCollector, - TextPos stopPosition, - AutoCompleteContext& newContext, - collections::SortedList& tableTokenIndices - ) - { - // initialize the PDA state - state.Reset(newContext.rule); - List nonRecoveryFutures, recoveryFutures; - nonRecoveryFutures.Add(state.ExploreCreateRootFuture()); - - // traverse the PDA until it reach the stop position - // nonRecoveryFutures store the state when the last token (existing) is reached - // recoveryFutures store the state when the last token (inserted by error recovery) is reached - RegexToken* token = TraverseTransitions(state, transitionCollector, stopPosition, nonRecoveryFutures, recoveryFutures); - - // explore all possibilities from the last token before the stop position - List possibilities; - for (vint i = 0; i < nonRecoveryFutures.Count(); i++) - { - state.Explore(ParsingTable::NormalReduce, nonRecoveryFutures[i], nonRecoveryFutures); - state.Explore(ParsingTable::LeftRecursiveReduce, nonRecoveryFutures[i], nonRecoveryFutures); - } - for (auto future : nonRecoveryFutures) - { - vint count = state.GetTable()->GetTokenCount(); - for (vint i = ParsingTable::UserTokenStart; i < count; i++) - { - state.Explore(i, future, possibilities); - } - } - - // get all possible tokens that marked using @AutoCompleteCandidate - for (auto future : possibilities) - { - if (!tableTokenIndices.Contains(future->selectedToken)) - { - tableTokenIndices.Add(future->selectedToken); - } - } - - // release all data - DeleteFutures(possibilities); - DeleteFutures(nonRecoveryFutures); - DeleteFutures(recoveryFutures); - - // return the editing token - return token; - } - - TextPos GuiGrammarAutoComplete::GlobalTextPosToModifiedTextPos(AutoCompleteContext& newContext, TextPos pos) - { - pos.row-=newContext.originalRange.start.row; - if(pos.row==0) - { - pos.column-=newContext.originalRange.start.column; - } - return pos; - } - - TextPos GuiGrammarAutoComplete::ModifiedTextPosToGlobalTextPos(AutoCompleteContext& newContext, TextPos pos) - { - if(pos.row==0) - { - pos.column+=newContext.originalRange.start.column; - } - pos.row+=newContext.originalRange.start.row; - return pos; - } - - void GuiGrammarAutoComplete::ExecuteCalculateList(AutoCompleteContext& newContext) - { - // calcuate the content of the auto complete list - // it is sad that, because the parser's algorithm is too complex - // we need to reparse and track the internal state of the PDA(push-down automaton) here. - // initialize the PDA - ParsingState state(newContext.modifiedCode, grammarParser->GetTable()); - state.Reset(newContext.rule); - - // prepare to get all transitions - ParsingTransitionCollector collector; - List> errors; - - // reparse and get all transitions during parsing - if (grammarParser->Parse(state, collector, errors)) - { - // if modifiedNode is not prepared (the task is submitted because of text editing) - // use the transition to build the syntax tree - if (!newContext.modifiedNode) - { - ParsingTreeBuilder builder; - builder.Reset(); - bool succeeded = true; - for (auto transition : collector.GetTransitions()) - { - if (!(succeeded = builder.Run(transition))) - { - break; - } - } - - if (succeeded) - { - Ptr parsedNode = builder.GetNode(); - newContext.modifiedNode = parsedNode.Cast(); - newContext.modifiedNode->InitializeQueryCache(); - } - } - - if (newContext.modifiedNode) - { - // get the latest text editing trace - TextEditNotifyStruct trace; - SPIN_LOCK(editTraceLock) - { - vint index = UnsafeGetEditTraceIndex(newContext.modifiedEditVersion); - if (index == -1) - { - return; - } - else - { - trace = editTrace[index]; - } - } - - // calculate the stop position for PDA traversing - TextPos stopPosition = GlobalTextPosToModifiedTextPos(newContext, trace.inputStart); - - // find all possible token before the current caret using the PDA - auto autoComplete = Ptr(new AutoCompleteData); - SortedList tableTokenIndices; - RegexToken* editingToken = SearchValidInputToken(state, collector, stopPosition, newContext, tableTokenIndices); - - // collect all auto complete types - { - // collect all keywords that can be put into the auto complete list - for (auto token : tableTokenIndices) - { - vint regexToken = token - ParsingTable::UserTokenStart; - if (regexToken >= 0) - { - autoComplete->candidates.Add(regexToken); - if (parsingExecutor->GetTokenMetaData(regexToken).isCandidate) - { - autoComplete->shownCandidates.Add(regexToken); - } - } - } - - // calculate the arranged stopPosition - if (editingToken) - { - TextPos tokenPos(editingToken->rowStart, editingToken->columnStart); - if (tokenPos < stopPosition) - { - stopPosition = tokenPos; - } - } - - // calculate the start/end position for PDA traversing - TextPos startPos, endPos; - { - startPos = ModifiedTextPosToGlobalTextPos(newContext, stopPosition); - autoComplete->startPosition = startPos; - endPos = trace.inputEnd; - if (newContext.modifiedNode != newContext.originalNode) - { - startPos = GlobalTextPosToModifiedTextPos(newContext, startPos); - endPos = GlobalTextPosToModifiedTextPos(newContext, endPos); - } - if (startPos0) - { - endPos.column--; - } - } - - // calculate the auto complete type - if (editingToken && parsingExecutor->GetTokenMetaData(editingToken->token).hasAutoComplete) - { - ParsingTextRange range(ParsingTextPos(startPos.row, startPos.column), ParsingTextPos(endPos.row, endPos.column)); - AutoCompleteData::RetriveContext(*autoComplete.Obj(), range, newContext.modifiedNode.Obj(), parsingExecutor.Obj()); - } - } - newContext.autoComplete = autoComplete; - } - } - } - - void GuiGrammarAutoComplete::Execute(const RepeatingParsingOutput& input) - { - SPIN_LOCK(contextLock) - { - if(input.editVersionInvokeInMainThread(ownerComposition->GetRelatedControlHost(), [=, this]() - { - PostList(newContext, byGlobalCorrection); - }); - } - } - - void GuiGrammarAutoComplete::PostList(const AutoCompleteContext& newContext, bool byGlobalCorrection) - { - bool openList = true; // true: make the list visible - bool keepListState = false; // true: don't change the list visibility - Ptr autoComplete = newContext.autoComplete; - - // if failed to get the auto complete list, close - if (!autoComplete) - { - openList = false; - } - if (openList) - { - if (autoComplete->shownCandidates.Count() + autoComplete->candidateItems.Count() == 0) - { - openList = false; - } - } - - TextPos startPosition, endPosition; - WString editingText; - if (openList) - { - SPIN_LOCK(editTraceLock) - { - // if the edit version is invalid, cancel - vint traceIndex = UnsafeGetEditTraceIndex(newContext.modifiedEditVersion); - if (traceIndex == -1) - { - return; - } - // an edit version has two trace at most, for text change and caret change, here we peak the text change - if (traceIndex > 0 && editTrace[traceIndex - 1].editVersion == context.modifiedEditVersion) - { - traceIndex--; - } - // if the edit version is not created by keyboard input, close - if (traceIndex >= 0) - { - TextEditNotifyStruct& trace = editTrace[traceIndex]; - if (!trace.keyInput) - { - openList = false; - } - } - - // scan all traces from the calculation's edit version until now - if (openList) - { - keepListState = true; - startPosition = autoComplete->startPosition; - endPosition = editTrace[editTrace.Count() - 1].inputEnd; - for (vint i = traceIndex; i < editTrace.Count(); i++) - { - TextEditNotifyStruct& trace = editTrace[i]; - // if there are no text change trace until now, don't change the list - if (trace.originalText != L"" || trace.inputText != L"") - { - keepListState = false; - } - // if the edit position goes before the start position of the auto complete, refresh - if (trace.inputEnd <= startPosition) - { - openList = false; - break; - } - } - } - - if (traceIndex > 0) - { - editTrace.RemoveRange(0, traceIndex); - } - } - } - - // if there is a global correction send to the UI thread but the list is not opening, cancel - if (byGlobalCorrection && !IsListOpening()) - { - return; - } - - // if the input text from the start position to the current position crosses a token, close - if (openList && element) - { - editingText = element->GetLines().GetText(startPosition, endPosition); - if (grammarParser->GetTable()->GetLexer().Walk().IsClosedToken(editingText)) - { - openList = false; - } - } - - // calculate the content of the list - if (autoComplete && ((!keepListState && openList) || IsListOpening())) - { - SortedList itemKeys; - List itemValues; - - // copy all candidate keywords - for (auto token : autoComplete->shownCandidates) - { - WString literal = parsingExecutor->GetTokenMetaData(token).unescapedRegexText; - if (literal != L"" && !itemKeys.Contains(literal)) - { - ParsingCandidateItem item; - item.name = literal; - item.semanticId = -1; - itemValues.Insert(itemKeys.Add(literal), item); - } - } - - // copy all candidate symbols - if (autoComplete->acceptableSemanticIds) - { - for (auto item : autoComplete->candidateItems) - { - if (autoComplete->acceptableSemanticIds->Contains(item.semanticId)) - { - // add all acceptable display of a symbol - // because a symbol can has multiple representation in different places - if (item.name != L"" && !itemKeys.Contains(item.name)) - { - itemValues.Insert(itemKeys.Add(item.name), item); - } - } - } - } - - // fill the list - List candidateItems; - for (vint i = 0; i < itemValues.Count(); i++) - { - auto& item = itemValues[i]; - if (item.tag.IsNull()) - { - if (auto analyzer = parsingExecutor->GetAnalyzer()) - { - item.tag = analyzer->CreateTagForCandidateItem(item); - } - } - - GuiTextBoxAutoCompleteBase::AutoCompleteItem candidateItem; - candidateItem.text = item.name; - candidateItem.tag = item.tag; - candidateItems.Add(candidateItem); - } - SetListContent(candidateItems); - } - - // set the list state - if (!keepListState) - { - if (openList) - { - OpenList(startPosition); - } - else - { - CloseList(); - } - } - - if (IsListOpening()) - { - HighlightList(editingText); - } - } - - void GuiGrammarAutoComplete::Initialize() - { - grammarParser=CreateAutoRecoverParser(parsingExecutor->GetParser()->GetTable()); - CollectLeftRecursiveRules(); - parsingExecutor->AttachCallback(this); - } - - void GuiGrammarAutoComplete::OnContextFinishedAsync(AutoCompleteContext& context) - { - if (auto analyzer = parsingExecutor->GetAnalyzer()) - { - if (context.autoComplete && context.autoComplete->acceptableSemanticIds) - { - analyzer->GetCandidateItemsAsync(*context.autoComplete.Obj(), context, context.autoComplete->candidateItems); - } - } - } - - void GuiGrammarAutoComplete::EnsureAutoCompleteFinished() - { - parsingExecutor->EnsureTaskFinished(); - SPIN_LOCK(contextLock) - { - context = AutoCompleteContext(); - } - } - - GuiGrammarAutoComplete::GuiGrammarAutoComplete(Ptr _parsingExecutor) - :RepeatingParsingExecutor::CallbackBase(_parsingExecutor) - ,editing(false) - { - Initialize(); - } - - GuiGrammarAutoComplete::GuiGrammarAutoComplete(Ptr _grammarParser, const WString& _grammarRule) - :RepeatingParsingExecutor::CallbackBase(Ptr(new RepeatingParsingExecutor(_grammarParser, _grammarRule))) - ,editing(false) - { - Initialize(); - } - - GuiGrammarAutoComplete::~GuiGrammarAutoComplete() - { - EnsureAutoCompleteFinished(); - parsingExecutor->DetachCallback(this); - } - - Ptr GuiGrammarAutoComplete::GetParsingExecutor() - { - return parsingExecutor; - } - } - } -} - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGECOLORIZER.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace elements; - using namespace parsing; - using namespace parsing::tabling; - using namespace collections; - using namespace theme; - -/*********************************************************************** -GuiGrammarColorizer -***********************************************************************/ - - void GuiGrammarColorizer::OnParsingFinishedAsync(const RepeatingParsingOutput& output) - { - SPIN_LOCK(contextLock) - { - context=output; - OnContextFinishedAsync(context); - } - RestartColorizer(); - } - - void GuiGrammarColorizer::OnContextFinishedAsync(const RepeatingParsingOutput& context) - { - } - - void GuiGrammarColorizer::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - GuiTextBoxRegexColorizer::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); - RepeatingParsingExecutor::CallbackBase::Attach(_element, _elementModifyLock, _ownerComposition, editVersion); - } - - void GuiGrammarColorizer::Detach() - { - GuiTextBoxRegexColorizer::Detach(); - RepeatingParsingExecutor::CallbackBase::Detach(); - if(element && elementModifyLock) - { - parsingExecutor->EnsureTaskFinished(); - StopColorizer(false); - } - } - - void GuiGrammarColorizer::TextEditPreview(TextEditPreviewStruct& arguments) - { - GuiTextBoxRegexColorizer::TextEditPreview(arguments); - RepeatingParsingExecutor::CallbackBase::TextEditPreview(arguments); - } - - void GuiGrammarColorizer::TextEditNotify(const TextEditNotifyStruct& arguments) - { - GuiTextBoxRegexColorizer::TextEditNotify(arguments); - RepeatingParsingExecutor::CallbackBase::TextEditNotify(arguments); - } - - void GuiGrammarColorizer::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - GuiTextBoxRegexColorizer::TextCaretChanged(arguments); - RepeatingParsingExecutor::CallbackBase::TextCaretChanged(arguments); - } - - void GuiGrammarColorizer::TextEditFinished(vuint editVersion) - { - GuiTextBoxRegexColorizer::TextEditFinished(editVersion); - RepeatingParsingExecutor::CallbackBase::TextEditFinished(editVersion); - } - - void GuiGrammarColorizer::OnSemanticColorize(SemanticColorizeContext& context, const RepeatingParsingOutput& input) - { - if (auto analyzer = parsingExecutor->GetAnalyzer()) - { - auto semanticId = analyzer->GetSemanticIdForTokenAsync(context, input); - if(semanticId!=-1) - { - context.semanticId=semanticId; - } - } - } - - void GuiGrammarColorizer::EnsureColorizerFinished() - { - parsingExecutor->EnsureTaskFinished(); - StopColorizerForever(); - SPIN_LOCK(contextLock) - { - context=RepeatingParsingOutput(); - } - } - - GuiGrammarColorizer::GuiGrammarColorizer(Ptr _parsingExecutor) - :RepeatingParsingExecutor::CallbackBase(_parsingExecutor) - { - parsingExecutor->AttachCallback(this); - BeginSetColors(); - } - - GuiGrammarColorizer::GuiGrammarColorizer(Ptr _grammarParser, const WString& _grammarRule) - :RepeatingParsingExecutor::CallbackBase(Ptr(new RepeatingParsingExecutor(_grammarParser, _grammarRule))) - { - parsingExecutor->AttachCallback(this); - BeginSetColors(); - } - - GuiGrammarColorizer::~GuiGrammarColorizer() - { - EnsureColorizerFinished(); - parsingExecutor->DetachCallback(this); - } - - void GuiGrammarColorizer::BeginSetColors() - { - ClearTokens(); - colorSettings.Clear(); - - text::ColorEntry entry; - { - entry.normal.text = Color(0, 0, 0); - entry.normal.background = Color(0, 0, 0, 0); - entry.selectedFocused.text = Color(255, 255, 255); - entry.selectedFocused.background = Color(51, 153, 255); - entry.selectedUnfocused.text = Color(255, 255, 255); - entry.selectedUnfocused.background = Color(51, 153, 255); - } - - SetDefaultColor(entry); - colorSettings.Add(L"Default", entry); - } - - const collections::SortedList& GuiGrammarColorizer::GetColorNames() - { - return colorSettings.Keys(); - } - - GuiGrammarColorizer::ColorEntry GuiGrammarColorizer::GetColor(const WString& name) - { - vint index=colorSettings.Keys().IndexOf(name); - return index==-1?GetDefaultColor():colorSettings.Values().Get(index); - } - - void GuiGrammarColorizer::SetColor(const WString& name, const ColorEntry& entry) - { - colorSettings.Set(name, entry); - } - - void GuiGrammarColorizer::SetColor(const WString& name, const Color& color) - { - text::ColorEntry entry=GetDefaultColor(); - entry.normal.text=color; - SetColor(name, entry); - } - - void GuiGrammarColorizer::EndSetColors() - { - SortedList tokenColors; - Ptr table=parsingExecutor->GetParser()->GetTable(); - semanticColorMap.Clear(); - - vint tokenCount=table->GetTokenCount(); - for(vint token=ParsingTable::UserTokenStart;tokenGetTokenInfo(token); - const RepeatingParsingExecutor::TokenMetaData& md=parsingExecutor->GetTokenMetaData(token-ParsingTable::UserTokenStart); - if(md.defaultColorIndex==-1) - { - AddToken(tokenInfo.regex, GetDefaultColor()); - } - else - { - WString name=parsingExecutor->GetSemanticName(md.defaultColorIndex); - vint color=AddToken(tokenInfo.regex, GetColor(name)); - semanticColorMap.Set(md.defaultColorIndex, color); - tokenColors.Add(name); - } - } - - for (auto [color, index] : indexed(colorSettings.Keys())) - { - if(!tokenColors.Contains(color)) - { - vint semanticId=parsingExecutor->GetSemanticId(color); - if(semanticId!=-1) - { - vint tokenId=AddExtraToken(colorSettings.Values().Get(index)); - vint color=tokenId+tokenCount-ParsingTable::UserTokenStart; - semanticColorMap.Set(semanticId, color); - } - } - } - Setup(); - } - - void GuiGrammarColorizer::ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState) - { - SPIN_LOCK(contextLock) - { - ParsingTreeObject* node=context.node.Obj(); - if(node && token!=-1 && parsingExecutor->GetTokenMetaData(token).hasContextColor) - { - ParsingTextPos pos(lineIndex, start); - SemanticColorizeContext scContext; - if(SemanticColorizeContext::RetriveContext(scContext, pos, node, parsingExecutor.Obj())) - { - const RepeatingParsingExecutor::FieldMetaData& md=parsingExecutor->GetFieldMetaData(scContext.type, scContext.field); - vint semantic=md.colorIndex; - scContext.semanticId=-1; - - if(scContext.acceptableSemanticIds) - { - OnSemanticColorize(scContext, context); - if(md.semantics->Contains(scContext.semanticId)) - { - semantic=scContext.semanticId; - } - } - - if(semantic!=-1) - { - vint index=semanticColorMap.Keys().IndexOf(semantic); - if(index!=-1) - { - token=semanticColorMap.Values()[index]; - } - } - } - } - } - } - - Ptr GuiGrammarColorizer::GetParsingExecutor() - { - return parsingExecutor; - } - } - } -} - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEOPERATIONS.CPP -***********************************************************************/ - -namespace vl -{ - namespace presentation - { - namespace controls - { - using namespace collections; - using namespace parsing; - using namespace parsing::tabling; - using namespace regex_internal; - -/*********************************************************************** -ParsingContext -***********************************************************************/ - - bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTreeNode* foundNode, RepeatingParsingExecutor* executor) - { - ParsingTreeToken* foundToken=dynamic_cast(foundNode); - if(!foundToken) return false; - ParsingTreeObject* tokenParent=dynamic_cast(foundNode->GetParent()); - if(!tokenParent) return false; - vint index=tokenParent->GetMembers().Values().IndexOf(foundNode); - if(index==-1) return false; - - WString type=tokenParent->GetType(); - WString field=tokenParent->GetMembers().Keys().Get(index); - const RepeatingParsingExecutor::FieldMetaData& md=executor->GetFieldMetaData(type, field); - - output.foundToken=foundToken; - output.tokenParent=tokenParent; - output.type=type; - output.field=field; - output.acceptableSemanticIds=md.semantics; - return true; - } - - bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTextPos pos, parsing::ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor) - { - ParsingTreeNode* foundNode=rootNode->FindDeepestNode(pos); - if(!foundNode) return false; - return RetriveContext(output, foundNode, executor); - } - - bool ParsingTokenContext::RetriveContext(ParsingTokenContext& output, parsing::ParsingTextRange range, ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor) - { - ParsingTreeNode* foundNode=rootNode->FindDeepestNode(range); - if(!foundNode) return false; - return RetriveContext(output, foundNode, executor); - } - -/*********************************************************************** -RepeatingParsingExecutor::IParsingAnalyzer -***********************************************************************/ - - parsing::ParsingTreeNode* RepeatingParsingExecutor::IParsingAnalyzer::ToParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output) - { - if (!output || !output->modifiedNode) return node; - return node == output->modifiedNode.Obj() - ? output->originalNode.Obj() - : node; - } - - parsing::ParsingTreeObject* RepeatingParsingExecutor::IParsingAnalyzer::ToChild(parsing::ParsingTreeObject* node, const RepeatingPartialParsingOutput* output) - { - if (!output || !output->modifiedNode) return node; - return node == output->originalNode.Obj() - ? output->modifiedNode.Obj() - : node; - } - - Ptr RepeatingParsingExecutor::IParsingAnalyzer::ToChild(Ptr node, const RepeatingPartialParsingOutput* output) - { - if (!output) return node; - return node == output->originalNode - ? output->modifiedNode.Cast() - : node; - } - - parsing::ParsingTreeNode* RepeatingParsingExecutor::IParsingAnalyzer::GetParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output) - { - return ToParent(node, output)->GetParent(); - } - - Ptr RepeatingParsingExecutor::IParsingAnalyzer::GetMember(parsing::ParsingTreeObject* node, const WString& name, const RepeatingPartialParsingOutput* output) - { - return ToChild(ToChild(node, output)->GetMember(name), output); - } - - Ptr RepeatingParsingExecutor::IParsingAnalyzer::GetItem(parsing::ParsingTreeArray* node, vint index, const RepeatingPartialParsingOutput* output) - { - return ToChild(node->GetItem(index), output); - } - -/*********************************************************************** -RepeatingParsingExecutor::CallbackBase -***********************************************************************/ - - RepeatingParsingExecutor::CallbackBase::CallbackBase(Ptr _parsingExecutor) - :parsingExecutor(_parsingExecutor) - ,callbackAutoPushing(false) - ,callbackElement(0) - ,callbackElementModifyLock(0) - { - } - - RepeatingParsingExecutor::CallbackBase::~CallbackBase() - { - } - - void RepeatingParsingExecutor::CallbackBase::RequireAutoSubmitTask(bool enabled) - { - callbackAutoPushing=enabled; - } - - void RepeatingParsingExecutor::CallbackBase::Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion) - { - if(_element) - { - SPIN_LOCK(_elementModifyLock) - { - callbackElement=_element; - callbackElementModifyLock=&_elementModifyLock; - } - } - - parsingExecutor->ActivateCallback(this); - if(callbackElement && callbackElementModifyLock && callbackAutoPushing) - { - SPIN_LOCK(*callbackElementModifyLock) - { - RepeatingParsingInput input; - input.editVersion=editVersion; - input.code=callbackElement->GetLines().GetText(); - parsingExecutor->SubmitTask(input); - } - } - } - - void RepeatingParsingExecutor::CallbackBase::Detach() - { - if(callbackElement && callbackElementModifyLock) - { - SPIN_LOCK(*callbackElementModifyLock) - { - callbackElement=0; - callbackElementModifyLock=0; - } - } - - parsingExecutor->DeactivateCallback(this); - } - - void RepeatingParsingExecutor::CallbackBase::TextEditPreview(TextEditPreviewStruct& arguments) - { - } - - void RepeatingParsingExecutor::CallbackBase::TextEditNotify(const TextEditNotifyStruct& arguments) - { - } - - void RepeatingParsingExecutor::CallbackBase::TextCaretChanged(const TextCaretChangedStruct& arguments) - { - } - - void RepeatingParsingExecutor::CallbackBase::TextEditFinished(vuint editVersion) - { - if(callbackElement && callbackElementModifyLock && callbackAutoPushing) - { - SPIN_LOCK(*callbackElementModifyLock) - { - RepeatingParsingInput input; - input.editVersion=editVersion; - input.code=callbackElement->GetLines().GetText(); - parsingExecutor->SubmitTask(input); - } - } - } - -/*********************************************************************** -RepeatingParsingExecutor -***********************************************************************/ - - void RepeatingParsingExecutor::Execute(const RepeatingParsingInput& input) - { - List> errors; - Ptr node=grammarParser->Parse(input.code, grammarRule, errors).Cast(); - if(node) - { - node->InitializeQueryCache(); - } - - RepeatingParsingOutput result; - result.node=node; - result.editVersion=input.editVersion; - result.code=input.code; - if(node) - { - OnContextFinishedAsync(result); - for (auto callback : callbacks) - { - callback->OnParsingFinishedAsync(result); - } - } - } - - void RepeatingParsingExecutor::PrepareMetaData() - { - Ptr table=grammarParser->GetTable(); - tokenIndexMap.Clear(); - semanticIndexMap.Clear(); - tokenMetaDatas.Clear(); - fieldMetaDatas.Clear(); - - Dictionary> tokenColorAtts, tokenContextColorAtts, tokenCandidateAtts, tokenAutoCompleteAtts; - Dictionary> fieldColorAtts, fieldSemanticAtts; - - { - vint tokenCount=table->GetTokenCount(); - for(vint token=ParsingTable::UserTokenStart;tokenGetTokenInfo(token); - vint tokenIndex=token-ParsingTable::UserTokenStart; - tokenIndexMap.Add(tokenInfo.name, tokenIndex); - - if(Ptr att=GetColorAttribute(tokenInfo.attributeIndex)) - { - tokenColorAtts.Add(tokenIndex, att); - } - if(Ptr att=GetContextColorAttribute(tokenInfo.attributeIndex)) - { - tokenContextColorAtts.Add(tokenIndex, att); - } - if(Ptr att=GetCandidateAttribute(tokenInfo.attributeIndex)) - { - tokenCandidateAtts.Add(tokenIndex, att); - } - if(Ptr att=GetAutoCompleteAttribute(tokenInfo.attributeIndex)) - { - tokenAutoCompleteAtts.Add(tokenIndex, att); - } - } - } - { - vint fieldCount=table->GetTreeFieldInfoCount(); - for(vint field=0;fieldGetTreeFieldInfo(field); - FieldDesc fieldDesc(fieldInfo.type, fieldInfo.field); - - if(Ptr att=GetColorAttribute(fieldInfo.attributeIndex)) - { - fieldColorAtts.Add(fieldDesc, att); - } - if(Ptr att=GetSemanticAttribute(fieldInfo.attributeIndex)) - { - fieldSemanticAtts.Add(fieldDesc, att); - } - } - } - - for (auto att : - From(tokenColorAtts.Values()) - .Concat(tokenContextColorAtts.Values()) - .Concat(fieldColorAtts.Values()) - .Concat(fieldSemanticAtts.Values()) - ) - { - for (auto argument : att->arguments) - { - if(!semanticIndexMap.Contains(argument)) - { - semanticIndexMap.Add(argument); - } - } - } - - vint index=0; - for (auto tokenIndex : tokenIndexMap.Values()) - { - TokenMetaData md; - md.tableTokenIndex=tokenIndex+ParsingTable::UserTokenStart; - md.lexerTokenIndex=tokenIndex; - md.defaultColorIndex=-1; - md.hasContextColor=false; - md.hasAutoComplete=false; - md.isCandidate=false; - - if((index=tokenColorAtts.Keys().IndexOf(tokenIndex))!=-1) - { - md.defaultColorIndex=semanticIndexMap.IndexOf(tokenColorAtts.Values()[index]->arguments[0]); - } - md.hasContextColor=tokenContextColorAtts.Keys().Contains(tokenIndex); - md.hasAutoComplete=tokenAutoCompleteAtts.Keys().Contains(tokenIndex); - if ((md.isCandidate = tokenCandidateAtts.Keys().Contains(tokenIndex))) - { - const ParsingTable::TokenInfo& tokenInfo = table->GetTokenInfo(md.tableTokenIndex); - auto regex = wtou32(tokenInfo.regex); - if (IsRegexEscapedLiteralString(regex)) - { - md.unescapedRegexText = u32tow(UnescapeTextForRegex(regex)); - } - else - { - md.isCandidate = false; - } - } - - tokenMetaDatas.Add(tokenIndex, md); - } - { - vint fieldCount=table->GetTreeFieldInfoCount(); - for(vint field=0;fieldGetTreeFieldInfo(field); - FieldDesc fieldDesc(fieldInfo.type, fieldInfo.field); - - FieldMetaData md; - md.colorIndex=-1; - - if((index=fieldColorAtts.Keys().IndexOf(fieldDesc))!=-1) - { - md.colorIndex=semanticIndexMap.IndexOf(fieldColorAtts.Values()[index]->arguments[0]); - } - if((index=fieldSemanticAtts.Keys().IndexOf(fieldDesc))!=-1) - { - md.semantics=Ptr(new List); - for (auto argument : fieldSemanticAtts.Values()[index]->arguments) - { - md.semantics->Add(semanticIndexMap.IndexOf(argument)); - } - } - - fieldMetaDatas.Add(fieldDesc, md); - } - } - } - - void RepeatingParsingExecutor::OnContextFinishedAsync(RepeatingParsingOutput& context) - { - if(analyzer) - { - context.cache = analyzer->CreateCacheAsync(context); - } - } - - RepeatingParsingExecutor::RepeatingParsingExecutor(Ptr _grammarParser, const WString& _grammarRule, Ptr _analyzer) - :grammarParser(_grammarParser) - ,grammarRule(_grammarRule) - ,analyzer(_analyzer) - ,autoPushingCallback(0) - { - PrepareMetaData(); - if (analyzer) - { - analyzer->Attach(this); - } - } - - RepeatingParsingExecutor::~RepeatingParsingExecutor() - { - EnsureTaskFinished(); - if (analyzer) - { - analyzer->Detach(this); - } - } - - Ptr RepeatingParsingExecutor::GetParser() - { - return grammarParser; - } - - bool RepeatingParsingExecutor::AttachCallback(ICallback* value) - { - if(!value) return false; - if(callbacks.Contains(value)) return false; - callbacks.Add(value); - return true; - } - - bool RepeatingParsingExecutor::DetachCallback(ICallback* value) - { - if(!value) return false; - if(!callbacks.Contains(value)) return false; - DeactivateCallback(value); - callbacks.Remove(value); - return true; - } - - bool RepeatingParsingExecutor::ActivateCallback(ICallback* value) - { - if(!value) return false; - if(!callbacks.Contains(value)) return false; - if(activatedCallbacks.Contains(value)) return false; - activatedCallbacks.Add(value); - - if(!autoPushingCallback) - { - autoPushingCallback=value; - autoPushingCallback->RequireAutoSubmitTask(true); - } - return true; - } - - bool RepeatingParsingExecutor::DeactivateCallback(ICallback* value) - { - if(!value) return false; - if(!callbacks.Contains(value)) return false; - if(!activatedCallbacks.Contains(value)) return false; - - if(autoPushingCallback==value) - { - autoPushingCallback->RequireAutoSubmitTask(false); - autoPushingCallback=0; - } - activatedCallbacks.Remove(value); - if(!autoPushingCallback && activatedCallbacks.Count()>0) - { - autoPushingCallback=activatedCallbacks[0]; - autoPushingCallback->RequireAutoSubmitTask(true); - } - return true; - } - - Ptr RepeatingParsingExecutor::GetAnalyzer() - { - return analyzer; - } - - vint RepeatingParsingExecutor::GetTokenIndex(const WString& tokenName) - { - vint index=tokenIndexMap.Keys().IndexOf(tokenName); - return index==-1?-1:tokenIndexMap.Values()[index]; - } - - vint RepeatingParsingExecutor::GetSemanticId(const WString& name) - { - return semanticIndexMap.IndexOf(name); - } - - WString RepeatingParsingExecutor::GetSemanticName(vint id) - { - return 0<=id&&id RepeatingParsingExecutor::GetAttribute(vint index, const WString& name, vint argumentCount) - { - if(index!=-1) - { - Ptr att=grammarParser->GetTable()->GetAttributeInfo(index)->FindFirst(name); - if(att && (argumentCount==-1 || att->arguments.Count()==argumentCount)) - { - return att; - } - } - return 0; - } - - Ptr RepeatingParsingExecutor::GetColorAttribute(vint index) - { - return GetAttribute(index, L"Color", 1); - } - - Ptr RepeatingParsingExecutor::GetContextColorAttribute(vint index) - { - return GetAttribute(index, L"ContextColor", 0); - } - - Ptr RepeatingParsingExecutor::GetSemanticAttribute(vint index) - { - return GetAttribute(index, L"Semantic", -1); - } - - Ptr RepeatingParsingExecutor::GetCandidateAttribute(vint index) - { - return GetAttribute(index, L"Candidate", 0); - } - - Ptr RepeatingParsingExecutor::GetAutoCompleteAttribute(vint index) - { - return GetAttribute(index, L"AutoComplete", 0); - } - } - } -} - /*********************************************************************** .\CONTROLS\TOOLSTRIPPACKAGE\GUIMENUCONTROLS.CPP ***********************************************************************/ @@ -31835,6 +27985,7 @@ GuiStackItemComposition /*********************************************************************** .\GRAPHICSCOMPOSITION\GUIGRAPHICSTABLECOMPOSITION.CPP ***********************************************************************/ +#include namespace vl { @@ -32812,781 +28963,6 @@ namespace vl namespace elements { -/*********************************************************************** -SetPropertiesVisitor -***********************************************************************/ - - namespace visitors - { - class SetPropertiesVisitor : public Object, public DocumentRun::IVisitor - { - typedef GuiDocumentElement::GuiDocumentElementRenderer Renderer; - typedef DocumentModel::ResolvedStyle ResolvedStyle; - public: - vint start; - vint length; - vint selectionBegin; - vint selectionEnd; - List styles; - - DocumentModel* model; - Renderer* renderer; - Ptr cache; - IGuiGraphicsParagraph* paragraph; - - SetPropertiesVisitor(DocumentModel* _model, Renderer* _renderer, Ptr _cache, vint _selectionBegin, vint _selectionEnd) - :start(0) - ,length(0) - ,model(_model) - ,renderer(_renderer) - ,cache(_cache) - ,paragraph(_cache->graphicsParagraph.Obj()) - ,selectionBegin(_selectionBegin) - ,selectionEnd(_selectionEnd) - { - ResolvedStyle style; - style=model->GetStyle(DocumentModel::DefaultStyleName, style); - styles.Add(style); - } - - void VisitContainer(DocumentContainerRun* run) - { - for (auto subRun : run->runs) - { - subRun->Accept(this); - } - } - - void ApplyStyle(vint start, vint length, const ResolvedStyle& style) - { - paragraph->SetFont(start, length, style.style.fontFamily); - paragraph->SetSize(start, length, style.style.size); - paragraph->SetStyle(start, length, - (IGuiGraphicsParagraph::TextStyle) - ( (style.style.bold?IGuiGraphicsParagraph::Bold:0) - | (style.style.italic?IGuiGraphicsParagraph::Italic:0) - | (style.style.underline?IGuiGraphicsParagraph::Underline:0) - | (style.style.strikeline?IGuiGraphicsParagraph::Strikeline:0) - )); - } - - void ApplyColor(vint start, vint length, const ResolvedStyle& style) - { - paragraph->SetColor(start, length, style.color); - paragraph->SetBackgroundColor(start, length, style.backgroundColor); - } - - void Visit(DocumentTextRun* run)override - { - length=run->GetRepresentationText().Length(); - if(length>0) - { - ResolvedStyle style=styles[styles.Count()-1]; - ApplyStyle(start, length, style); - ApplyColor(start, length, style); - - vint styleStart=start; - vint styleEnd=styleStart+length; - if(styleStartselectionBegin?styleStart:selectionBegin; - vint s3=selectionEndGetStyle(DocumentModel::SelectionStyleName, style); - ApplyColor(s2, s3-s2, selectionStyle); - } - } - } - start+=length; - } - - void Visit(DocumentStylePropertiesRun* run)override - { - ResolvedStyle style=styles[styles.Count()-1]; - style=model->GetStyle(run->style, style); - styles.Add(style); - VisitContainer(run); - styles.RemoveAt(styles.Count()-1); - } - - void Visit(DocumentStyleApplicationRun* run)override - { - ResolvedStyle style=styles[styles.Count()-1]; - style=model->GetStyle(run->styleName, style); - styles.Add(style); - VisitContainer(run); - styles.RemoveAt(styles.Count()-1); - } - - void Visit(DocumentHyperlinkRun* run)override - { - ResolvedStyle style=styles[styles.Count()-1]; - style=model->GetStyle(run->styleName, style); - styles.Add(style); - VisitContainer(run); - styles.RemoveAt(styles.Count()-1); - } - - void Visit(DocumentImageRun* run)override - { - length=run->GetRepresentationText().Length(); - - auto element=Ptr(GuiImageFrameElement::Create()); - element->SetImage(run->image, run->frameIndex); - element->SetStretch(true); - - IGuiGraphicsParagraph::InlineObjectProperties properties; - properties.size=run->size; - properties.baseline=run->baseline; - properties.breakCondition=IGuiGraphicsParagraph::Alone; - properties.backgroundImage = element; - - paragraph->SetInlineObject(start, length, properties); - - if(startGetStyle(DocumentModel::SelectionStyleName, style); - ApplyColor(start, length, selectionStyle); - } - start+=length; - } - - void Visit(DocumentEmbeddedObjectRun* run)override - { - length=run->GetRepresentationText().Length(); - - IGuiGraphicsParagraph::InlineObjectProperties properties; - properties.breakCondition=IGuiGraphicsParagraph::Alone; - - if (run->name != L"") - { - vint index = renderer->nameCallbackIdMap.Keys().IndexOf(run->name); - if (index != -1) - { - auto id = renderer->nameCallbackIdMap.Values()[index]; - index = cache->embeddedObjects.Keys().IndexOf(id); - if (index != -1) - { - auto eo = cache->embeddedObjects.Values()[index]; - if (eo->start == start) - { - properties.size = eo->size; - properties.callbackId = id; - } - } - } - else - { - auto eo = Ptr(new Renderer::EmbeddedObject); - eo->name = run->name; - eo->size = Size(0, 0); - eo->start = start; - - vint id = -1; - vint count = renderer->freeCallbackIds.Count(); - if (count > 0) - { - id = renderer->freeCallbackIds[count - 1]; - renderer->freeCallbackIds.RemoveAt(count - 1); - } - else - { - id = renderer->usedCallbackIds++; - } - - renderer->nameCallbackIdMap.Add(eo->name, id); - cache->embeddedObjects.Add(id, eo); - properties.callbackId = id; - } - } - - paragraph->SetInlineObject(start, length, properties); - - if(startGetStyle(DocumentModel::SelectionStyleName, style); - ApplyColor(start, length, selectionStyle); - } - start+=length; - } - - void Visit(DocumentParagraphRun* run)override - { - VisitContainer(run); - } - - static vint SetProperty(DocumentModel* model, Renderer* renderer, Ptr cache, Ptr run, vint selectionBegin, vint selectionEnd) - { - SetPropertiesVisitor visitor(model, renderer, cache, selectionBegin, selectionEnd); - run->Accept(&visitor); - return visitor.length; - } - }; - } - using namespace visitors; - -/*********************************************************************** -GuiDocumentElement::GuiDocumentElementRenderer -***********************************************************************/ - - Size GuiDocumentElement::GuiDocumentElementRenderer::OnRenderInlineObject(vint callbackId, Rect location) - { - if (element->callback) - { - auto cache = paragraphCaches[renderingParagraph]; - auto relativeLocation = Rect(Point(location.x1 + renderingParagraphOffset.x, location.y1 + renderingParagraphOffset.y), location.GetSize()); - auto eo = cache->embeddedObjects[callbackId]; - auto size = element->callback->OnRenderEmbeddedObject(eo->name, relativeLocation); - eo->resized = eo->size != size; - eo->size = size; - return eo->size; - } - else - { - return Size(); - } - } - - void GuiDocumentElement::GuiDocumentElementRenderer::InitializeInternal() - { - } - - void GuiDocumentElement::GuiDocumentElementRenderer::FinalizeInternal() - { - } - - void GuiDocumentElement::GuiDocumentElementRenderer::RenderTargetChangedInternal(IGuiGraphicsRenderTarget* oldRenderTarget, IGuiGraphicsRenderTarget* newRenderTarget) - { - // TODO: (enumerable) foreach - for(vint i=0;igraphicsParagraph=0; - } - } - } - - Ptr GuiDocumentElement::GuiDocumentElementRenderer::EnsureAndGetCache(vint paragraphIndex, bool createParagraph) - { - if (paragraphIndex < 0 || paragraphIndex >= paragraphCaches.Count()) return 0; - Ptr paragraph = element->document->paragraphs[paragraphIndex]; - Ptr cache = paragraphCaches[paragraphIndex]; - if (!cache) - { - cache = Ptr(new ParagraphCache); - cache->fullText = paragraph->GetTextForCaret(); - paragraphCaches[paragraphIndex] = cache; - } - - if (createParagraph) - { - if (!cache->graphicsParagraph) - { - cache->graphicsParagraph = layoutProvider->CreateParagraph(cache->fullText, renderTarget, this); - cache->graphicsParagraph->SetParagraphAlignment(paragraph->alignment ? paragraph->alignment.Value() : Alignment::Left); - cache->graphicsParagraph->SetWrapLine(element->wrapLine); - SetPropertiesVisitor::SetProperty(element->document.Obj(), this, cache, paragraph, cache->selectionBegin, cache->selectionEnd); - } - if (cache->graphicsParagraph->GetMaxWidth() != lastMaxWidth) - { - cache->graphicsParagraph->SetMaxWidth(lastMaxWidth); - } - - Size cachedSize = paragraphSizes[paragraphIndex]; - Size realSize = cache->graphicsParagraph->GetSize(); - if (cachedTotalSize.x < realSize.x) - { - cachedTotalSize.x = realSize.x; - } - if (cachedSize.y != realSize.y) - { - cachedTotalSize.y += realSize.y - cachedSize.y; - } - paragraphSizes[paragraphIndex] = realSize; - minSize = cachedTotalSize; - } - - return cache; - } - - bool GuiDocumentElement::GuiDocumentElementRenderer::GetParagraphIndexFromPoint(Point point, vint& top, vint& index) - { - vint y = 0; - // TODO: (enumerable) foreach - for (vint i = 0; i < paragraphSizes.Count(); i++) - { - vint paragraphHeight = paragraphSizes[i].y; - vint nextY = y + paragraphHeight + paragraphDistance; - top = y; - index = i; - - if (nextY <= point.y) - { - y = nextY; - continue; - } - else - { - break; - } - } - return true; - } - - GuiDocumentElement::GuiDocumentElementRenderer::GuiDocumentElementRenderer() - :paragraphDistance(0) - ,lastMaxWidth(-1) - ,layoutProvider(GetGuiGraphicsResourceManager()->GetLayoutProvider()) - ,lastCaret(-1, -1) - ,lastCaretFrontSide(false) - { - } - - void GuiDocumentElement::GuiDocumentElementRenderer::Render(Rect bounds) - { - if (element->callback) - { - element->callback->OnStartRender(); - } - renderTarget->PushClipper(bounds, element); - if (!renderTarget->IsClipperCoverWholeTarget()) - { - vint maxWidth = bounds.Width(); - Rect clipper = renderTarget->GetClipper(); - vint cx = bounds.Left(); - vint cy = bounds.Top(); - vint y1 = clipper.Top() - bounds.Top(); - vint y2 = y1 + clipper.Height(); - vint y = 0; - - lastMaxWidth = maxWidth; - - // TODO: (enumerable) foreach - vint paragraphCount = paragraphSizes.Count(); - if (paragraphCount > element->document->paragraphs.Count()) - { - paragraphCount = element->document->paragraphs.Count(); - } - for (vint i = 0; i < paragraphCount; i++) - { - Size cachedSize = paragraphSizes[i]; - if (y + cachedSize.y <= y1) - { - y += cachedSize.y + paragraphDistance; - continue; - } - else if (y >= y2) - { - break; - } - else - { - Ptr paragraph = element->document->paragraphs[i]; - Ptr cache = paragraphCaches[i]; - bool created = cache && cache->graphicsParagraph; - cache = EnsureAndGetCache(i, true); - if (!created && i == lastCaret.row && element->caretVisible) - { - cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); - } - - cachedSize = cache->graphicsParagraph->GetSize(); - - renderingParagraph = i; - renderingParagraphOffset = Point(cx - bounds.x1, cy + y - bounds.y1); - cache->graphicsParagraph->Render(Rect(Point(cx, cy + y), Size(maxWidth, cachedSize.y))); - renderingParagraph = -1; - - bool resized = false; - // TODO: (enumerable) foreach - for (vint j = 0; j < cache->embeddedObjects.Count(); j++) - { - auto eo = cache->embeddedObjects.Values()[j]; - if (eo->resized) - { - eo->resized = false; - resized = true; - } - } - - if (resized) - { - cache->graphicsParagraph = 0; - } - } - - y += cachedSize.y + paragraphDistance; - } - } - renderTarget->PopClipper(element); - if (element->callback) - { - element->callback->OnFinishRender(); - } - } - - void GuiDocumentElement::GuiDocumentElementRenderer::OnElementStateChanged() - { - cachedTotalSize = { 1,1 }; - if (element->document && element->document->paragraphs.Count() > 0) - { - vint defaultHeight = GetCurrentController()->ResourceService()->GetDefaultFont().size; - paragraphDistance = element->paragraphPadding ? defaultHeight : 0; - - paragraphCaches.Resize(element->document->paragraphs.Count()); - paragraphSizes.Resize(element->document->paragraphs.Count()); - - for (vint i = 0; i < paragraphCaches.Count(); i++) - { - paragraphCaches[i] = 0; - } - for (vint i = 0; i < paragraphSizes.Count(); i++) - { - paragraphSizes[i] = { 0,defaultHeight }; - } - - cachedTotalSize.y = paragraphSizes.Count() * (defaultHeight + paragraphDistance); - if (paragraphSizes.Count()>0) - { - cachedTotalSize.y -= paragraphDistance; - } - } - else - { - paragraphCaches.Resize(0); - paragraphSizes.Resize(0); - } - minSize = cachedTotalSize; - - nameCallbackIdMap.Clear(); - freeCallbackIds.Clear(); - usedCallbackIds = 0; - } - - void GuiDocumentElement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) - { - if (0 <= index && index < paragraphCaches.Count() && 0 <= oldCount && index + oldCount <= paragraphCaches.Count() && 0 <= newCount) - { - vint paragraphCount = element->document->paragraphs.Count(); - CHECK_ERROR(updatedText || oldCount == newCount, L"GuiDocumentlement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); - CHECK_ERROR(paragraphCount - paragraphCaches.Count() == newCount - oldCount, L"GuiDocumentElement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); - - ParagraphCacheArray oldCaches; - CopyFrom(oldCaches, paragraphCaches); - paragraphCaches.Resize(paragraphCount); - - ParagraphSizeArray oldSizes; - CopyFrom(oldSizes, paragraphSizes); - paragraphSizes.Resize(paragraphCount); - - vint defaultHeight = GetCurrentController()->ResourceService()->GetDefaultFont().size; - cachedTotalSize = { 1,1 }; - - for (vint i = 0; i < paragraphCount; i++) - { - if (i < index) - { - paragraphCaches[i] = oldCaches[i]; - paragraphSizes[i] = oldSizes[i]; - } - else if (i < index + newCount) - { - paragraphCaches[i] = 0; - paragraphSizes[i] = { 0,defaultHeight }; - if (!updatedText && i < index + oldCount) - { - auto cache = oldCaches[i]; - if(cache) - { - cache->graphicsParagraph = 0; - } - paragraphCaches[i] = cache; - paragraphSizes[i] = oldSizes[i]; - } - } - else - { - paragraphCaches[i] = oldCaches[i - (newCount - oldCount)]; - paragraphSizes[i] = oldSizes[i - (newCount - oldCount)]; - } - - auto cachedSize = paragraphSizes[i]; - if (cachedTotalSize.x < cachedSize.x) - { - cachedTotalSize.x = cachedSize.x; - } - cachedTotalSize.y += cachedSize.y + paragraphDistance; - } - if (paragraphCount > 0) - { - cachedTotalSize.y -= paragraphDistance; - } - - if (updatedText) - { - vint count = oldCount < newCount ? oldCount : newCount; - for (vint i = 0; i < count; i++) - { - if (auto cache = oldCaches[index + i]) - { - // TODO: (enumerable) foreach on dictionary - for (vint j = 0; j < cache->embeddedObjects.Count(); j++) - { - auto id = cache->embeddedObjects.Keys()[j]; - auto name = cache->embeddedObjects.Values()[j]->name; - nameCallbackIdMap.Remove(name); - freeCallbackIds.Add(id); - } - } - } - } - minSize = cachedTotalSize; - } - } - - Ptr GuiDocumentElement::GuiDocumentElementRenderer::GetHyperlinkFromPoint(Point point) - { - if (!renderTarget) return nullptr; - vint top=0; - vint index=-1; - if(GetParagraphIndexFromPoint(point, top, index)) - { - Ptr cache=EnsureAndGetCache(index, true); - Point paragraphPoint(point.x, point.y-top); - - vint start=-1; - vint length=0; - if(cache->graphicsParagraph->GetInlineObjectFromPoint(paragraphPoint, start, length)) - { - return element->document->GetHyperlink(index, start, start+length); - } - - vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); - return element->document->GetHyperlink(index, caret, caret); - } - return nullptr; - } - - void GuiDocumentElement::GuiDocumentElementRenderer::OpenCaret(TextPos caret, Color color, bool frontSide) - { - CloseCaret(caret); - lastCaret=caret; - lastCaretColor=color; - lastCaretFrontSide=frontSide; - - Ptr cache=paragraphCaches[lastCaret.row]; - if(cache && cache->graphicsParagraph) - { - cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); - } - } - - void GuiDocumentElement::GuiDocumentElementRenderer::CloseCaret(TextPos caret) - { - if(lastCaret!=TextPos(-1, -1)) - { - if(0<=lastCaret.row && lastCaret.row cache=paragraphCaches[lastCaret.row]; - if(cache && cache->graphicsParagraph) - { - cache->graphicsParagraph->CloseCaret(); - } - } - } - lastCaret=caret; - } - - void GuiDocumentElement::GuiDocumentElementRenderer::SetSelection(TextPos begin, TextPos end) - { - if(begin>end) - { - TextPos t=begin; - begin=end; - end=t; - } - if(begin==end) - { - begin=TextPos(-1, -1); - end=TextPos(-1, -1); - } - - if (!renderTarget) return; - // TODO: (enumerable) foreach:indexed - for(vint i=0;i cache=EnsureAndGetCache(i, false); - vint newBegin=i==begin.row?begin.column:0; - vint newEnd=i==end.row?end.column:cache->fullText.Length(); - - if(cache->selectionBegin!=newBegin || cache->selectionEnd!=newEnd) - { - cache->selectionBegin=newBegin; - cache->selectionEnd=newEnd; - NotifyParagraphUpdated(i, 1, 1, false); - } - } - else - { - Ptr cache=paragraphCaches[i]; - if(cache) - { - if(cache->selectionBegin!=-1 || cache->selectionEnd!=-1) - { - cache->selectionBegin=-1; - cache->selectionEnd=-1; - NotifyParagraphUpdated(i, 1, 1, false); - } - } - } - } - } - - TextPos GuiDocumentElement::GuiDocumentElementRenderer::CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide) - { - if (!renderTarget) return comparingCaret; - Ptr cache = EnsureAndGetCache(comparingCaret.row, true); - if (cache) - { - switch (position) - { - case IGuiGraphicsParagraph::CaretFirst: - { - preferFrontSide = false; - vint caret = cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); - return TextPos(comparingCaret.row, caret); - } - case IGuiGraphicsParagraph::CaretLast: - { - preferFrontSide = true; - vint caret = cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); - return TextPos(comparingCaret.row, caret); - } - case IGuiGraphicsParagraph::CaretLineFirst: - { - preferFrontSide = false; - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineFirst, preferFrontSide); - return TextPos(comparingCaret.row, caret); - } - case IGuiGraphicsParagraph::CaretLineLast: - { - preferFrontSide = true; - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineLast, preferFrontSide); - return TextPos(comparingCaret.row, caret); - } - case IGuiGraphicsParagraph::CaretMoveUp: - { - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveUp, preferFrontSide); - if (caret == comparingCaret.column && comparingCaret.row > 0) - { - Rect caretBounds = cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); - Ptr anotherCache = EnsureAndGetCache(comparingCaret.row - 1, true); - vint height = anotherCache->graphicsParagraph->GetSize().y; - caret = anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, height)); - return TextPos(comparingCaret.row - 1, caret); - } - else - { - return TextPos(comparingCaret.row, caret); - } - } - case IGuiGraphicsParagraph::CaretMoveDown: - { - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveDown, preferFrontSide); - if (caret == comparingCaret.column && comparingCaret.row < paragraphCaches.Count() - 1) - { - Rect caretBounds = cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); - Ptr anotherCache = EnsureAndGetCache(comparingCaret.row + 1, true); - caret = anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, 0)); - return TextPos(comparingCaret.row + 1, caret); - } - else - { - return TextPos(comparingCaret.row, caret); - } - } - case IGuiGraphicsParagraph::CaretMoveLeft: - { - preferFrontSide = false; - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveLeft, preferFrontSide); - if (caret == comparingCaret.column && comparingCaret.row > 0) - { - Ptr anotherCache = EnsureAndGetCache(comparingCaret.row - 1, true); - caret = anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); - return TextPos(comparingCaret.row - 1, caret); - } - else - { - return TextPos(comparingCaret.row, caret); - } - } - case IGuiGraphicsParagraph::CaretMoveRight: - { - preferFrontSide = true; - vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveRight, preferFrontSide); - if (caret == comparingCaret.column && comparingCaret.row < paragraphCaches.Count() - 1) - { - Ptr anotherCache = EnsureAndGetCache(comparingCaret.row + 1, true); - caret = anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); - return TextPos(comparingCaret.row + 1, caret); - } - else - { - return TextPos(comparingCaret.row, caret); - } - } - } - } - return comparingCaret; - } - - TextPos GuiDocumentElement::GuiDocumentElementRenderer::CalculateCaretFromPoint(Point point) - { - if (!renderTarget) return TextPos(-1, -1); - vint top=0; - vint index=-1; - if(GetParagraphIndexFromPoint(point, top, index)) - { - Ptr cache=EnsureAndGetCache(index, true); - Point paragraphPoint(point.x, point.y-top); - vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); - return TextPos(index, caret); - } - return TextPos(-1, -1); - } - - Rect GuiDocumentElement::GuiDocumentElementRenderer::GetCaretBounds(TextPos caret, bool frontSide) - { - if (!renderTarget) return Rect(); - Ptr cache = EnsureAndGetCache(caret.row, true); - if (cache) - { - Rect bounds = cache->graphicsParagraph->GetCaretBounds(caret.column, frontSide); - if (bounds != Rect()) - { - vint y = 0; - for (vint i = 0; i < caret.row; i++) - { - EnsureAndGetCache(i, true); - y += paragraphSizes[i].y + paragraphDistance; - } - - bounds.y1 += y; - bounds.y2 += y; - return bounds; - } - } - return Rect(); - } - /*********************************************************************** GuiDocumentElement ***********************************************************************/ @@ -33610,17 +28986,18 @@ GuiDocumentElement } GuiDocumentElement::GuiDocumentElement() - :caretVisible(false) + :passwordChar(0) + ,caretVisible(false) ,caretFrontSide(false) { } - GuiDocumentElement::ICallback* GuiDocumentElement::GetCallback() + IGuiDocumentElementCallback* GuiDocumentElement::GetCallback() { return callback; } - void GuiDocumentElement::SetCallback(ICallback* value) + void GuiDocumentElement::SetCallback(IGuiDocumentElementCallback* value) { callback = value; } @@ -33659,6 +29036,20 @@ GuiDocumentElement InvokeOnElementStateChanged(); } + wchar_t GuiDocumentElement::GetPasswordChar() + { + return passwordChar; + } + + void GuiDocumentElement::SetPasswordChar(wchar_t value) + { + if(passwordChar!=value) + { + passwordChar=value; + InvokeOnElementStateChanged(); + } + } + TextPos GuiDocumentElement::GetCaretBegin() { return caretBegin; @@ -34046,6 +29437,811 @@ GuiDocumentElement } } +/*********************************************************************** +.\GRAPHICSELEMENT\GUIGRAPHICSDOCUMENTRENDERER.CPP +***********************************************************************/ + +namespace vl +{ + using namespace collections; + + namespace presentation + { + namespace elements + { + +/*********************************************************************** +SetPropertiesVisitor +***********************************************************************/ + + namespace visitors + { + class SetPropertiesVisitor : public Object, public DocumentRun::IVisitor + { + typedef GuiDocumentElementRenderer Renderer; + typedef DocumentModel::ResolvedStyle ResolvedStyle; + public: + vint start; + vint length; + vint selectionBegin; + vint selectionEnd; + List styles; + + DocumentModel* model; + Renderer* renderer; + Ptr cache; + IGuiGraphicsParagraph* paragraph; + + SetPropertiesVisitor(DocumentModel* _model, Renderer* _renderer, Ptr _cache, vint _selectionBegin, vint _selectionEnd) + :start(0) + ,length(0) + ,model(_model) + ,renderer(_renderer) + ,cache(_cache) + ,paragraph(_cache->graphicsParagraph.Obj()) + ,selectionBegin(_selectionBegin) + ,selectionEnd(_selectionEnd) + { + ResolvedStyle style; + style=model->GetStyle(DocumentModel::DefaultStyleName, style); + styles.Add(style); + } + + void VisitContainer(DocumentContainerRun* run) + { + for (auto subRun : run->runs) + { + subRun->Accept(this); + } + } + + void ApplyStyle(vint start, vint length, const ResolvedStyle& style) + { + paragraph->SetFont(start, length, style.style.fontFamily); + paragraph->SetSize(start, length, style.style.size); + paragraph->SetStyle(start, length, + (IGuiGraphicsParagraph::TextStyle) + ( (style.style.bold?IGuiGraphicsParagraph::Bold:0) + | (style.style.italic?IGuiGraphicsParagraph::Italic:0) + | (style.style.underline?IGuiGraphicsParagraph::Underline:0) + | (style.style.strikeline?IGuiGraphicsParagraph::Strikeline:0) + )); + } + + void ApplyColor(vint start, vint length, const ResolvedStyle& style) + { + paragraph->SetColor(start, length, style.color); + paragraph->SetBackgroundColor(start, length, style.backgroundColor); + } + + void Visit(DocumentTextRun* run)override + { + length=run->GetRepresentationText().Length(); + if(length>0) + { + ResolvedStyle style=styles[styles.Count()-1]; + ApplyStyle(start, length, style); + ApplyColor(start, length, style); + + vint styleStart=start; + vint styleEnd=styleStart+length; + if(styleStartselectionBegin?styleStart:selectionBegin; + vint s3=selectionEndGetStyle(DocumentModel::SelectionStyleName, style); + ApplyColor(s2, s3-s2, selectionStyle); + } + } + } + start+=length; + } + + void Visit(DocumentStylePropertiesRun* run)override + { + ResolvedStyle style=styles[styles.Count()-1]; + style=model->GetStyle(run->style, style); + styles.Add(style); + VisitContainer(run); + styles.RemoveAt(styles.Count()-1); + } + + void Visit(DocumentStyleApplicationRun* run)override + { + ResolvedStyle style=styles[styles.Count()-1]; + style=model->GetStyle(run->styleName, style); + styles.Add(style); + VisitContainer(run); + styles.RemoveAt(styles.Count()-1); + } + + void Visit(DocumentHyperlinkRun* run)override + { + ResolvedStyle style=styles[styles.Count()-1]; + style=model->GetStyle(run->styleName, style); + styles.Add(style); + VisitContainer(run); + styles.RemoveAt(styles.Count()-1); + } + + void Visit(DocumentImageRun* run)override + { + length=run->GetRepresentationText().Length(); + + auto element=Ptr(GuiImageFrameElement::Create()); + element->SetImage(run->image, run->frameIndex); + element->SetStretch(true); + + IGuiGraphicsParagraph::InlineObjectProperties properties; + properties.size=run->size; + properties.baseline=run->baseline; + properties.breakCondition=IGuiGraphicsParagraph::Alone; + properties.backgroundImage = element; + + paragraph->SetInlineObject(start, length, properties); + + if(startGetStyle(DocumentModel::SelectionStyleName, style); + ApplyColor(start, length, selectionStyle); + } + start+=length; + } + + void Visit(DocumentEmbeddedObjectRun* run)override + { + length=run->GetRepresentationText().Length(); + + IGuiGraphicsParagraph::InlineObjectProperties properties; + properties.breakCondition=IGuiGraphicsParagraph::Alone; + + if (run->name != L"") + { + vint index = renderer->nameCallbackIdMap.Keys().IndexOf(run->name); + if (index != -1) + { + auto id = renderer->nameCallbackIdMap.Values()[index]; + index = cache->embeddedObjects.Keys().IndexOf(id); + if (index != -1) + { + auto eo = cache->embeddedObjects.Values()[index]; + if (eo->start == start) + { + properties.size = eo->size; + properties.callbackId = id; + } + } + } + else + { + auto eo = Ptr(new Renderer::EmbeddedObject); + eo->name = run->name; + eo->size = Size(0, 0); + eo->start = start; + + vint id = -1; + vint count = renderer->freeCallbackIds.Count(); + if (count > 0) + { + id = renderer->freeCallbackIds[count - 1]; + renderer->freeCallbackIds.RemoveAt(count - 1); + } + else + { + id = renderer->usedCallbackIds++; + } + + renderer->nameCallbackIdMap.Add(eo->name, id); + cache->embeddedObjects.Add(id, eo); + properties.callbackId = id; + } + } + + paragraph->SetInlineObject(start, length, properties); + + if(startGetStyle(DocumentModel::SelectionStyleName, style); + ApplyColor(start, length, selectionStyle); + } + start+=length; + } + + void Visit(DocumentParagraphRun* run)override + { + VisitContainer(run); + } + + static vint SetProperty(DocumentModel* model, Renderer* renderer, Ptr cache, Ptr run, vint selectionBegin, vint selectionEnd) + { + SetPropertiesVisitor visitor(model, renderer, cache, selectionBegin, selectionEnd); + run->Accept(&visitor); + return visitor.length; + } + }; + } + using namespace visitors; + +/*********************************************************************** +GuiDocumentElementRenderer +***********************************************************************/ + + Size GuiDocumentElementRenderer::OnRenderInlineObject(vint callbackId, Rect location) + { + if (auto callback = element->GetCallback()) + { + auto cache = paragraphCaches[renderingParagraph]; + auto relativeLocation = Rect(Point(location.x1 + renderingParagraphOffset.x, location.y1 + renderingParagraphOffset.y), location.GetSize()); + auto eo = cache->embeddedObjects[callbackId]; + auto size = callback->OnRenderEmbeddedObject(eo->name, relativeLocation); + eo->resized = eo->size != size; + eo->size = size; + return eo->size; + } + else + { + return Size(); + } + } + + void GuiDocumentElementRenderer::InitializeInternal() + { + } + + void GuiDocumentElementRenderer::FinalizeInternal() + { + } + + void GuiDocumentElementRenderer::RenderTargetChangedInternal(IGuiGraphicsRenderTarget* oldRenderTarget, IGuiGraphicsRenderTarget* newRenderTarget) + { + // TODO: (enumerable) foreach + for(vint i=0;igraphicsParagraph=0; + } + } + } + + Ptr GuiDocumentElementRenderer::EnsureAndGetCache(vint paragraphIndex, bool createParagraph) + { + if (paragraphIndex < 0 || paragraphIndex >= paragraphCaches.Count()) return 0; + Ptr paragraph = element->GetDocument()->paragraphs[paragraphIndex]; + Ptr cache = paragraphCaches[paragraphIndex]; + if (!cache) + { + cache = Ptr(new ParagraphCache); + cache->fullText = paragraph->GetTextForCaret(); + paragraphCaches[paragraphIndex] = cache; + } + + if (createParagraph) + { + if (!cache->graphicsParagraph) + { + auto paragraphText = cache->fullText; + if (auto passwordChar = element->GetPasswordChar()) + { + Array passwordText(paragraphText.Length() + 1); + for (vint i = 0; i < paragraphText.Length(); i++) + { + passwordText[i] = passwordChar; + } + passwordText[paragraphText.Length()] = 0; + paragraphText = &passwordText[0]; + } + cache->graphicsParagraph = layoutProvider->CreateParagraph(paragraphText, renderTarget, this); + cache->graphicsParagraph->SetParagraphAlignment(paragraph->alignment ? paragraph->alignment.Value() : Alignment::Left); + cache->graphicsParagraph->SetWrapLine(element->GetWrapLine()); + SetPropertiesVisitor::SetProperty(element->GetDocument().Obj(), this, cache, paragraph, cache->selectionBegin, cache->selectionEnd); + } + if (cache->graphicsParagraph->GetMaxWidth() != lastMaxWidth) + { + cache->graphicsParagraph->SetMaxWidth(lastMaxWidth); + } + + Size cachedSize = paragraphSizes[paragraphIndex]; + Size realSize = cache->graphicsParagraph->GetSize(); + if (cachedTotalSize.x < realSize.x) + { + cachedTotalSize.x = realSize.x; + } + if (cachedSize.y != realSize.y) + { + cachedTotalSize.y += realSize.y - cachedSize.y; + } + paragraphSizes[paragraphIndex] = realSize; + minSize = cachedTotalSize; + } + + return cache; + } + + bool GuiDocumentElementRenderer::GetParagraphIndexFromPoint(Point point, vint& top, vint& index) + { + vint y = 0; + // TODO: (enumerable) foreach + for (vint i = 0; i < paragraphSizes.Count(); i++) + { + vint paragraphHeight = paragraphSizes[i].y; + vint nextY = y + paragraphHeight + paragraphDistance; + top = y; + index = i; + + if (nextY <= point.y) + { + y = nextY; + continue; + } + else + { + break; + } + } + return true; + } + + GuiDocumentElementRenderer::GuiDocumentElementRenderer() + :paragraphDistance(0) + ,lastMaxWidth(-1) + ,layoutProvider(GetGuiGraphicsResourceManager()->GetLayoutProvider()) + ,lastCaret(-1, -1) + ,lastCaretFrontSide(false) + { + } + + void GuiDocumentElementRenderer::Render(Rect bounds) + { + if (auto callback = element->GetCallback()) + { + callback->OnStartRender(); + } + renderTarget->PushClipper(bounds, element); + if (!renderTarget->IsClipperCoverWholeTarget()) + { + vint maxWidth = bounds.Width(); + Rect clipper = renderTarget->GetClipper(); + vint cx = bounds.Left(); + vint cy = bounds.Top(); + vint y1 = clipper.Top() - bounds.Top(); + vint y2 = y1 + clipper.Height(); + vint y = 0; + + lastMaxWidth = maxWidth; + + // TODO: (enumerable) foreach + vint paragraphCount = paragraphSizes.Count(); + auto document = element->GetDocument(); + if (paragraphCount > document->paragraphs.Count()) + { + paragraphCount = document->paragraphs.Count(); + } + for (vint i = 0; i < paragraphCount; i++) + { + Size cachedSize = paragraphSizes[i]; + if (y + cachedSize.y <= y1) + { + y += cachedSize.y + paragraphDistance; + continue; + } + else if (y >= y2) + { + break; + } + else + { + Ptr paragraph = document->paragraphs[i]; + Ptr cache = paragraphCaches[i]; + bool created = cache && cache->graphicsParagraph; + cache = EnsureAndGetCache(i, true); + if (!created && i == lastCaret.row && element->GetCaretVisible()) + { + cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); + } + + cachedSize = cache->graphicsParagraph->GetSize(); + + renderingParagraph = i; + renderingParagraphOffset = Point(cx - bounds.x1, cy + y - bounds.y1); + cache->graphicsParagraph->Render(Rect(Point(cx, cy + y), Size(maxWidth, cachedSize.y))); + renderingParagraph = -1; + + bool resized = false; + // TODO: (enumerable) foreach + for (vint j = 0; j < cache->embeddedObjects.Count(); j++) + { + auto eo = cache->embeddedObjects.Values()[j]; + if (eo->resized) + { + eo->resized = false; + resized = true; + } + } + + if (resized) + { + cache->graphicsParagraph = 0; + } + } + + y += cachedSize.y + paragraphDistance; + } + } + renderTarget->PopClipper(element); + if (auto callback = element->GetCallback()) + { + callback->OnFinishRender(); + } + } + + void GuiDocumentElementRenderer::OnElementStateChanged() + { + cachedTotalSize = { 1,1 }; + auto document = element->GetDocument(); + if (document && document->paragraphs.Count() > 0) + { + vint defaultHeight = GetCurrentController()->ResourceService()->GetDefaultFont().size; + paragraphDistance = element->GetParagraphPadding() ? defaultHeight : 0; + + paragraphCaches.Resize(document->paragraphs.Count()); + paragraphSizes.Resize(document->paragraphs.Count()); + + for (vint i = 0; i < paragraphCaches.Count(); i++) + { + paragraphCaches[i] = 0; + } + for (vint i = 0; i < paragraphSizes.Count(); i++) + { + paragraphSizes[i] = { 0,defaultHeight }; + } + + cachedTotalSize.y = paragraphSizes.Count() * (defaultHeight + paragraphDistance); + if (paragraphSizes.Count()>0) + { + cachedTotalSize.y -= paragraphDistance; + } + } + else + { + paragraphCaches.Resize(0); + paragraphSizes.Resize(0); + } + minSize = cachedTotalSize; + + nameCallbackIdMap.Clear(); + freeCallbackIds.Clear(); + usedCallbackIds = 0; + } + + void GuiDocumentElementRenderer::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) + { + if (0 <= index && index < paragraphCaches.Count() && 0 <= oldCount && index + oldCount <= paragraphCaches.Count() && 0 <= newCount) + { + vint paragraphCount = element->GetDocument()->paragraphs.Count(); + CHECK_ERROR(updatedText || oldCount == newCount, L"GuiDocumentlement::GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); + CHECK_ERROR(paragraphCount - paragraphCaches.Count() == newCount - oldCount, L"GuiDocumentElementRenderer::NotifyParagraphUpdated(vint, vint, vint, bool)#Illegal values of oldCount and newCount."); + + ParagraphCacheArray oldCaches; + CopyFrom(oldCaches, paragraphCaches); + paragraphCaches.Resize(paragraphCount); + + ParagraphSizeArray oldSizes; + CopyFrom(oldSizes, paragraphSizes); + paragraphSizes.Resize(paragraphCount); + + vint defaultHeight = GetCurrentController()->ResourceService()->GetDefaultFont().size; + cachedTotalSize = { 1,1 }; + + for (vint i = 0; i < paragraphCount; i++) + { + if (i < index) + { + paragraphCaches[i] = oldCaches[i]; + paragraphSizes[i] = oldSizes[i]; + } + else if (i < index + newCount) + { + paragraphCaches[i] = 0; + paragraphSizes[i] = { 0,defaultHeight }; + if (!updatedText && i < index + oldCount) + { + auto cache = oldCaches[i]; + if(cache) + { + cache->graphicsParagraph = 0; + } + paragraphCaches[i] = cache; + paragraphSizes[i] = oldSizes[i]; + } + } + else + { + paragraphCaches[i] = oldCaches[i - (newCount - oldCount)]; + paragraphSizes[i] = oldSizes[i - (newCount - oldCount)]; + } + + auto cachedSize = paragraphSizes[i]; + if (cachedTotalSize.x < cachedSize.x) + { + cachedTotalSize.x = cachedSize.x; + } + cachedTotalSize.y += cachedSize.y + paragraphDistance; + } + if (paragraphCount > 0) + { + cachedTotalSize.y -= paragraphDistance; + } + + if (updatedText) + { + vint count = oldCount < newCount ? oldCount : newCount; + for (vint i = 0; i < count; i++) + { + if (auto cache = oldCaches[index + i]) + { + // TODO: (enumerable) foreach on dictionary + for (vint j = 0; j < cache->embeddedObjects.Count(); j++) + { + auto id = cache->embeddedObjects.Keys()[j]; + auto name = cache->embeddedObjects.Values()[j]->name; + nameCallbackIdMap.Remove(name); + freeCallbackIds.Add(id); + } + } + } + } + minSize = cachedTotalSize; + } + } + + Ptr GuiDocumentElementRenderer::GetHyperlinkFromPoint(Point point) + { + if (!renderTarget) return nullptr; + vint top=0; + vint index=-1; + if(GetParagraphIndexFromPoint(point, top, index)) + { + auto document = element->GetDocument(); + Ptr cache=EnsureAndGetCache(index, true); + Point paragraphPoint(point.x, point.y-top); + + vint start=-1; + vint length=0; + if(cache->graphicsParagraph->GetInlineObjectFromPoint(paragraphPoint, start, length)) + { + return document->GetHyperlink(index, start, start+length); + } + + vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); + return document->GetHyperlink(index, caret, caret); + } + return nullptr; + } + + void GuiDocumentElementRenderer::OpenCaret(TextPos caret, Color color, bool frontSide) + { + CloseCaret(caret); + lastCaret=caret; + lastCaretColor=color; + lastCaretFrontSide=frontSide; + + Ptr cache=paragraphCaches[lastCaret.row]; + if(cache && cache->graphicsParagraph) + { + cache->graphicsParagraph->OpenCaret(lastCaret.column, lastCaretColor, lastCaretFrontSide); + } + } + + void GuiDocumentElementRenderer::CloseCaret(TextPos caret) + { + if(lastCaret!=TextPos(-1, -1)) + { + if(0<=lastCaret.row && lastCaret.row cache=paragraphCaches[lastCaret.row]; + if(cache && cache->graphicsParagraph) + { + cache->graphicsParagraph->CloseCaret(); + } + } + } + lastCaret=caret; + } + + void GuiDocumentElementRenderer::SetSelection(TextPos begin, TextPos end) + { + if(begin>end) + { + TextPos t=begin; + begin=end; + end=t; + } + if(begin==end) + { + begin=TextPos(-1, -1); + end=TextPos(-1, -1); + } + + if (!renderTarget) return; + // TODO: (enumerable) foreach:indexed + for(vint i=0;i cache=EnsureAndGetCache(i, false); + vint newBegin=i==begin.row?begin.column:0; + vint newEnd=i==end.row?end.column:cache->fullText.Length(); + + if(cache->selectionBegin!=newBegin || cache->selectionEnd!=newEnd) + { + cache->selectionBegin=newBegin; + cache->selectionEnd=newEnd; + NotifyParagraphUpdated(i, 1, 1, false); + } + } + else + { + Ptr cache=paragraphCaches[i]; + if(cache) + { + if(cache->selectionBegin!=-1 || cache->selectionEnd!=-1) + { + cache->selectionBegin=-1; + cache->selectionEnd=-1; + NotifyParagraphUpdated(i, 1, 1, false); + } + } + } + } + } + + TextPos GuiDocumentElementRenderer::CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide) + { + if (!renderTarget) return comparingCaret; + Ptr cache = EnsureAndGetCache(comparingCaret.row, true); + if (cache) + { + switch (position) + { + case IGuiGraphicsParagraph::CaretFirst: + { + preferFrontSide = false; + vint caret = cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); + return TextPos(comparingCaret.row, caret); + } + case IGuiGraphicsParagraph::CaretLast: + { + preferFrontSide = true; + vint caret = cache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); + return TextPos(comparingCaret.row, caret); + } + case IGuiGraphicsParagraph::CaretLineFirst: + { + preferFrontSide = false; + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineFirst, preferFrontSide); + return TextPos(comparingCaret.row, caret); + } + case IGuiGraphicsParagraph::CaretLineLast: + { + preferFrontSide = true; + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretLineLast, preferFrontSide); + return TextPos(comparingCaret.row, caret); + } + case IGuiGraphicsParagraph::CaretMoveUp: + { + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveUp, preferFrontSide); + if (caret == comparingCaret.column && comparingCaret.row > 0) + { + Rect caretBounds = cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); + Ptr anotherCache = EnsureAndGetCache(comparingCaret.row - 1, true); + vint height = anotherCache->graphicsParagraph->GetSize().y; + caret = anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, height)); + return TextPos(comparingCaret.row - 1, caret); + } + else + { + return TextPos(comparingCaret.row, caret); + } + } + case IGuiGraphicsParagraph::CaretMoveDown: + { + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveDown, preferFrontSide); + if (caret == comparingCaret.column && comparingCaret.row < paragraphCaches.Count() - 1) + { + Rect caretBounds = cache->graphicsParagraph->GetCaretBounds(comparingCaret.column, preferFrontSide); + Ptr anotherCache = EnsureAndGetCache(comparingCaret.row + 1, true); + caret = anotherCache->graphicsParagraph->GetCaretFromPoint(Point(caretBounds.x1, 0)); + return TextPos(comparingCaret.row + 1, caret); + } + else + { + return TextPos(comparingCaret.row, caret); + } + } + case IGuiGraphicsParagraph::CaretMoveLeft: + { + preferFrontSide = false; + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveLeft, preferFrontSide); + if (caret == comparingCaret.column && comparingCaret.row > 0) + { + Ptr anotherCache = EnsureAndGetCache(comparingCaret.row - 1, true); + caret = anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretLast, preferFrontSide); + return TextPos(comparingCaret.row - 1, caret); + } + else + { + return TextPos(comparingCaret.row, caret); + } + } + case IGuiGraphicsParagraph::CaretMoveRight: + { + preferFrontSide = true; + vint caret = cache->graphicsParagraph->GetCaret(comparingCaret.column, IGuiGraphicsParagraph::CaretMoveRight, preferFrontSide); + if (caret == comparingCaret.column && comparingCaret.row < paragraphCaches.Count() - 1) + { + Ptr anotherCache = EnsureAndGetCache(comparingCaret.row + 1, true); + caret = anotherCache->graphicsParagraph->GetCaret(0, IGuiGraphicsParagraph::CaretFirst, preferFrontSide); + return TextPos(comparingCaret.row + 1, caret); + } + else + { + return TextPos(comparingCaret.row, caret); + } + } + } + } + return comparingCaret; + } + + TextPos GuiDocumentElementRenderer::CalculateCaretFromPoint(Point point) + { + if (!renderTarget) return TextPos(-1, -1); + vint top=0; + vint index=-1; + if(GetParagraphIndexFromPoint(point, top, index)) + { + Ptr cache=EnsureAndGetCache(index, true); + Point paragraphPoint(point.x, point.y-top); + vint caret=cache->graphicsParagraph->GetCaretFromPoint(paragraphPoint); + return TextPos(index, caret); + } + return TextPos(-1, -1); + } + + Rect GuiDocumentElementRenderer::GetCaretBounds(TextPos caret, bool frontSide) + { + if (!renderTarget) return Rect(); + Ptr cache = EnsureAndGetCache(caret.row, true); + if (cache) + { + Rect bounds = cache->graphicsParagraph->GetCaretBounds(caret.column, frontSide); + if (bounds != Rect()) + { + vint y = 0; + for (vint i = 0; i < caret.row; i++) + { + EnsureAndGetCache(i, true); + y += paragraphSizes[i].y + paragraphDistance; + } + + bounds.y1 += y; + bounds.y2 += y; + return bounds; + } + } + return Rect(); + } + } + } +} + /*********************************************************************** .\GRAPHICSELEMENT\GUIGRAPHICSELEMENT.CPP ***********************************************************************/ @@ -34845,885 +31041,6 @@ GuiGraphicsResourceManager } } -/*********************************************************************** -.\GRAPHICSELEMENT\GUIGRAPHICSTEXTELEMENT.CPP -***********************************************************************/ - -namespace vl -{ - using namespace collections; - - namespace presentation - { - namespace elements - { - namespace text - { - -/*********************************************************************** -text::TextLine -***********************************************************************/ - - TextLine::TextLine() - :text(0) - ,att(0) - ,availableOffsetCount(0) - ,bufferLength(0) - ,dataLength(0) - ,lexerFinalState(-1) - ,contextFinalState(-1) - { - } - - TextLine::~TextLine() - { - } - - vint TextLine::CalculateBufferLength(vint dataLength) - { - if(dataLength<1)dataLength=1; - vint bufferLength=dataLength-dataLength%BlockSize; - if(bufferLengthdataLength || inputCount<0) return false; - - vint newDataLength=dataLength-count+inputCount; - vint newBufferLength=CalculateBufferLength(newDataLength); - if(newBufferLength!=bufferLength) - { - wchar_t* newText=new wchar_t[newBufferLength]; - memcpy(newText, text, start*sizeof(wchar_t)); - memcpy(newText+start, input, inputCount*sizeof(wchar_t)); - memcpy(newText+start+inputCount, text+start+count, (dataLength-start-count)*sizeof(wchar_t)); - - CharAtt* newAtt=new CharAtt[newBufferLength]; - memcpy(newAtt, att, start*sizeof(CharAtt)); - memset(newAtt+start, 0, inputCount*sizeof(CharAtt)); - memcpy(newAtt+start+inputCount, att+start+count, (dataLength-start-count)*sizeof(CharAtt)); - - delete[] text; - delete[] att; - text=newText; - att=newAtt; - } - else - { - memmove(text+start+inputCount, text+start+count, (dataLength-start-count)*sizeof(wchar_t)); - memmove(att+start+inputCount, att+start+count, (dataLength-start-count)*sizeof(CharAtt)); - memcpy(text+start, input, inputCount*sizeof(wchar_t)); - memset(att+start, 0, inputCount*sizeof(CharAtt)); - } - dataLength=newDataLength; - bufferLength=newBufferLength; - if(availableOffsetCount>start) - { - availableOffsetCount=start; - } - - return true; - } - - TextLine TextLine::Split(vint index) - { - if(index<0 || index>dataLength) return TextLine(); - vint count=dataLength-index; - TextLine line; - line.Initialize(); - line.Modify(0, 0, text+index, count); - memcpy(line.att, att+index, count*sizeof(CharAtt)); - Modify(index, count, L"", 0); - return line; - } - - void TextLine::AppendAndFinalize(TextLine& line) - { - vint oldDataLength=dataLength; - Modify(oldDataLength, 0, line.text, line.dataLength); - memcpy(att+oldDataLength, line.att, line.dataLength*sizeof(CharAtt)); - line.Finalize(); - } - -/*********************************************************************** -text::CharMeasurer -***********************************************************************/ - - CharMeasurer::CharMeasurer(vint _rowHeight) - :rowHeight(_rowHeight) - { - memset(widths, 0, sizeof(widths)); - } - - CharMeasurer::~CharMeasurer() - { - } - - void CharMeasurer::SetRenderTarget(IGuiGraphicsRenderTarget* value) - { - if(oldRenderTarget!=value) - { - oldRenderTarget=value; - rowHeight=GetRowHeightInternal(oldRenderTarget); - memset(widths, 0, sizeof(widths)); - } - } - - vint CharMeasurer::MeasureWidth(UnicodeCodePoint codePoint) - { - vuint32_t index = codePoint.GetCodePoint(); - if (0 <= index && index < 65536) - { - vint w = widths[index]; - if (w == 0) - { - widths[index] = w = MeasureWidthInternal(codePoint, oldRenderTarget); - } - return w; - } - else if (index < 0x110000) - { - return MeasureWidthInternal(codePoint, oldRenderTarget); - } - else - { - return 0; - } - } - - vint CharMeasurer::GetRowHeight() - { - return rowHeight; - } - -/*********************************************************************** -text::TextLines -***********************************************************************/ - - TextLines::TextLines(GuiColorizedTextElement* _ownerElement) - :ownerElement(_ownerElement) - ,charMeasurer(0) - ,renderTarget(0) - ,tabWidth(1) - ,tabSpaceCount(4) - ,passwordChar(L'\0') - { - TextLine line; - line.Initialize(); - lines.Add(line); - } - - TextLines::~TextLines() - { - RemoveLines(0, lines.Count()); - } - - //-------------------------------------------------------- - - vint TextLines::GetCount() - { - return lines.Count(); - } - - TextLine& TextLines::GetLine(vint row) - { - return lines[row]; - } - - CharMeasurer* TextLines::GetCharMeasurer() - { - return charMeasurer; - } - - void TextLines::SetCharMeasurer(CharMeasurer* value) - { - charMeasurer=value; - if(charMeasurer) charMeasurer->SetRenderTarget(renderTarget); - ClearMeasurement(); - } - - IGuiGraphicsRenderTarget* TextLines::GetRenderTarget() - { - return renderTarget; - } - - void TextLines::SetRenderTarget(IGuiGraphicsRenderTarget* value) - { - renderTarget=value; - if(charMeasurer) charMeasurer->SetRenderTarget(renderTarget); - ClearMeasurement(); - } - - WString TextLines::GetText(TextPos start, TextPos end) - { - if(!IsAvailable(start) || !IsAvailable(end) || start>end) return L""; - - if(start.row==end.row) - { - return WString::CopyFrom(lines[start.row].text+start.column, end.column-start.column); - } - - vint count=0; - for(vint i=start.row+1;i buffer; - buffer.Resize(count+(end.row-start.row)*2); - wchar_t* writing=&buffer[0]; - - for(vint i=start.row;i<=end.row;i++) - { - wchar_t* text=lines[i].text; - vint chars=0; - if(i==start.row) - { - text+=start.column; - chars=lines[i].dataLength-start.column; - } - else if(i==end.row) - { - chars=end.column; - } - else - { - chars=lines[i].dataLength; - } - - if(i!=start.row) - { - *writing++=L'\r'; - *writing++=L'\n'; - } - memcpy(writing, text, chars*sizeof(wchar_t)); - writing+=chars; - } - return WString::CopyFrom(&buffer[0], buffer.Count()); - } - - WString TextLines::GetText() - { - return GetText(TextPos(0, 0), TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength)); - } - - void TextLines::SetText(const WString& value) - { - Modify(TextPos(0, 0), TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength), value); - } - - //-------------------------------------------------------- - - bool TextLines::RemoveLines(vint start, vint count) - { - if(start<0 || count<0 || start+count>lines.Count()) return false; - for(vint i=start+count-1;i>=start;i--) - { - lines[i].Finalize(); - } - lines.RemoveRange(start, count); - return true; - } - - bool TextLines::IsAvailable(TextPos pos) - { - return 0<=pos.row && pos.row=lines.Count()) - { - return TextPos(lines.Count()-1, lines[lines.Count()-1].dataLength); - } - else - { - TextLine& line=lines[pos.row]; - if(pos.column<0) - { - return TextPos(pos.row, 0); - } - else if(pos.column>line.dataLength) - { - return TextPos(pos.row, line.dataLength); - } - else - { - return pos; - } - } - } - - TextPos TextLines::Modify(TextPos start, TextPos end, const wchar_t** inputs, vint* inputCounts, vint rows) - { - if(!IsAvailable(start) || !IsAvailable(end) || start>end) return TextPos(-1, -1); - if (ownerElement) - { - ownerElement->InvokeOnElementStateChanged(); - } - - if(rows==1) - { - if(start.row==end.row) - { - lines[start.row].Modify(start.column, end.column-start.column, inputs[0], inputCounts[0]); - } - else - { - if(end.row-start.row>1) - { - RemoveLines(start.row+1, end.row-start.row-1); - } - vint modifyCount=lines[start.row].dataLength-start.column+end.column; - lines[start.row].AppendAndFinalize(lines[start.row+1]); - lines.RemoveAt(start.row+1); - lines[start.row].Modify(start.column, modifyCount, inputs[0], inputCounts[0]); - } - return TextPos(start.row, start.column+inputCounts[0]); - } - - if(start.row==end.row) - { - TextLine newLine=lines[start.row].Split(end.column); - lines.Insert(start.row+1, newLine); - end=TextPos(start.row+1, 0); - } - - vint oldMiddleLines=end.row-start.row-1; - vint newMiddleLines=rows-2; - if(oldMiddleLinesnewMiddleLines) - { - RemoveLines(start.row+newMiddleLines+1, oldMiddleLines-newMiddleLines); - } - end.row+=newMiddleLines-oldMiddleLines; - - lines[start.row].Modify(start.column, lines[start.row].dataLength-start.column, inputs[0], inputCounts[0]); - lines[end.row].Modify(0, end.column, inputs[rows-1], inputCounts[rows-1]); - for(vint i=1;i inputs; - List inputCounts; - const wchar_t* previous=input; - const wchar_t* current=input; - - while(true) - { - if(current==input+inputCount) - { - inputs.Add(previous); - inputCounts.Add(current-previous); - break; - } - else if(*current==L'\r' || *current==L'\n') - { - inputs.Add(previous); - inputCounts.Add(current-previous); - previous=current+(current[1]==L'\n'?2:1); - current=previous; - } - else - { - current++; - } - } - - return Modify(start, end, &inputs[0], &inputCounts[0], inputs.Count()); - } - - TextPos TextLines::Modify(TextPos start, TextPos end, const wchar_t* input) - { - return Modify(start, end, input, wcslen(input)); - } - - TextPos TextLines::Modify(TextPos start, TextPos end, const WString& input) - { - return Modify(start, end, input.Buffer(), input.Length()); - } - - void TextLines::Clear() - { - RemoveLines(0, lines.Count()); - TextLine line; - line.Initialize(); - lines.Add(line); - if (ownerElement) - { - ownerElement->InvokeOnElementStateChanged(); - } - } - - //-------------------------------------------------------- - - void TextLines::ClearMeasurement() - { - for (vint i = 0; i < lines.Count(); i++) - { - lines[i].availableOffsetCount = 0; - } - - tabWidth = tabSpaceCount * (charMeasurer ? charMeasurer->MeasureWidth({ L' ' }) : 1); - if (tabWidth == 0) - { - tabWidth = 1; - } - - if (ownerElement) - { - ownerElement->InvokeOnElementStateChanged(); - } - } - - vint TextLines::GetTabSpaceCount() - { - return tabSpaceCount; - } - - void TextLines::SetTabSpaceCount(vint value) - { - if(value<1) value=1; - if(tabSpaceCount!=value) - { - tabSpaceCount=value; - ClearMeasurement(); - } - } - - void TextLines::MeasureRow(vint row) - { - TextLine& line = lines[row]; - vint offset = 0; - if (line.availableOffsetCount) - { - offset = line.att[line.availableOffsetCount - 1].rightOffset; - } - for (vint i = line.availableOffsetCount; i < line.dataLength; i++) - { - CharAtt& att = line.att[i]; - wchar_t c = line.text[i]; - vint width = 0; - vint passwordWidth = 0; - if (passwordChar) - { - passwordWidth = charMeasurer ? charMeasurer->MeasureWidth({ passwordChar }) : 1; - } - - if (c == L'\t') - { - width = tabWidth - offset % tabWidth; - } -#if defined VCZH_MSVC - else if (UTF16SPFirst(c) && (i + 1 < line.dataLength) && UTF16SPSecond(line.text[i + 1])) - { - width = passwordChar ? passwordWidth : (charMeasurer ? charMeasurer->MeasureWidth({ c, line.text[i + 1] }) : 1); - offset += width; - att.rightOffset = (int)offset; - line.att[i + 1].rightOffset = (int)offset; - i++; - continue; - } -#endif - else - { - width = passwordChar ? passwordWidth : (charMeasurer ? charMeasurer->MeasureWidth({ c }) : 1); - } - offset += width; - att.rightOffset = (int)offset; - } - line.availableOffsetCount = line.dataLength; - } - - vint TextLines::GetRowWidth(vint row) - { - if(row<0 || row>=lines.Count()) return -1; - TextLine& line=lines[row]; - if(line.dataLength==0) - { - return 0; - } - else - { - MeasureRow(row); - return line.att[line.dataLength-1].rightOffset; - } - } - - vint TextLines::GetRowHeight() - { - return charMeasurer ? charMeasurer->GetRowHeight() : 1; - } - - vint TextLines::GetMaxWidth() - { - vint width=0; - for(vint i=0;i=h*lines.Count()) - { - point.y=h*lines.Count()-1; - } - - vint row=point.y/h; - if(point.x<0) - { - return TextPos(row, 0); - } - else if(point.x>=GetRowWidth(row)) - { - return TextPos(row, lines[row].dataLength); - } - TextLine& line=lines[row]; - - vint i1=0, i2=line.dataLength; - vint p1=0, p2=line.att[line.dataLength-1].rightOffset; - while(i2-i1>1) - { - vint i=(i1+i2)/2; - vint p=i==0?0:line.att[i-1].rightOffset; - if(point.x 0 && UTF16SPFirst(line.text[i1 - 1])) - { - i1--; - } -#endif - return TextPos(row, i1); - } - - Point TextLines::GetPointFromTextPos(TextPos pos) - { - if(IsAvailable(pos)) - { - vint y = pos.row * GetRowHeight(); - if(pos.column==0) - { - return Point(0, y); - } - else - { - MeasureRow(pos.row); - TextLine& line=lines[pos.row]; - return Point(line.att[pos.column-1].rightOffset, y); - } - } - else - { - return Point(-1, -1); - } - } - - Rect TextLines::GetRectFromTextPos(TextPos pos) - { - Point point=GetPointFromTextPos(pos); - if(point==Point(-1, -1)) - { - return Rect(-1, -1, -1, -1); - } - else - { - vint h = GetRowHeight(); - TextLine& line=lines[pos.row]; - if(pos.column==line.dataLength) - { - return Rect(point, Size(h/2, h)); - } - else - { - return Rect(point, Size(line.att[pos.column].rightOffset-point.x, h)); - } - } - } - - //-------------------------------------------------------- - - wchar_t TextLines::GetPasswordChar() - { - return passwordChar; - } - - void TextLines::SetPasswordChar(wchar_t value) - { - passwordChar=value; - ClearMeasurement(); - } - } - - using namespace text; - -/*********************************************************************** -GuiColorizedTextElement -***********************************************************************/ - - GuiColorizedTextElement::GuiColorizedTextElement() - :callback(0) - ,isVisuallyEnabled(true) - ,isFocused(false) - ,caretVisible(false) - ,lines(this) - { - } - - text::TextLines& GuiColorizedTextElement::GetLines() - { - return lines; - } - - GuiColorizedTextElement::ICallback* GuiColorizedTextElement::GetCallback() - { - return callback; - } - - void GuiColorizedTextElement::SetCallback(ICallback* value) - { - callback=value; - if(!callback) - { - lines.SetCharMeasurer(0); - } - } - - const GuiColorizedTextElement::ColorArray& GuiColorizedTextElement::GetColors() - { - return colors; - } - - void GuiColorizedTextElement::SetColors(const ColorArray& value) - { - CopyFrom(colors, value); - if(callback) callback->ColorChanged(); - InvokeOnElementStateChanged(); - } - - void GuiColorizedTextElement::ResetTextColorIndex(vint index) - { - vint lineCount = lines.GetCount(); - for (vint i = 0; i < lineCount; i++) - { - auto& line = lines.GetLine(i); - line.lexerFinalState = -1; - line.contextFinalState = -1; - for (vint j = 0; j < line.dataLength; j++) - { - line.att[j].colorIndex = (vuint32_t)index; - } - } - } - - const FontProperties& GuiColorizedTextElement::GetFont() - { - return font; - } - - void GuiColorizedTextElement::SetFont(const FontProperties& value) - { - if(font!=value) - { - font=value; - if(callback) - { - callback->FontChanged(); - } - InvokeOnElementStateChanged(); - } - } - - wchar_t GuiColorizedTextElement::GetPasswordChar() - { - return lines.GetPasswordChar(); - } - - void GuiColorizedTextElement::SetPasswordChar(wchar_t value) - { - if(lines.GetPasswordChar()!=value) - { - lines.SetPasswordChar(value); - InvokeOnElementStateChanged(); - } - } - - Point GuiColorizedTextElement::GetViewPosition() - { - return viewPosition; - } - - void GuiColorizedTextElement::SetViewPosition(Point value) - { - if(viewPosition!=value) - { - viewPosition=value; - InvokeOnElementStateChanged(); - } - } - - bool GuiColorizedTextElement::GetVisuallyEnabled() - { - return isVisuallyEnabled; - } - - void GuiColorizedTextElement::SetVisuallyEnabled(bool value) - { - if(isVisuallyEnabled!=value) - { - isVisuallyEnabled=value; - InvokeOnElementStateChanged(); - } - } - - bool GuiColorizedTextElement::GetFocused() - { - return isFocused; - } - - void GuiColorizedTextElement::SetFocused(bool value) - { - if(isFocused!=value) - { - isFocused=value; - InvokeOnElementStateChanged(); - } - } - - TextPos GuiColorizedTextElement::GetCaretBegin() - { - return caretBegin; - } - - void GuiColorizedTextElement::SetCaretBegin(TextPos value) - { - caretBegin=value; - InvokeOnElementStateChanged(); - } - - TextPos GuiColorizedTextElement::GetCaretEnd() - { - return caretEnd; - } - - void GuiColorizedTextElement::SetCaretEnd(TextPos value) - { - caretEnd=value; - InvokeOnElementStateChanged(); - } - - bool GuiColorizedTextElement::GetCaretVisible() - { - return caretVisible; - } - - void GuiColorizedTextElement::SetCaretVisible(bool value) - { - caretVisible=value; - InvokeOnElementStateChanged(); - } - - Color GuiColorizedTextElement::GetCaretColor() - { - return caretColor; - } - - void GuiColorizedTextElement::SetCaretColor(Color value) - { - if(caretColor!=value) - { - caretColor=value; - InvokeOnElementStateChanged(); - } - } - } - } -} - - /*********************************************************************** .\NATIVEWINDOW\GUINATIVEWINDOW.CPP ***********************************************************************/ @@ -40010,8 +35327,7 @@ GuiRemoteGraphicsResourceManager elements_remoteprotocol::GuiSolidLabelElementRenderer::Register(); elements_remoteprotocol::GuiImageFrameElementRenderer::Register(); elements_remoteprotocol::GuiPolygonElementRenderer::Register(); - elements_remoteprotocol::GuiColorizedTextElementRenderer::Register(); - elements::GuiDocumentElement::GuiDocumentElementRenderer::Register(); + elements::GuiDocumentElementRenderer::Register(); } void GuiRemoteGraphicsResourceManager::Finalize() @@ -40632,55 +35948,6 @@ GuiPolygonElementRenderer CopyFrom(*arguments.points.Obj(), element->GetPointsArray()); renderTarget->GetRemoteMessages().RequestRendererUpdateElement_Polygon(arguments); } - -/*********************************************************************** -GuiColorizedTextElementRenderer -***********************************************************************/ - - void GuiColorizedTextElementRenderer::ColorChanged() - { - } - - void GuiColorizedTextElementRenderer::FontChanged() - { - } - - void GuiColorizedTextElementRenderer::InitializeInternal() - { - TBase::InitializeInternal(); - element->SetCallback(this); - } - - void GuiColorizedTextElementRenderer::FinalizeInternal() - { - element->SetCallback(nullptr); - TBase::FinalizeInternal(); - } - - GuiColorizedTextElementRenderer::GuiColorizedTextElementRenderer() - { - } - - void GuiColorizedTextElementRenderer::OnElementStateChanged() - { - TBase::OnElementStateChanged(); - } - - void GuiColorizedTextElementRenderer::SendUpdateElementMessages(bool fullContent) - { - // Lines - // Colors - // Font - // PasswordChar - // ViewPosition - // VisuallyEnabled - // Focused - // CaretBegin - // CaretEnd - // CaretVisible - // CaretColor - CHECK_FAIL(L"Not Implemented!"); - } } /*********************************************************************** @@ -56055,7 +51322,7 @@ Closures void __vwsnf35_GuiFakeDialogServiceUI_gaclib_controls_FilePickerControlConstructor___vwsn_gaclib_controls_FilePickerControl_Initialize_::operator()(::vl::presentation::compositions::GuiGraphicsComposition* sender, ::vl::presentation::compositions::GuiEventArgs* arguments) const { ::vl::__vwsn::This(__vwsnthis_0->textBox)->SetText(::vl::__vwsn::This(__vwsnthis_0->ViewModel.Obj())->GetDisplayString(::vl::__vwsn::This(__vwsnthis_0->self)->GetSelectedFiles())); - ::vl::__vwsn::This(__vwsnthis_0->textBox)->Select([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); + ::vl::__vwsn::This(__vwsnthis_0->textBox)->SetCaret([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); } //------------------------------------------------------------------- @@ -62547,7 +57814,7 @@ Class (::gaclib_controls::FontNameControlConstructor) ::vl::__vwsn::This(this->self)->AddChild(this->__vwsn_precompile_0); } { - ::vl::__vwsn::This(this->textBox)->SetReadonly(::vl::__vwsn::This(this->ViewModel.Obj())->GetFontMustExist()); + ::vl::__vwsn::This(this->textBox)->SetEditMode((::vl::__vwsn::This(this->ViewModel.Obj())->GetFontMustExist() ? ::vl::presentation::controls::GuiDocumentEditMode::Selectable : ::vl::presentation::controls::GuiDocumentEditMode::Editable)); } { ::vl::__vwsn::This(this->textList)->SetItemSource(::vl::Ptr<::vl::reflection::description::IValueEnumerable>(::vl::__vwsn::UnboxCollection<::vl::reflection::description::IValueReadonlyList>(::vl::__vwsn::This(this->ViewModel.Obj())->GetFontList()))); @@ -62643,7 +57910,7 @@ Class (::gaclib_controls::FontNameControl) void FontNameControl::InitValue(const ::vl::WString& value) { ::vl::__vwsn::This(this->textBox)->SetText(value); - ::vl::__vwsn::This(this->textBox)->Select([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); + ::vl::__vwsn::This(this->textBox)->SetCaret([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); this->UpdateSelectedIndex(); } @@ -62873,7 +58140,7 @@ Class (::gaclib_controls::FontSizeControl) void FontSizeControl::InitValue(::vl::vint value) { ::vl::__vwsn::This(this->textBox)->SetText(::vl::__vwsn::ToString(value)); - ::vl::__vwsn::This(this->textBox)->Select([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); + ::vl::__vwsn::This(this->textBox)->SetCaret([&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }(), [&](){ ::vl::presentation::TextPos __vwsn_temp__; __vwsn_temp__.row = static_cast<::vl::vint>(0); __vwsn_temp__.column = static_cast<::vl::vint>(0); return __vwsn_temp__; }()); this->UpdateSelectedIndex(); } diff --git a/Import/GacUI.h b/Import/GacUI.h index a33c77d5..5852fa42 100644 --- a/Import/GacUI.h +++ b/Import/GacUI.h @@ -8,7 +8,6 @@ DEVELOPER: Zihan Chen(vczh) #include "VlppOS.h" #include "Vlpp.h" #include "VlppRegex.h" -#include "VlppParser.h" /*********************************************************************** .\GUITYPES.H @@ -1525,6 +1524,107 @@ MemoryNodeRootProvider #endif +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTCONFIG.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTCONFIG +#define VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTCONFIG + + +namespace vl +{ + namespace presentation + { + namespace controls + { + +/*********************************************************************** +GuiDocumentConfig +***********************************************************************/ + + /// Represents the edit mode. + enum class GuiDocumentEditMode + { + /// View the rich text only. + ViewOnly, + /// The rich text is selectable. + Selectable, + /// The rich text is editable. + Editable, + }; + + /// Represents the paragraph mode. + enum class GuiDocumentParagraphMode + { + /// Only one paragraph is allowed, only one line in a paragraph is allowed. + Singleline, + /// Only one line in a paragraph is allowed. + Multiline, + /// No constraint. + Paragraph, + }; + + /// Control of editing and rendering behavior. + struct GuiDocumentConfig + { + /// For GuiDocumentLabel only. When it is true, or when wrapLine is true, or when paragraphMode is not Singleline, the control automatically expands to display all content. + Nullable autoExpand; + /// When it is true, the defaut copy paste behavior ignores RTF format. + Nullable pasteAsPlainText; + /// When it is true, document automatically wraps if the width of the control is not enough. + Nullable wrapLine; + /// Control the paragraph and line behavior + Nullable paragraphMode; + /// Insert the space of a default font between paragraphs. + Nullable paragraphPadding; + /// When it is true: + /// double CrLf will be used between paragraphs, when the document converts to plain text. + /// only double CrLf will be recognized as paragraph breaks, when the document converts from plain text. + /// + Nullable doubleLineBreaksBetweenParagraph; + /// When it is true, when removing a line break from a document due to paragraphMode, insert a extra space. + Nullable spaceForFlattenedLineBreak; + + auto operator<=>(const GuiDocumentConfig&) const = default; + + static GuiDocumentConfig GetDocumentLabelDefaultConfig(); + static GuiDocumentConfig GetDocumentViewerDefaultConfig(); + static GuiDocumentConfig GetSinglelineTextBoxDefaultConfig(); + static GuiDocumentConfig GetMultilineTextBoxDefaultConfig(); + static GuiDocumentConfig OverrideConfig(const GuiDocumentConfig& toOverride, const GuiDocumentConfig& newConfig); + }; + +/*********************************************************************** +GuiDocumentConfigEvaluated +***********************************************************************/ + + struct GuiDocumentConfigEvaluated + { + bool autoExpand; + bool pasteAsPlainText; + bool wrapLine; + GuiDocumentParagraphMode paragraphMode; + bool paragraphPadding; + bool doubleLineBreaksBetweenParagraph; + bool spaceForFlattenedLineBreak; + + GuiDocumentConfigEvaluated(const GuiDocumentConfig& config); + }; + } + } +} + +#endif + + /*********************************************************************** .\GRAPHICSCOMPOSITION\GUIGRAPHICSAXIS.H ***********************************************************************/ @@ -9909,11 +10009,11 @@ Theme Names F(ControlTemplate, GroupBox) \ F(TabTemplate, Tab) \ F(ComboBoxTemplate, ComboBox) \ - F(MultilineTextBoxTemplate, MultilineTextBox) \ - F(SinglelineTextBoxTemplate, SinglelineTextBox) \ F(DocumentViewerTemplate, DocumentViewer) \ + F(DocumentViewerTemplate, MultilineTextBox) \ F(DocumentLabelTemplate, DocumentLabel) \ F(DocumentLabelTemplate, DocumentTextBox) \ + F(DocumentLabelTemplate, SinglelineTextBox) \ F(ListViewTemplate, ListView) \ F(TreeViewTemplate, TreeView) \ F(TextListTemplate, TextList) \ @@ -12823,970 +12923,6 @@ Elements #endif -/*********************************************************************** -.\GRAPHICSELEMENT\GUIGRAPHICSDOCUMENTELEMENT.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Element System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTELEMENT -#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTELEMENT - - -namespace vl -{ - namespace presentation - { - namespace elements - { - - namespace visitors - { - class SetPropertiesVisitor; - } - -/*********************************************************************** -Rich Content Document (element) -***********************************************************************/ - - /// Defines a rich text document element for rendering complex styled document. - class GuiDocumentElement : public GuiElementBase - { - friend class GuiElementBase; - static constexpr const wchar_t* ElementTypeName = L"RichDocument"; - public: - /// Callback interface for this element. - class ICallback : public virtual IDescriptable, public Description - { - public: - /// Called when the rendering is started. - virtual void OnStartRender() = 0; - - /// Called when the rendering is finished. - virtual void OnFinishRender() = 0; - - /// Called when an embedded object is being rendered. - /// Returns the new size of the rendered embedded object. - /// The name of the embedded object - /// The location of the embedded object, relative to the left-top corner of this element. - virtual Size OnRenderEmbeddedObject(const WString& name, const Rect& location) = 0; - }; - - class GuiDocumentElementRenderer : public GuiElementRendererBase, private IGuiGraphicsParagraphCallback - { - friend class visitors::SetPropertiesVisitor; - friend class GuiElementRendererBase; - protected: - struct EmbeddedObject - { - WString name; - Size size; - vint start; - bool resized = false; - }; - - typedef collections::Dictionary> IdEmbeddedObjectMap; - typedef collections::Dictionary NameIdMap; - typedef collections::List FreeIdList; - - struct ParagraphCache - { - WString fullText; - Ptr graphicsParagraph; - IdEmbeddedObjectMap embeddedObjects; - vint selectionBegin; - vint selectionEnd; - - ParagraphCache() - :selectionBegin(-1) - ,selectionEnd(-1) - { - } - }; - - typedef collections::Array> ParagraphCacheArray; - typedef collections::Array ParagraphSizeArray; - - private: - - Size OnRenderInlineObject(vint callbackId, Rect location)override; - protected: - vint paragraphDistance; - vint lastMaxWidth; - Size cachedTotalSize; - IGuiGraphicsLayoutProvider* layoutProvider; - ParagraphCacheArray paragraphCaches; - ParagraphSizeArray paragraphSizes; - - TextPos lastCaret; - Color lastCaretColor; - bool lastCaretFrontSide; - - NameIdMap nameCallbackIdMap; - FreeIdList freeCallbackIds; - vint usedCallbackIds = 0; - - vint renderingParagraph = -1; - Point renderingParagraphOffset; - - void InitializeInternal(); - void FinalizeInternal(); - void RenderTargetChangedInternal(IGuiGraphicsRenderTarget* oldRenderTarget, IGuiGraphicsRenderTarget* newRenderTarget); - Ptr EnsureAndGetCache(vint paragraphIndex, bool createParagraph); - bool GetParagraphIndexFromPoint(Point point, vint& top, vint& index); - public: - GuiDocumentElementRenderer(); - - void Render(Rect bounds)override; - void OnElementStateChanged()override; - void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); - Ptr GetHyperlinkFromPoint(Point point); - - void OpenCaret(TextPos caret, Color color, bool frontSide); - void CloseCaret(TextPos caret); - void SetSelection(TextPos begin, TextPos end); - TextPos CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide); - TextPos CalculateCaretFromPoint(Point point); - Rect GetCaretBounds(TextPos caret, bool frontSide); - }; - - protected: - Ptr document; - ICallback* callback = nullptr; - bool paragraphPadding = true; - bool wrapLine = true; - TextPos caretBegin; - TextPos caretEnd; - bool caretVisible; - bool caretFrontSide; - Color caretColor; - - void UpdateCaret(); - - GuiDocumentElement(); - public: - /// Get the callback. - /// The callback. - ICallback* GetCallback(); - /// Set the callback. - /// The callback. - void SetCallback(ICallback* value); - - /// Get the document. - /// The document. - Ptr GetDocument(); - /// Set the document. When a document is set to this element, modifying the document without invoking will lead to undefined behavior. - /// The document. - void SetDocument(Ptr value); - /// Get whether paddings are inserted between paragraphs. - /// Returns true if paddings are inserted between paragraphs. - bool GetParagraphPadding(); - /// Set whether paddings are inserted between paragraphs - /// Set to true so that paddings are inserted between paragraphs. - void SetParagraphPadding(bool value); - /// Get line wrapping. - /// Return true if there is automatic line wrapping. - bool GetWrapLine(); - /// Set line wrapping. - /// Set to true so that there is automatic line wrapping. - void SetWrapLine(bool value); - - /// - /// Get the begin position of the selection area. - /// - /// The begin position of the selection area. - TextPos GetCaretBegin(); - /// - /// Get the end position of the selection area. - /// - /// The end position of the selection area. - TextPos GetCaretEnd(); - /// - /// Get the prefer side for the caret. - /// - /// Returns true if the caret is rendered for the front side. - bool IsCaretEndPreferFrontSide(); - /// - /// Set the end position of the selection area. - /// - /// The begin position of the selection area. - /// The end position of the selection area. - /// Set to true to show the caret for the character before it. This argument is ignored if begin and end are the same. - void SetCaret(TextPos begin, TextPos end, bool frontSide); - /// - /// Get the caret visibility. - /// - /// Returns true if the caret will be rendered. - bool GetCaretVisible(); - /// - /// Set the caret visibility. - /// - /// True if the caret will be rendered. - void SetCaretVisible(bool value); - /// - /// Get the color of the caret. - /// - /// The color of the caret. - Color GetCaretColor(); - /// - /// Set the color of the caret. - /// - /// The color of the caret. - void SetCaretColor(Color value); - - /// Calculate a caret using a specified comparing caret and a relative position. - /// The calculated caret. - /// The comparing caret. - /// The relative position. - /// Specify the side for the comparingCaret. Retrive the suggested side for the new caret. If the return caret equals compareCaret, this output is ignored. - TextPos CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide); - /// Calculate a caret using a specified point. - /// The calculated caret. - /// The specified point. - TextPos CalculateCaretFromPoint(Point point); - /// Get the bounds of a caret. - /// The bounds. - /// The caret. - /// Set to true to get the bounds for the character before it. - Rect GetCaretBounds(TextPos caret, bool frontSide); - - /// Notify that some paragraphs are updated. - /// The start paragraph index. - /// The number of paragraphs to be updated. - /// The number of updated paragraphs. - /// Set to true to notify that the text is updated. - void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); - /// Edit run in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new run. - /// Set to true to copy the model before editing. Otherwise, objects inside the model will be used directly - void EditRun(TextPos begin, TextPos end, Ptr model, bool copy); - /// Edit text in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// Set to true to use the text style in front of the specified range. - /// The new text. - void EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text); - /// Edit style in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new style. - void EditStyle(TextPos begin, TextPos end, Ptr style); - /// Edit image in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new image. - void EditImage(TextPos begin, TextPos end, Ptr image); - /// Set hyperlink in a specified range. - /// The index of the paragraph to edit. - /// The begin position of the range. - /// The end position of the range. - /// The reference of the hyperlink. - /// The normal style name of the hyperlink. - /// The active style name of the hyperlink. - void EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName=DocumentModel::NormalLinkStyleName, const WString& activeStyleName=DocumentModel::ActiveLinkStyleName); - /// Remove hyperlink in a specified range. - /// The index of the paragraph to edit. - /// The begin position of the range. - /// The end position of the range. - void RemoveHyperlink(vint paragraphIndex, vint begin, vint end); - /// Edit style name in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new style name. - void EditStyleName(TextPos begin, TextPos end, const WString& styleName); - /// Remove style name in a specified range. - /// The begin position of the range. - /// The end position of the range. - void RemoveStyleName(TextPos begin, TextPos end); - /// Rename a style. - /// The name of the style. - /// The new name. - void RenameStyle(const WString& oldStyleName, const WString& newStyleName); - /// Clear all styles in a specified range. - /// The begin position of the range. - /// The end position of the range. - void ClearStyle(TextPos begin, TextPos end); - /// Clear all styles and remove non-text contents in a specified range. - /// The begin position of the range. - /// The end position of the range. - void ConvertToPlainText(TextPos begin, TextPos end); - /// Summarize the text style in a specified range. - /// The text style summary. - /// The begin position of the range. - /// The end position of the range. - Ptr SummarizeStyle(TextPos begin, TextPos end); - /// Summarize the style name in a specified range. - /// The style name summary. - /// The begin position of the range. - /// The end position of the range. - Nullable SummarizeStyleName(TextPos begin, TextPos end); - /// Set the alignment of paragraphs in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The alignment for each paragraph. - void SetParagraphAlignment(TextPos begin, TextPos end, const collections::Array>& alignments); - /// Summarize the text alignment in a specified range. - /// The text alignment summary. - /// The begin position of the range. - /// The end position of the range. - Nullable SummarizeParagraphAlignment(TextPos begin, TextPos end); - - /// Get hyperlink from point. - /// Corressponding hyperlink id. Returns -1 indicates that the point is not in a hyperlink. - /// The point to get the hyperlink id. - Ptr GetHyperlinkFromPoint(Point point); - }; - } - } -} - -#endif - -/*********************************************************************** -.\GRAPHICSELEMENT\GUIGRAPHICSTEXTELEMENT.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Element System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTELEMENT -#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSTEXTELEMENT - - -namespace vl -{ - namespace presentation - { - namespace elements - { - class GuiColorizedTextElement; - -/*********************************************************************** -Colorized Plain Text (model) -***********************************************************************/ - - namespace text - { - /// - /// Represents the extra information of a character to display. - /// - struct CharAtt - { - /// - /// The distance from the head of the line to the right side of this character in pixel. - /// - vuint32_t rightOffset; - /// - /// The color index of the character. Use [M:vl.presentation.elements.GuiColorizedTextElement.GetColors] and [M:vl.presentation.elements.GuiColorizedTextElement.SetColors] to access the color table. - /// - vuint32_t colorIndex; - }; - - /// - /// Represents a line of characters. - /// - struct TextLine - { - static const vint BlockSize=32; - static const vint MaxWidth=0xFFFF; - - /// - /// A character buffer starts from the first character of this line. - /// - wchar_t* text; - /// - /// A extra information buffer starts from the first character of this line. - /// - CharAtt* att; - /// - /// The number of available in the buffer. - /// - vint availableOffsetCount; - /// - /// The number of elements in the allocated buffer memory. - /// - vint bufferLength; - /// - /// The number of available characters in the buffer. - /// - vint dataLength; - /// - /// The internal lexical analyzer state of a colorizer when it parses to the end of this line. -1 means that this state is not available. - /// - vint lexerFinalState; - /// - /// The internal context sensitive state of a colorizer when it parses to the end of this line. -1 means that this state is not available. - /// - vint contextFinalState; - - TextLine(); - ~TextLine(); - - static vint CalculateBufferLength(vint dataLength); - - std::partial_ordering operator<=>(const TextLine&) const { return std::partial_ordering::unordered; } - bool operator==(const TextLine& value) const { return false; } - - /// - /// Initialize the instance to be an empty line. - /// - void Initialize(); - /// - /// Release all resources used in this line. - /// - void Finalize(); - /// - /// Test is the line initialized. - /// - /// Returns true if the line is initialized. - bool IsReady(); - /// - /// Modify the characters in the line by replacing characters. - /// - /// Returns true if the modification succeeded. - /// The position of the first character to be replaced. - /// The number of characters to be replaced. - /// The buffer to the characters to write into this line. - /// The numbers of the characters to write into this line. - bool Modify(vint start, vint count, const wchar_t* input, vint inputCount); - /// - /// Split a text line into two by the position. The current line contains characters before this position. This function returns a new text line contains characters after this position. - /// - /// The new text line. - /// . - TextLine Split(vint index); - /// - /// Append a text line after the this text line, and finalize the input text line. - /// - /// The text line that contains all characters and color indices to append and be finalized. - void AppendAndFinalize(TextLine& line); - }; - -#if defined VCZH_MSVC - /// Test if a wchar_t is the first character of a surrogate pair. - /// The character to test. - /// Returns true if it is the first character of a surrogate pair. - inline bool UTF16SPFirst(wchar_t c) - { - return 0xD800 <= c && c < 0xDC00; - } - - /// Test if a wchar_t is the second character of a surrogate pair. - /// The character to test. - /// Returns true if it is the second character of a surrogate pair. - inline bool UTF16SPSecond(wchar_t c) - { - return 0xDC00 <= c && c < 0xDFFF; - } -#endif - - /// - /// A unicode code point. - /// In Windows, when the first character is not the leading character of a surrogate pair, the second character is ignored. - /// In other platforms which treat wchar_t as a UTF-32 character, the second character is ignored. - /// - struct UnicodeCodePoint - { -#if defined VCZH_MSVC - wchar_t characters[2]; - - UnicodeCodePoint(wchar_t c) :characters{ c,0 } {} - UnicodeCodePoint(wchar_t c1, wchar_t c2) :characters{ c1,c2 } {} -#elif defined VCZH_GCC - wchar_t character; - - UnicodeCodePoint(wchar_t c) :character(c) {} -#endif - - vuint32_t GetCodePoint()const - { -#if defined VCZH_MSVC - if (UTF16SPFirst(characters[0]) && UTF16SPSecond(characters[1])) - { - return (wchar_t)(characters[0] - 0xD800) * 0x400 + (wchar_t)(characters[1] - 0xDC00) + 0x10000; - } - else - { - return (vuint32_t)characters[0]; - } -#elif defined VCZH_GCC - return (vuint32_t)character; -#endif - } - }; - - /// - /// An abstract class for character size measuring in differect rendering technology. - /// - class CharMeasurer : public virtual IDescriptable - { - protected: - IGuiGraphicsRenderTarget* oldRenderTarget = nullptr; - vint rowHeight; - vint widths[65536]; - - /// - /// Measure the width of a character. - /// - /// The width in pixel. - /// The unicode code point to measure. - /// The render target which the character is going to be rendered. This is a pure virtual member function to be overrided. - virtual vint MeasureWidthInternal(UnicodeCodePoint codePoint, IGuiGraphicsRenderTarget* renderTarget)=0; - /// - /// Measure the height of a character. - /// - /// The height in pixel. - /// The render target which the character is going to be rendered. - virtual vint GetRowHeightInternal(IGuiGraphicsRenderTarget* renderTarget)=0; - public: - - /// - /// Initialize a character measurer. - /// - /// The default character height in pixel before the character measurer is binded to a render target. - CharMeasurer(vint _rowHeight); - ~CharMeasurer(); - - /// - /// Bind a render target to this character measurer. - /// - /// The render target to bind. - void SetRenderTarget(IGuiGraphicsRenderTarget* value); - /// - /// Measure the width of a character using the binded render target. - /// - /// The width of a character, in pixel. - /// The unicode code point to measure. - vint MeasureWidth(UnicodeCodePoint codePoint); - /// - /// Measure the height of a character. - /// - /// The height of a character, in pixel. - vint GetRowHeight(); - }; - - /// - /// A class to maintain multiple lines of text buffer. - /// - class TextLines : public Object, public Description - { - typedef collections::List TextLineList; - protected: - GuiColorizedTextElement* ownerElement; - TextLineList lines; - CharMeasurer* charMeasurer; - IGuiGraphicsRenderTarget* renderTarget; - vint tabWidth; - vint tabSpaceCount; - wchar_t passwordChar; - public: - TextLines(GuiColorizedTextElement* _ownerElement); - ~TextLines(); - - /// - /// Returns the number of text lines. - /// - /// The number of text lines. - vint GetCount(); - /// - /// Returns the text line of a specified row number. - /// - /// The related text line object. - /// The specified row number. - TextLine& GetLine(vint row); - /// - /// Returns the binded . - /// - /// The binded . - CharMeasurer* GetCharMeasurer(); - /// - /// Binded a . - /// - /// The to bind. - void SetCharMeasurer(CharMeasurer* value); - /// - /// Returns the binded . - /// - /// The binded . - IGuiGraphicsRenderTarget* GetRenderTarget(); - /// - /// Binded a . - /// - /// The to bind. - void SetRenderTarget(IGuiGraphicsRenderTarget* value); - /// - /// Returns a string from a specified range of the text lines. - /// - /// The string. - /// The start position. - /// The end position. - WString GetText(TextPos start, TextPos end); - /// - /// Returns the whole string in the text lines. - /// - /// The string. - WString GetText(); - /// - /// Set the string to the text lines. This operation will modified every objects. - /// - /// The string to set into the text lines. - void SetText(const WString& value); - - /// - /// Remove text lines in a specified range. - /// - /// Returns true if this operation succeeded. - /// The first row number. - /// The number of text lines to be removed. - bool RemoveLines(vint start, vint count); - /// - /// Test is a text position available in the text lines. - /// - /// Returns true if this position is available. - /// The text position to test. - bool IsAvailable(TextPos pos); - /// - /// Normalize a text position to be available. - /// - /// The normalized text position. - /// The text position to normalize. - TextPos Normalize(TextPos pos); - /// - /// Modify some text lines by replacing characters. - /// - /// The new end position. - /// The start position of the range of characters to be replaced. - /// The end position of the range of characters to be replaced. - /// The buffer to the string buffers to replace into the text lines. - /// The numbers of characters for each string buffer. - /// The number of string buffers. - TextPos Modify(TextPos start, TextPos end, const wchar_t** inputs, vint* inputCounts, vint rows); - /// - /// Modify some text lines by replacing characters. - /// - /// The new end position. - /// The start position of the range of characters to be replaced. - /// The end position of the range of characters to be replaced. - /// The buffer to the string to replace into the text lines. - /// The number of characters to replace into the text lines. - TextPos Modify(TextPos start, TextPos end, const wchar_t* input, vint inputCount); - /// - /// Modify some text lines by replacing characters. - /// - /// The new end position. - /// The start position of the range of characters to be replaced. - /// The end position of the range of characters to be replaced. - /// The string to replace into the text lines. - TextPos Modify(TextPos start, TextPos end, const wchar_t* input); - /// - /// Modify some text lines by replacing characters. - /// - /// The new end position. - /// The start position of the range of characters to be replaced. - /// The end position of the range of characters to be replaced. - /// The string to replace into the text lines. - TextPos Modify(TextPos start, TextPos end, const WString& input); - /// - /// Remove every text lines. - /// - void Clear(); - - /// - /// Clear all cached . - /// - void ClearMeasurement(); - /// - /// Returns the number of spaces to replace a tab character for rendering. - /// - /// The number of spaces to replace a tab character for rendering. - vint GetTabSpaceCount(); - /// - /// Set the number of spaces to replace a tab character for rendering. - /// - /// The number of spaces to replace a tab character for rendering. - void SetTabSpaceCount(vint value); - /// - /// Measure all characters in a specified row. - /// - /// The specified row number. - void MeasureRow(vint row); - /// - /// Returns the width of a specified row. - /// - /// The width of a specified row, in pixel. - /// The specified row number. - vint GetRowWidth(vint row); - /// - /// Returns the height of a row. - /// - /// The height of a row, in pixel. - vint GetRowHeight(); - /// - /// Returns the total width of the text lines. - /// - /// The width of the text lines, in pixel. - vint GetMaxWidth(); - /// - /// Returns the total height of the text lines. - /// - /// The height of the text lines, in pixel. - vint GetMaxHeight(); - /// - /// Get the text position near to specified point. - /// - /// The text position. - /// The specified point, in pixel. - TextPos GetTextPosFromPoint(Point point); - /// - /// Get the point of a specified text position. - /// - /// The point, in pixel. Returns (-1, -1) if the text position is not available. - /// The specified text position. - Point GetPointFromTextPos(TextPos pos); - /// - /// Get the bounds of a specified text position. - /// - /// The bounds, in pixel. Returns (-1, -1, -1, -1) if the text position is not available. - /// The specified text position. - Rect GetRectFromTextPos(TextPos pos); - /// - /// Get the password mode displaying character. - /// - /// The password mode displaying character. Returns L'\0' means the password mode is not activated. - wchar_t GetPasswordChar(); - /// - /// Set the password mode displaying character. - /// - /// The password mode displaying character. Set to L'\0' to deactivate the password mode. - void SetPasswordChar(wchar_t value); - }; - - /// - /// Represents colors of a character. - /// - struct ColorItem - { - /// - /// Text color. - /// - Color text; - /// - /// Background color. - /// - Color background; - - GUI_DEFINE_COMPARE_OPERATORS(ColorItem) - }; - - /// - /// Represents color entry in a color table. Use [M:vl.presentation.elements.GuiColorizedTextElement.GetColors] and [M:vl.presentation.elements.GuiColorizedTextElement.SetColors] to access the color table. - /// - struct ColorEntry - { - /// - /// Colors in normal state. - /// - ColorItem normal; - /// - /// Colors in focused and selected state. - /// - ColorItem selectedFocused; - /// - /// Colors in not focused and selected state. - /// - ColorItem selectedUnfocused; - - GUI_DEFINE_COMPARE_OPERATORS(ColorEntry) - }; - } - -/*********************************************************************** -Colorized Plain Text (element) -***********************************************************************/ - - /// - /// Defines a text element with separate color configuration for each character. - /// - class GuiColorizedTextElement : public GuiElementBase - { - friend class GuiElementBase; - friend class text::TextLines; - - typedef collections::Array ColorArray; - static constexpr const wchar_t* ElementTypeName = L"ColorizedText"; - public: - /// - /// An callback interface. Member functions will be called when colors or fonts of a changed. - /// - class ICallback : public virtual IDescriptable, public Description - { - public: - /// - /// Called when the color table of a changed. - /// - virtual void ColorChanged()=0; - /// - /// Called when the font configuration of a changed. - /// - virtual void FontChanged()=0; - }; - protected: - ICallback* callback; - ColorArray colors; - FontProperties font; - Point viewPosition; - bool isVisuallyEnabled; - bool isFocused; - - TextPos caretBegin; - TextPos caretEnd; - bool caretVisible; - Color caretColor; - - text::TextLines lines; - - GuiColorizedTextElement(); - public: - /// - /// Get the internal object that stores all characters and colors. - /// - /// The internal object. - text::TextLines& GetLines(); - /// - /// Get the binded callback object. - /// - /// The binded callback object. - ICallback* GetCallback(); - /// - /// Bind a callback object. - /// - /// The callback object to bind. - void SetCallback(ICallback* value); - - /// - /// Get the binded color table. Use to use colors in this color table. - /// - /// The binded color table. - const ColorArray& GetColors(); - /// - /// Bind a color table. Use to use colors in this color table. will be called. - /// - /// The color table to bind. - void SetColors(const ColorArray& value); - /// - /// Reset color of all characters - /// - /// Color index of all characters. - void ResetTextColorIndex(vint index); - /// - /// Get the font configuration for all characters. - /// - /// The font configuration. - const FontProperties& GetFont(); - /// - /// Set the font configuration for all characters. will be called. - /// - /// The font configuration. - void SetFont(const FontProperties& value); - /// - /// Get the password mode displaying character. - /// - /// The password mode displaying character. Returns L'\0' means the password mode is not activated. - wchar_t GetPasswordChar(); - /// - /// Set the password mode displaying character. - /// - /// The password mode displaying character. Set to L'\0' to deactivate the password mode. - void SetPasswordChar(wchar_t value); - /// - /// Get the left-top position of the visible bounds of characters. - /// - /// The left-top position of the visible bounds of characters. - Point GetViewPosition(); - /// - /// Set the left-top position of the visible bounds of characters. - /// - /// The left-top position of the visible bounds of characters. - void SetViewPosition(Point value); - /// - /// Get the enabling state. - /// - /// Returns true if the element will be rendered as an enabled element. - bool GetVisuallyEnabled(); - /// - /// Set the enabling state. - /// - /// True if the element will be rendered as an enabled element. - void SetVisuallyEnabled(bool value); - /// - /// Get the focused state. - /// - /// Returns true if the element will be rendered as a focused element. - bool GetFocused(); - /// - /// Set the focused state. - /// - /// True if the element will be rendered as a focused element. - void SetFocused(bool value); - - /// - /// Get the begin position of the selection area. - /// - /// The begin position of the selection area. - TextPos GetCaretBegin(); - /// - /// Set the begin position of the selection area. - /// - /// The begin position of the selection area. - void SetCaretBegin(TextPos value); - /// - /// Get the end position of the selection area. - /// - /// The end position of the selection area. - TextPos GetCaretEnd(); - /// - /// Set the end position of the selection area. - /// - /// The end position of the selection area. - void SetCaretEnd(TextPos value); - /// - /// Get the caret visibility. - /// - /// Returns true if the caret will be rendered. - bool GetCaretVisible(); - /// - /// Set the caret visibility. - /// - /// True if the caret will be rendered. - void SetCaretVisible(bool value); - /// - /// Get the color of the caret. - /// - /// The color of the caret. - Color GetCaretColor(); - /// - /// Set the color of the caret. - /// - /// The color of the caret. - void SetCaretColor(Color value); - }; - } - } -} - -#endif - /*********************************************************************** .\CONTROLS\TEMPLATES\GUICONTROLTEMPLATES.H ***********************************************************************/ @@ -13943,7 +13079,6 @@ Templates { #define GUI_CONTROL_TEMPLATE_DECL(F)\ - F(GuiSinglelineTextBoxTemplate, GuiControlTemplate) \ F(GuiDocumentLabelTemplate, GuiControlTemplate) \ F(GuiMenuTemplate, GuiWindowTemplate) \ F(GuiButtonTemplate, GuiControlTemplate) \ @@ -13953,7 +13088,6 @@ Templates F(GuiComboBoxTemplate, GuiToolstripButtonTemplate) \ F(GuiScrollTemplate, GuiControlTemplate) \ F(GuiScrollViewTemplate, GuiControlTemplate) \ - F(GuiMultilineTextBoxTemplate, GuiScrollViewTemplate) \ F(GuiDocumentViewerTemplate, GuiScrollViewTemplate) \ F(GuiListControlTemplate, GuiScrollViewTemplate) \ F(GuiTextListTemplate, GuiListControlTemplate) \ @@ -13984,10 +13118,6 @@ Templates Control Template ***********************************************************************/ -#define GuiSinglelineTextBoxTemplate_PROPERTIES(F)\ - F(GuiSinglelineTextBoxTemplate, elements::text::ColorEntry, TextColor, {})\ - F(GuiSinglelineTextBoxTemplate, Color, CaretColor, {})\ - #define GuiDocumentLabelTemplate_PROPERTIES(F)\ F(GuiDocumentLabelTemplate, Ptr, BaselineDocument, {})\ F(GuiDocumentLabelTemplate, Color, CaretColor, {})\ @@ -14025,11 +13155,6 @@ Control Template F(GuiScrollViewTemplate, controls::GuiScroll*, HorizontalScroll, nullptr)\ F(GuiScrollViewTemplate, controls::GuiScroll*, VerticalScroll, nullptr)\ -#define GuiMultilineTextBoxTemplate_PROPERTIES(F)\ - F(GuiMultilineTextBoxTemplate, controls::ITextBoxCommandExecutor*, Commands, nullptr)\ - F(GuiMultilineTextBoxTemplate, elements::text::ColorEntry, TextColor, {})\ - F(GuiMultilineTextBoxTemplate, Color, CaretColor, {})\ - #define GuiDocumentViewerTemplate_PROPERTIES(F)\ F(GuiDocumentViewerTemplate, Ptr, BaselineDocument, {})\ F(GuiDocumentViewerTemplate, Color, CaretColor, {})\ @@ -16077,2076 +15202,6 @@ namespace vl #endif -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTGENERALOPERATIONS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTGENERALOPERATIONS -#define VCZH_PRESENTATION_CONTROLS_GUITEXTGENERALOPERATIONS - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -Common Operations -***********************************************************************/ - - /// An text edit callback for text box controls. - class ICommonTextEditCallback : public virtual IDescriptable, public Description - { - public: - /// Callback data for text editing preview. - struct TextEditPreviewStruct - { - /// The start position of the selection before replacing. This field can be modified. - TextPos originalStart; - /// The end position of the selection before replacing. This field can be modified. - TextPos originalEnd; - /// The text of the selection before replacing. - WString originalText; - /// The text of the selection after replacing. This field can be modified. - WString inputText; - /// The base edit version. - vuint editVersion = 0; - /// True if this modification is raised by the keyboard. - bool keyInput = false; - }; - - /// Callback data for text editing. - struct TextEditNotifyStruct - { - /// The start position of the selection before replacing. - TextPos originalStart; - /// The end position of the selection before replacing. - TextPos originalEnd; - /// The text of the selection before replacing. - WString originalText; - /// The start position of the selection after replacing. - TextPos inputStart; - /// The end position of the selection after replacing. - TextPos inputEnd; - /// The text of the selection after replacing. - WString inputText; - /// The created edit version. - vuint editVersion = 0; - /// True if this modification is raised by the keyboard. - bool keyInput = false; - }; - - /// Callback data for text caret changing. - struct TextCaretChangedStruct - { - /// The start position of the selection before caret changing. - TextPos oldBegin; - /// The end position of the selection before caret changing. - TextPos oldEnd; - /// The start position of the selection after caret changing. - TextPos newBegin; - /// The end position of the selection after caret changing. - TextPos newEnd; - /// The current edit version. - vuint editVersion = 0; - }; - - /// Called when the callback is attached to a text box control. - /// The element that used in the text box control. - /// The lock that pretect the element. - /// The owner composition of this element. - /// The current edit version. - virtual void Attach(elements::GuiColorizedTextElement* element, SpinLock& elementModifyLock, compositions::GuiGraphicsComposition* ownerComposition, vuint editVersion)=0; - /// Called when the callback is detached from a text box control. - virtual void Detach()=0; - /// Called before the text is edited. - /// The data for this callback. - virtual void TextEditPreview(TextEditPreviewStruct& arguments)=0; - /// Called after the text is edited and before the caret is changed. - /// The data for this callback. - virtual void TextEditNotify(const TextEditNotifyStruct& arguments)=0; - /// Called after the caret is changed. - /// The data for this callback. - virtual void TextCaretChanged(const TextCaretChangedStruct& arguments)=0; - /// Called after the text is edited and after the caret is changed. - /// The current edit version. - virtual void TextEditFinished(vuint editVersion)=0; - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTAUTOCOMPLETE.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTAUTOCOMPLETE -#define VCZH_PRESENTATION_CONTROLS_GUITEXTAUTOCOMPLETE - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -GuiTextBoxAutoCompleteBase -***********************************************************************/ - - /// The base class of text box auto complete controller. - class GuiTextBoxAutoCompleteBase : public Object, public virtual ICommonTextEditCallback - { - public: - /// Represents an auto complete candidate item. - struct AutoCompleteItem - { - /// Tag object for any purpose, e.g., data binding. - description::Value tag; - /// Display text for the item. - WString text; - }; - - /// Auto complete control provider. - class IAutoCompleteControlProvider : public virtual Interface - { - public: - /// Get the auto complete control that will be installed in a popup to show candidate items. - /// The auto complete control. - virtual GuiControl* GetAutoCompleteControl() = 0; - - /// Get the list control storing candidate items. - /// The list control. It should be inside the auto complete control, or the auto complete control itself. - virtual GuiSelectableListControl* GetListControl() = 0; - - /// Store candidate items in the list control. - /// Candidate items. - virtual void SetSortedContent(const collections::List& items) = 0; - - /// Get the numbers of all stored candidate items. - /// The number of all stored candidate items. - virtual vint GetItemCount() = 0; - - /// Get the text of a specified item. - /// The index of the item. - /// The text of the item. - virtual WString GetItemText(vint index) = 0; - }; - - class TextListControlProvider : public Object, public virtual IAutoCompleteControlProvider - { - protected: - GuiTextList* autoCompleteList; - - public: - TextListControlProvider(TemplateProperty controlTemplate = {}); - ~TextListControlProvider(); - - GuiControl* GetAutoCompleteControl()override; - GuiSelectableListControl* GetListControl()override; - void SetSortedContent(const collections::List& items)override; - vint GetItemCount()override; - WString GetItemText(vint index)override; - }; - - protected: - elements::GuiColorizedTextElement* element; - SpinLock* elementModifyLock; - compositions::GuiGraphicsComposition* ownerComposition; - GuiPopup* autoCompletePopup; - Ptr autoCompleteControlProvider; - TextPos autoCompleteStartPosition; - - bool IsPrefix(const WString& prefix, const WString& candidate); - public: - /// Create an auto complete. - /// A auto complete control provider. Set to null to use a default one. - GuiTextBoxAutoCompleteBase(Ptr _autoCompleteControlProvider = nullptr); - ~GuiTextBoxAutoCompleteBase(); - - void Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - - /// Get the list state. - /// Returns true if the list is visible. - bool IsListOpening(); - /// Notify the list to be visible. - /// The text position to show the list. - void OpenList(TextPos startPosition); - /// Notify the list to be invisible. - void CloseList(); - /// Set the content of the list. - /// The content of the list. - void SetListContent(const collections::List& items); - /// Get the last start position when the list is opened. - /// The start position. - TextPos GetListStartPosition(); - /// Select the previous item. - /// Returns true if this operation succeeded. - bool SelectPreviousListItem(); - /// Select the next item. - /// Returns true if this operation succeeded. - bool SelectNextListItem(); - /// Apply the selected item into the text box. - /// Returns true if this operation succeeded. - bool ApplySelectedListItem(); - /// Get the selected item. - /// The text of the selected item. Returns empty if there is no selected item. - WString GetSelectedListItem(); - /// Highlight a candidate item in the list. - /// The text to match an item. - void HighlightList(const WString& editingText); - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTCOLORIZER.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTCOLORIZER -#define VCZH_PRESENTATION_CONTROLS_GUITEXTCOLORIZER - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -GuiTextBoxColorizerBase -***********************************************************************/ - - /// The base class of text box colorizer. - class GuiTextBoxColorizerBase : public Object, public virtual ICommonTextEditCallback - { - public: - typedef collections::Array ColorArray; - protected: - elements::GuiColorizedTextElement* element; - SpinLock* elementModifyLock; - volatile vint colorizedLineCount; - volatile bool isColorizerRunning; - volatile bool isFinalizing; - SpinLock colorizerRunningEvent; - - static void ColorizerThreadProc(void* argument); - - void StartColorizer(); - void StopColorizer(bool forever); - void StopColorizerForever(); - public: - /// Create a colorrizer. - GuiTextBoxColorizerBase(); - ~GuiTextBoxColorizerBase(); - - void Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - void RestartColorizer(); - - /// Get the lexical analyzer start state for the first line. - /// The lexical analyzer start state for the first line. - virtual vint GetLexerStartState()=0; - /// Get the context sensitive start state for the first line. - /// The context sensitive start state for the first line. - virtual vint GetContextStartState()=0; - /// Colorizer one line with a start state. - /// Line index. - /// Text buffer. - /// Color index buffer. The index should be in [0 .. [M:vl.presentation.controls.GuiTextBoxColorizerBase.GetColors]()-1]. - /// The length of the buffer. - /// The lexical analyzer state for this line. After executing this function, the new value of this argument indicates the new state. - /// The context sensitive state for this line. After executing this function, the new value of this argument indicates the new state. - virtual void ColorizeLineWithCRLF(vint lineIndex, const wchar_t* text, vuint32_t* colors, vint length, vint& lexerState, vint& contextState)=0; - /// Get the supported colors ordered by their indices. - /// The supported colors ordered by their indices. - virtual const ColorArray& GetColors()=0; - }; - -/*********************************************************************** -GuiTextBoxRegexColorizer -***********************************************************************/ - - /// Regex based colorizer. - class GuiTextBoxRegexColorizer : public GuiTextBoxColorizerBase - { - protected: - Ptr lexer; - Ptr colorizer; - void* colorizerArgument[1] { nullptr }; - ColorArray colors; - - elements::text::ColorEntry defaultColor; - collections::List tokenRegexes; - collections::List tokenColors; - collections::List extraTokenColors; - - static void ColorizerProc(void* argument, vint start, vint length, vint token); - public: - /// Create the colorizer. - GuiTextBoxRegexColorizer(); - ~GuiTextBoxRegexColorizer(); - - /// Get the default color. - /// The default color. - elements::text::ColorEntry GetDefaultColor(); - /// Get all regular expressions for tokens. - /// All regular expressions for tokens. - collections::List& GetTokenRegexes(); - /// Get all colors for tokens. - /// All colors for tokens. - collections::List& GetTokenColors(); - /// Get all colors for extra tokens. - /// All colors for extra tokens. - collections::List& GetExtraTokenColors(); - /// Get the first token index for the first extra token. - /// The first token index for the first extra token. Returns -1 if this operation failed. - vint GetExtraTokenIndexStart(); - - /// Set the default color. Call [M:vl.presentation.controls.GuiTextBoxRegexColorizer.Setup] after finishing all configuration. - /// Returns the token index of this token. Returns -1 if this operation failed. - /// The default color. - bool SetDefaultColor(elements::text::ColorEntry value); - /// Add a token type. Call [M:vl.presentation.controls.GuiTextBoxRegexColorizer.Setup] after finishing all configuration. - /// Returns the token index of this token. Returns -1 if this operation failed. - /// The regular expression for this token type. - /// The color for this token type. - vint AddToken(const WString& regex, elements::text::ColorEntry color); - /// Add an extra token type. Call [M:vl.presentation.controls.GuiTextBoxRegexColorizer.Setup] after finishing all configuration. - /// Returns the extra token index of this token. The token index for this token is regex-token-count + extra-token-index Returns -1 if this operation failed. - /// The color for this token type. - vint AddExtraToken(elements::text::ColorEntry color); - /// Clear all token color settings. - void ClearTokens(); - /// Setup the colorizer. After that, the colorizer cannot be changed. - void Setup(); - /// Callback function to set context sensitive state and change token accordingly. - /// Line index. - /// Text buffer. - /// The start position of the token. - /// The length of the token. - /// The token type. After executing this function, the new value of this argument indicates the new token type. - /// The context sensitive state. After executing this function, the new value of this argument indicates the new state. - virtual void ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState); - - vint GetLexerStartState()override; - vint GetContextStartState()override; - void ColorizeLineWithCRLF(vint lineIndex, const wchar_t* text, vuint32_t* colors, vint length, vint& lexerState, vint& contextState)override; - const ColorArray& GetColors()override; - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTUNDOREDO.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTUNDOREDO -#define VCZH_PRESENTATION_CONTROLS_GUITEXTUNDOREDO - - -namespace vl -{ - namespace presentation - { - namespace controls - { - class GuiTextBoxCommonInterface; - -/*********************************************************************** -Undo Redo -***********************************************************************/ - - class GuiGeneralUndoRedoProcessor : public Object - { - protected: - class IEditStep : public Interface - { - public: - virtual void Undo()=0; - virtual void Redo()=0; - }; - friend class collections::ArrayBase>; - - protected: - collections::List> steps; - vint firstFutureStep; - vint savedStep; - bool performingUndoRedo; - - void PushStep(Ptr step); - public: - GuiGeneralUndoRedoProcessor(); - ~GuiGeneralUndoRedoProcessor(); - - Event UndoRedoChanged; - Event ModifiedChanged; - - bool CanUndo(); - bool CanRedo(); - void ClearUndoRedo(); - bool GetModified(); - void NotifyModificationSaved(); - bool Undo(); - bool Redo(); - }; - -/*********************************************************************** -Undo Redo (Text) -***********************************************************************/ - - class GuiTextBoxUndoRedoProcessor : public GuiGeneralUndoRedoProcessor, public ICommonTextEditCallback - { - protected: - class EditStep : public Object, public IEditStep - { - public: - GuiTextBoxUndoRedoProcessor* processor; - TextEditNotifyStruct arguments; - - void Undo(); - void Redo(); - }; - - compositions::GuiGraphicsComposition* ownerComposition; - public: - GuiTextBoxUndoRedoProcessor(); - ~GuiTextBoxUndoRedoProcessor(); - - void Attach(elements::GuiColorizedTextElement* element, SpinLock& elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - }; - -/*********************************************************************** -Undo Redo (Document) -***********************************************************************/ - - class GuiDocumentUndoRedoProcessor : public GuiGeneralUndoRedoProcessor - { - public: - struct ReplaceModelStruct - { - TextPos originalStart; - TextPos originalEnd; - Ptr originalModel; - TextPos inputStart; - TextPos inputEnd; - Ptr inputModel; - - ReplaceModelStruct() - { - } - }; - - struct RenameStyleStruct - { - WString oldStyleName; - WString newStyleName; - - RenameStyleStruct() - { - } - }; - - struct SetAlignmentStruct - { - vint start; - vint end; - collections::Array> originalAlignments; - collections::Array> inputAlignments; - }; - - protected: - elements::GuiDocumentElement* element; - compositions::GuiGraphicsComposition* ownerComposition; - - class ReplaceModelStep : public Object, public IEditStep - { - public: - GuiDocumentUndoRedoProcessor* processor; - ReplaceModelStruct arguments; - - void Undo(); - void Redo(); - }; - - class RenameStyleStep : public Object, public IEditStep - { - public: - GuiDocumentUndoRedoProcessor* processor; - RenameStyleStruct arguments; - - void Undo(); - void Redo(); - }; - - class SetAlignmentStep : public Object, public IEditStep - { - public: - GuiDocumentUndoRedoProcessor* processor; - Ptr arguments; - - void Undo(); - void Redo(); - }; - public: - - GuiDocumentUndoRedoProcessor(); - ~GuiDocumentUndoRedoProcessor(); - - void Setup(elements::GuiDocumentElement* _element, compositions::GuiGraphicsComposition* _ownerComposition); - void OnReplaceModel(const ReplaceModelStruct& arguments); - void OnRenameStyle(const RenameStyleStruct& arguments); - void OnSetAlignment(Ptr arguments); - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTVIEWER.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTVIEWER -#define VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTVIEWER - - -namespace vl -{ - namespace presentation - { - namespace compositions - { - class GuiShortcutKeyManager; - } - - namespace controls - { - -/*********************************************************************** -GuiDocumentConfig -***********************************************************************/ - - /// Represents the edit mode. - enum class GuiDocumentEditMode - { - /// View the rich text only. - ViewOnly, - /// The rich text is selectable. - Selectable, - /// The rich text is editable. - Editable, - }; - - /// Represents the paragraph mode. - enum class GuiDocumentParagraphMode - { - /// Only one paragraph is allowed, only one line in a paragraph is allowed. - Singleline, - /// Only one line in a paragraph is allowed. - Multiline, - /// No constraint. - Paragraph, - }; - - /// Control of editing and rendering behavior. - struct GuiDocumentConfig - { - /// For GuiDocumentLabel only. When it is true, or when wrapLine is true, or when paragraphMode is not Singleline, the control automatically expands to display all content. - Nullable autoExpand; - /// When it is true, the defaut copy paste behavior ignores RTF format. - Nullable pasteAsPlainText; - /// When it is true, document automatically wraps if the width of the control is not enough. - Nullable wrapLine; - /// Control the paragraph and line behavior - Nullable paragraphMode; - /// Insert the space of a default font between paragraphs. - Nullable paragraphPadding; - /// When it is true: - /// double CrLf will be used between paragraphs, when the document converts to plain text. - /// only double CrLf will be recognized as paragraph breaks, when the document converts from plain text. - /// - Nullable doubleLineBreaksBetweenParagraph; - /// When it is true, when removing a line break from a document due to paragraphMode, insert a extra space. - Nullable spaceForFlattenedLineBreak; - - auto operator<=>(const GuiDocumentConfig&) const = default; - - static GuiDocumentConfig GetDocumentLabelDefaultConfig(); - static GuiDocumentConfig GetDocumentViewerDefaultConfig(); - static GuiDocumentConfig GetSinglelineTextBoxDefaultConfig(); - static GuiDocumentConfig GetMultilineTextBoxDefaultConfig(); - static GuiDocumentConfig OverrideConfig(const GuiDocumentConfig& toOverride, const GuiDocumentConfig& newConfig); - }; - - struct GuiDocumentConfigEvaluated - { - bool autoExpand; - bool pasteAsPlainText; - bool wrapLine; - GuiDocumentParagraphMode paragraphMode; - bool paragraphPadding; - bool doubleLineBreaksBetweenParagraph; - bool spaceForFlattenedLineBreak; - - GuiDocumentConfigEvaluated(const GuiDocumentConfig& config) - : autoExpand(config.autoExpand.Value()) - , pasteAsPlainText(config.pasteAsPlainText.Value()) - , wrapLine(config.wrapLine.Value()) - , paragraphMode(config.paragraphMode.Value()) - , paragraphPadding(config.paragraphPadding.Value()) - , doubleLineBreaksBetweenParagraph(config.doubleLineBreaksBetweenParagraph.Value()) - , spaceForFlattenedLineBreak(config.spaceForFlattenedLineBreak.Value()) - { - } - }; - -/*********************************************************************** -GuiDocumentCommonInterface -***********************************************************************/ - - class GuiDocumentCommonInterface; - - /// Embedded object in a document. - class GuiDocumentItem : public Object, public Description - { - friend class GuiDocumentCommonInterface; - protected: - bool visible = false; - WString name; - compositions::GuiBoundsComposition* container; - bool owned = false; - public: - GuiDocumentItem(const WString& _name); - ~GuiDocumentItem(); - - /// Get the container for all embedded controls and compositions in this item. - /// The container. - compositions::GuiGraphicsComposition* GetContainer(); - - /// Get the name of the document item. - /// The name. - WString GetName(); - }; - - /// Document displayer control common interface for displaying . - class GuiDocumentCommonInterface abstract - : protected virtual elements::GuiDocumentElement::ICallback - , public Description - { - typedef collections::Dictionary> DocumentItemMap; - protected: - GuiDocumentConfigEvaluated config; - Ptr baselineDocument; - DocumentItemMap documentItems; - GuiControl* documentControl = nullptr; - elements::GuiDocumentElement* documentElement = nullptr; - compositions::GuiBoundsComposition* documentComposition = nullptr; - - compositions::GuiGraphicsComposition* documentMouseArea = nullptr; - Ptr onMouseMoveHandler; - Ptr onMouseDownHandler; - Ptr onMouseUpHandler; - Ptr onMouseLeaveHandler; - - Ptr activeHyperlinks; - bool dragging = false; - GuiDocumentEditMode editMode = GuiDocumentEditMode::ViewOnly; - - Ptr undoRedoProcessor; - Ptr internalShortcutKeyManager; - - protected: - void InvokeUndoRedoChanged(); - void InvokeModifiedChanged(); - void UpdateCaretPoint(); - void EnsureDocumentRectVisible(Rect bounds); - void Move(TextPos caret, bool shift, bool frontSide); - bool ProcessKey(VKEY code, bool shift, bool ctrl); - void InstallDocumentViewer( - GuiControl* _sender, - compositions::GuiGraphicsComposition* _mouseArea, - compositions::GuiGraphicsComposition* _container, - compositions::GuiGraphicsComposition* eventComposition, - compositions::GuiGraphicsComposition* focusableComposition - ); - void ReplaceMouseArea(compositions::GuiGraphicsComposition* _mouseArea); - - void SetActiveHyperlink(Ptr package); - void ActivateActiveHyperlink(bool activate); - void AddShortcutCommand(VKEY key, const Func& eventHandler); - void EditTextInternal(TextPos begin, TextPos end, const Func& editor); - void EditStyleInternal(TextPos begin, TextPos end, const Func& editor); - - void MergeBaselineAndDefaultFont(Ptr document); - void OnFontChanged(); - void OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments); - void OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments); - - void UpdateCursor(INativeCursor* cursor); - Point GetMouseOffset(); - void OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - - virtual Point GetDocumentViewPosition() = 0; - virtual void EnsureRectVisible(Rect bounds) = 0; - - //================ callback - - void OnStartRender()override; - void OnFinishRender()override; - Size OnRenderEmbeddedObject(const WString& name, const Rect& location)override; - - protected: - - void UserInput_FixForPlainText(Ptr model, vint beginParagraph, vint endParagraph); - void UserInput_FixForSingleline(collections::List& paragraphTexts); - void UserInput_FixForSingleline(Ptr model); - void UserInput_FixForNonParagraph(WString& text); - void UserInput_FixForNonParagraph(Ptr paragraph); - - WString UserInput_ConvertDocumentToText(Ptr model); - void UserInput_FormatText(collections::List& paragraphTexts); - void UserInput_FormatText(const WString& text, collections::List& paragraphTexts); - void UserInput_FormatDocument(Ptr model); - - public: - GuiDocumentCommonInterface(const GuiDocumentConfig& _config); - ~GuiDocumentCommonInterface(); - - /// Active hyperlink changed event. - compositions::GuiNotifyEvent ActiveHyperlinkChanged; - /// Active hyperlink executed event. - compositions::GuiNotifyEvent ActiveHyperlinkExecuted; - - /// Selection changed event. - compositions::GuiNotifyEvent SelectionChanged; - /// Undo redo status changed event. - compositions::GuiNotifyEvent UndoRedoChanged; - /// Modified status changed event. - compositions::GuiNotifyEvent ModifiedChanged; - - /// Get the document. - /// The document. - Ptr GetDocument(); - /// Set the document. When a document is set to this element, modifying the document without invoking will lead to undefined behavior. - /// The document. - void SetDocument(Ptr value); - - //================ document items - - /// Add a document item. The name of the document item will display in the position of the <object> element with the same name in the document. - /// The document item. - /// Returns true if this operation succeeded. - bool AddDocumentItem(Ptr value); - - /// Remove a document item. - /// The document item. - /// Returns true if this operation succeeded. - bool RemoveDocumentItem(Ptr value); - - /// Get all document items. - /// All document items. - const DocumentItemMap& GetDocumentItems(); - - //================ caret operations - - /// - /// Get the begin position of the selection area. - /// - /// The begin position of the selection area. - TextPos GetCaretBegin(); - /// - /// Get the end position of the selection area. - /// - /// The end position of the selection area. - TextPos GetCaretEnd(); - /// - /// Set the end position of the selection area. - /// - /// The begin position of the selection area. - /// The end position of the selection area. - void SetCaret(TextPos begin, TextPos end); - /// Calculate a caret using a specified point. - /// The calculated caret. - /// The specified point. - TextPos CalculateCaretFromPoint(Point point); - /// Get the bounds of a caret. - /// The bounds. - /// The caret. - /// Set to true to get the bounds for the character before it. - Rect GetCaretBounds(TextPos caret, bool frontSide); - - //================ editing operations - - /// Notify that some paragraphs are updated. - /// The start paragraph index. - /// The number of paragraphs to be updated. - /// The number of updated paragraphs. - /// Set to true to notify that the text is updated. - void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); - /// Edit run in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new run. - /// Set to true to copy the model before editing. Otherwise, objects inside the model will be used directly - void EditRun(TextPos begin, TextPos end, Ptr model, bool copy); - /// Edit text in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// Set to true to use the text style in front of the specified range. - /// The new text. - void EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text); - /// Edit style in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new style. - void EditStyle(TextPos begin, TextPos end, Ptr style); - /// Edit image in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new image. - void EditImage(TextPos begin, TextPos end, Ptr image); - /// Set hyperlink in a specified range. - /// The index of the paragraph to edit. - /// The begin position of the range. - /// The end position of the range. - /// The reference of the hyperlink. - /// The normal style name of the hyperlink. - /// The active style name of the hyperlink. - void EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName=DocumentModel::NormalLinkStyleName, const WString& activeStyleName=DocumentModel::ActiveLinkStyleName); - /// Remove hyperlink in a specified range. - /// The index of the paragraph to edit. - /// The begin position of the range. - /// The end position of the range. - void RemoveHyperlink(vint paragraphIndex, vint begin, vint end); - /// Edit style name in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The new style name. - void EditStyleName(TextPos begin, TextPos end, const WString& styleName); - /// Remove style name in a specified range. - /// The begin position of the range. - /// The end position of the range. - void RemoveStyleName(TextPos begin, TextPos end); - /// Rename a style. - /// The name of the style. - /// The new name. - void RenameStyle(const WString& oldStyleName, const WString& newStyleName); - /// Clear all styles in a specified range. - /// The begin position of the range. - /// The end position of the range. - void ClearStyle(TextPos begin, TextPos end); - /// Clear all styles and remove non-text contents in a specified range. - /// The begin position of the range. - /// The end position of the range. - void ConvertToPlainText(TextPos begin, TextPos end); - /// Summarize the text style in a specified range. - /// The text style summary. - /// The begin position of the range. - /// The end position of the range. - Ptr SummarizeStyle(TextPos begin, TextPos end); - /// Summarize the style name in a specified range. - /// The style name summary. - /// The begin position of the range. - /// The end position of the range. - Nullable SummarizeStyleName(TextPos begin, TextPos end); - /// Set the alignment of paragraphs in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The alignment for each paragraph. - void SetParagraphAlignments(TextPos begin, TextPos end, const collections::Array>& alignments); - /// Set the alignment of paragraphs in a specified range. - /// The begin position of the range. - /// The end position of the range. - /// The alignment for each paragraph. - void SetParagraphAlignment(TextPos begin, TextPos end, Nullable alignment); - /// Summarize the text alignment in a specified range. - /// The text alignment summary. - /// The begin position of the range. - /// The end position of the range. - Nullable SummarizeParagraphAlignment(TextPos begin, TextPos end); - - //================ editing control - - /// Get the href attribute of the active hyperlink. - /// The href attribute of the active hyperlink. - WString GetActiveHyperlinkReference(); - /// Get the edit mode of this control. - /// The edit mode. - GuiDocumentEditMode GetEditMode(); - /// Set the edit mode of this control. - /// The edit mode. - void SetEditMode(GuiDocumentEditMode value); - - //================ selection operations - - /// Select all text. - void SelectAll(); - /// Get the selected text. - /// The selected text. - WString GetSelectionText(); - /// Set the selected text. - /// The selected text. - void SetSelectionText(const WString& value); - /// Get the selected model. - /// The selected model. - Ptr GetSelectionModel(); - /// Set the selected model. - /// The selected model. - void SetSelectionModel(Ptr value); - - //================ clipboard operations - - /// Test can the selection be cut. - /// Returns true if the selection can be cut. - bool CanCut(); - /// Test can the selection be copied. - /// Returns true if the selection can be cut. - bool CanCopy(); - /// Test can the content in the clipboard be pasted. - /// Returns true if the content in the clipboard can be pasted. - bool CanPaste(); - /// Cut the selection text. - /// Returns true if this operation succeeded. - bool Cut(); - /// Copy the selection text. - /// Returns true if this operation succeeded. - bool Copy(); - /// Paste the content from the clipboard and replace the selected text. - /// Returns true if this operation succeeded. - bool Paste(); - - //================ undo redo control - - /// Test can undo. - /// Returns true if this action can be performed. - bool CanUndo(); - /// Test can redo. - /// Returns true if this action can be performed. - bool CanRedo(); - /// Clear all undo and redo information. - void ClearUndoRedo(); - /// Test is the text box modified. - /// Returns true if the text box is modified. - bool GetModified(); - /// Notify the text box that the current status is considered saved. - void NotifyModificationSaved(); - /// Perform the undo action. - /// Returns true if this operation succeeded. - bool Undo(); - /// Perform the redo action. - /// Returns true if this operation succeeded. - bool Redo(); - }; - -/*********************************************************************** -GuiDocumentViewer -***********************************************************************/ - - /// Scrollable document viewer for displaying . - class GuiDocumentViewer : public GuiScrollContainer, public GuiDocumentCommonInterface, public Description - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(DocumentViewerTemplate, GuiScrollContainer) - protected: - - void UpdateDisplayFont()override; - Point GetDocumentViewPosition()override; - void EnsureRectVisible(Rect bounds)override; - - static GuiDocumentConfig FixConfig(const GuiDocumentConfig& config); - public: - /// Create a control with a specified style provider. - /// The theme name for retriving a default control template. - /// (Optional): configuration of document editing and rendering behavior. - GuiDocumentViewer(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); - ~GuiDocumentViewer(); - - const WString& GetText()override; - void SetText(const WString& value)override; - }; - -/*********************************************************************** -GuiDocumentViewer -***********************************************************************/ - - /// Static document viewer for displaying . - class GuiDocumentLabel : public GuiControl, public GuiDocumentCommonInterface, public Description - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(DocumentLabelTemplate, GuiControl) - protected: - compositions::GuiBoundsComposition* scrollingContainer = nullptr; - compositions::GuiBoundsComposition* documentContainer = nullptr; - - void UpdateDisplayFont()override; - Point GetDocumentViewPosition()override; - void EnsureRectVisible(Rect bounds)override; - void scrollingContainer_CachedBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void documentContainer_CachedMinSizeChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - - static GuiDocumentConfig FixConfig(const GuiDocumentConfig& config); - public: - /// Create a control with a specified default theme. - /// The theme name for retriving a default control template. - /// (Optional): configuration of document editing and rendering behavior. - GuiDocumentLabel(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); - ~GuiDocumentLabel(); - - const WString& GetText()override; - void SetText(const WString& value)override; - }; - } - } -} - -#endif - - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUITEXTCOMMONINTERFACE.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTCOMMONINTERFACE -#define VCZH_PRESENTATION_CONTROLS_GUITEXTCOMMONINTERFACE - - -namespace vl -{ - namespace presentation - { - namespace compositions - { - class GuiShortcutKeyManager; - } - - namespace controls - { - -/*********************************************************************** -Common Interface -***********************************************************************/ - - /// Common interface for text box controls. - class GuiTextBoxCommonInterface abstract : public Description - { - typedef collections::Array ColorArray; - protected: - class ICallback : public virtual IDescriptable, public Description - { - public: - virtual TextPos GetLeftWord(TextPos pos)=0; - virtual TextPos GetRightWord(TextPos pos)=0; - virtual void GetWord(TextPos pos, TextPos& begin, TextPos& end)=0; - virtual vint GetPageRows()=0; - virtual bool BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText)=0; - virtual void AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText)=0; - virtual void ScrollToView(Point point)=0; - virtual vint GetTextMargin()=0; - }; - - class DefaultCallback : public Object, public ICallback, public Description - { - protected: - elements::GuiColorizedTextElement* textElement; - compositions::GuiGraphicsComposition* textComposition; - bool readonly; - public: - DefaultCallback(elements::GuiColorizedTextElement* _textElement, compositions::GuiGraphicsComposition* _textComposition); - ~DefaultCallback(); - - TextPos GetLeftWord(TextPos pos)override; - TextPos GetRightWord(TextPos pos)override; - void GetWord(TextPos pos, TextPos& begin, TextPos& end)override; - vint GetPageRows()override; - bool BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText)override; - }; - private: - elements::GuiColorizedTextElement* textElement; - compositions::GuiGraphicsComposition* textComposition; - vuint editVersion; - GuiControl* textControl; - ICallback* callback; - bool dragging; - bool readonly; - Ptr colorizer; - Ptr autoComplete; - Ptr undoRedoProcessor; - - bool filledDefaultColors = false; - ColorArray defaultColors; - - SpinLock elementModifyLock; - collections::List> textEditCallbacks; - Ptr internalShortcutKeyManager; - bool preventEnterDueToAutoComplete; - - void InvokeUndoRedoChanged(); - void InvokeModifiedChanged(); - void UpdateCaretPoint(); - void Move(TextPos pos, bool shift); - void Modify(TextPos start, TextPos end, const WString& input, bool asKeyInput); - bool ProcessKey(VKEY code, bool shift, bool ctrl); - - void OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - void OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); - - void OnLeftButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnLeftButtonUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments); - void OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments); - - protected: - - void Install(elements::GuiColorizedTextElement* _textElement, compositions::GuiGraphicsComposition* _textComposition, GuiControl* _textControl, compositions::GuiGraphicsComposition* eventComposition, compositions::GuiGraphicsComposition* focusableComposition); - ICallback* GetCallback(); - void SetCallback(ICallback* value); - bool AttachTextEditCallback(Ptr value); - bool DetachTextEditCallback(Ptr value); - void AddShortcutCommand(VKEY key, const Func& eventHandler); - elements::GuiColorizedTextElement* GetTextElement(); - void UnsafeSetText(const WString& value); - - public: - GuiTextBoxCommonInterface(); - ~GuiTextBoxCommonInterface(); - - /// Selection changed event. - compositions::GuiNotifyEvent SelectionChanged; - /// Undo redo status changed event. - compositions::GuiNotifyEvent UndoRedoChanged; - /// Modified status changed event. - compositions::GuiNotifyEvent ModifiedChanged; - - //================ clipboard operations - - /// Test can the selection be cut. - /// Returns true if the selection can be cut. - bool CanCut(); - /// Test can the selection be copied. - /// Returns true if the selection can be cut. - bool CanCopy(); - /// Test can the content in the clipboard be pasted. - /// Returns true if the content in the clipboard can be pasted. - bool CanPaste(); - /// Cut the selection text. - /// Returns true if this operation succeeded. - bool Cut(); - /// Copy the selection text. - /// Returns true if this operation succeeded. - bool Copy(); - /// Paste the content from the clipboard and replace the selected text. - /// Returns true if this operation succeeded. - bool Paste(); - - //================ editing control - - /// Get the readonly mode. - /// Returns true if the text box is readonly. - bool GetReadonly(); - /// Set the readonly mode. - /// Set to true to make the texg box readonly. - void SetReadonly(bool value); - - //================ text operations - - /// Select all text. - void SelectAll(); - /// Select (highlight) a part of text. - /// The begin position. - /// The end position. This is also the caret position. - void Select(TextPos begin, TextPos end); - /// Get the selected text. - /// The selected text. - WString GetSelectionText(); - /// Set the selected text. - /// The selected text. - void SetSelectionText(const WString& value); - /// Set the selected text and let to text box treat this changing as input by the keyboard. - /// The selected text. - void SetSelectionTextAsKeyInput(const WString& value); - - /// Get the text from a specified row number. - /// The text from a specified row number. - /// The specified row number. - WString GetRowText(vint row); - /// Get the number of rows. - /// The number of rows. - vint GetRowCount(); - /// Get the text from a specified range. - /// The text from a specified range. - /// The specified start position. - /// The specified end position. - WString GetFragmentText(TextPos start, TextPos end); - - /// Get the begin text position of the selection. - /// The begin text position of the selection. - TextPos GetCaretBegin(); - /// Get the end text position of the selection. - /// The end text position of the selection. - TextPos GetCaretEnd(); - /// Get the left-top text position of the selection. - /// The left-top text position of the selection. - TextPos GetCaretSmall(); - /// Get the right-bottom text position of the selection. - /// The right-bottom text position of the selection. - TextPos GetCaretLarge(); - - //================ position query - - /// Get the width of a row. - /// The width of a row in pixel. - /// The specified row number - vint GetRowWidth(vint row); - /// Get the height of a row. - /// The height of a row in pixel. - vint GetRowHeight(); - /// Get the maximum width of all rows. - /// The maximum width of all rows. - vint GetMaxWidth(); - /// Get the total height of all rows. - /// The total height of all rows. - vint GetMaxHeight(); - /// Get the nearest position of a character from a specified display position. - /// Get the nearest position of a character. - /// The specified display position. - TextPos GetTextPosFromPoint(Point point); - /// Get the display position of a character from a specified text position. - /// Get the display position of a character. - /// The specified text position. - Point GetPointFromTextPos(TextPos pos); - /// Get the display bounds of a character from a specified text position. - /// Get the display bounds of a character. - /// The specified text position. - Rect GetRectFromTextPos(TextPos pos); - /// Get the nearest text position from a specified display position. - /// Get the nearest text position. - /// The specified display position. - TextPos GetNearestTextPos(Point point); - - //================ colorizing - - /// Get the current colorizer. - /// The current colorizer. - Ptr GetColorizer(); - /// Set the current colorizer. - /// The current colorizer. - void SetColorizer(Ptr value); - - //================ auto complete - - /// Get the current auto complete controller. - /// The current auto complete controller. - Ptr GetAutoComplete(); - /// Set the current auto complete controller. - /// The current auto complete controller. - void SetAutoComplete(Ptr value); - - //================ undo redo control - - /// Get the current edit version. When the control is modified, the edit version increased. Calling will not reset the edit version. - /// The current edit version. - vuint GetEditVersion(); - /// Test can undo. - /// Returns true if this action can be performed. - bool CanUndo(); - /// Test can redo. - /// Returns true if this action can be performed. - bool CanRedo(); - /// Clear all undo and redo information. - void ClearUndoRedo(); - /// Test is the text box modified. - /// Returns true if the text box is modified. - bool GetModified(); - /// Notify the text box that the current status is considered saved. - void NotifyModificationSaved(); - /// Perform the undo action. - /// Returns true if this operation succeeded. - bool Undo(); - /// Perform the redo action. - /// Returns true if this operation succeeded. - bool Redo(); - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\GUITEXTCONTROLS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTCONTROLS -#define VCZH_PRESENTATION_CONTROLS_GUITEXTCONTROLS - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -MultilineTextBox -***********************************************************************/ - - /// Multiline text box control. - class GuiMultilineTextBox : public GuiScrollView, public GuiTextBoxCommonInterface, public Description - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(MultilineTextBoxTemplate, GuiScrollView) - public: - static const vint TextMargin=3; - - class CommandExecutor : public Object, public ITextBoxCommandExecutor - { - protected: - GuiMultilineTextBox* textBox; - - public: - CommandExecutor(GuiMultilineTextBox* _textBox); - ~CommandExecutor(); - - void UnsafeSetText(const WString& value)override; - }; - - protected: - class TextElementOperatorCallback : public GuiTextBoxCommonInterface::DefaultCallback, public Description - { - protected: - GuiMultilineTextBox* textControl; - public: - TextElementOperatorCallback(GuiMultilineTextBox* _textControl); - - void AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText)override; - void ScrollToView(Point point)override; - vint GetTextMargin()override; - }; - - protected: - Ptr callback; - Ptr commandExecutor; - elements::GuiColorizedTextElement* textElement = nullptr; - compositions::GuiBoundsComposition* textComposition = nullptr; - - void UpdateVisuallyEnabled()override; - void UpdateDisplayFont()override; - void OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget)override; - Size QueryFullSize()override; - void UpdateView(Rect viewBounds)override; - void CalculateViewAndSetScroll(); - void OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - public: - /// Create a control with a specified style provider. - /// The theme name for retriving a default control template. - GuiMultilineTextBox(theme::ThemeName themeName); - ~GuiMultilineTextBox(); - - const WString& GetText()override; - void SetText(const WString& value)override; - }; - -/*********************************************************************** -SinglelineTextBox -***********************************************************************/ - - /// Single text box control. - class GuiSinglelineTextBox : public GuiControl, public GuiTextBoxCommonInterface, public Description - { - GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(SinglelineTextBoxTemplate, GuiControl) - public: - static const vint TextMargin=2; - - protected: - class TextElementOperatorCallback : public GuiTextBoxCommonInterface::DefaultCallback, public Description - { - public: - TextElementOperatorCallback(GuiSinglelineTextBox* _textControl); - - bool BeforeModify(TextPos start, TextPos end, const WString& originalText, WString& inputText)override; - void AfterModify(TextPos originalStart, TextPos originalEnd, const WString& originalText, TextPos inputStart, TextPos inputEnd, const WString& inputText)override; - void ScrollToView(Point point)override; - vint GetTextMargin()override; - }; - - protected: - Ptr callback; - elements::GuiColorizedTextElement* textElement = nullptr; - compositions::GuiTableComposition* textCompositionTable = nullptr; - compositions::GuiCellComposition* textComposition = nullptr; - - void UpdateVisuallyEnabled()override; - void UpdateDisplayFont()override; - void RearrangeTextElement(); - void OnRenderTargetChanged(elements::IGuiGraphicsRenderTarget* renderTarget)override; - void OnBoundsMouseButtonDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); - public: - /// Create a control with a specified style provider. - /// The theme name for retriving a default control template. - GuiSinglelineTextBox(theme::ThemeName themeName); - ~GuiSinglelineTextBox(); - - const WString& GetText()override; - void SetText(const WString& value)override; - - /// - /// Get the password mode displaying character. - /// - /// The password mode displaying character. Returns L'\0' means the password mode is not activated. - wchar_t GetPasswordChar(); - /// - /// Set the password mode displaying character. - /// - /// The password mode displaying character. Set to L'\0' to deactivate the password mode. - void SetPasswordChar(wchar_t value); - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEOPERATIONS.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUILANGUAGEOPERATIONS -#define VCZH_PRESENTATION_CONTROLS_GUILANGUAGEOPERATIONS - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -ParsingInput -***********************************************************************/ - - class RepeatingParsingExecutor; - - /// A data structure storing the parsing input for text box control. - struct RepeatingParsingInput - { - /// The text box edit version of the code. - vuint editVersion = 0; - /// The code. - WString code; - }; - -/*********************************************************************** -ParsingOutput -***********************************************************************/ - - /// A data structure storing the parsing result for text box control. - struct RepeatingParsingOutput - { - /// The parsed syntax tree. - Ptr node; - /// The text box edit version of the code. - vuint editVersion = 0; - /// The code. - WString code; - /// The cache created from [T:vl.presentation.controls.RepeatingParsingExecutor.IParsingAnalyzer]. - Ptr cache; - }; - -/*********************************************************************** -PartialParsingOutput -***********************************************************************/ - - /// A data structure storing the parsing result for partial updating when a text box control is modified. - struct RepeatingPartialParsingOutput - { - /// The input data. - RepeatingParsingOutput input; - /// The rule name that can parse the code of the selected context. - WString rule; - /// Range of the original context in the input. - parsing::ParsingTextRange originalRange; - /// The original context in the syntax tree. - Ptr originalNode; - /// The modified context in the syntax tree. - Ptr modifiedNode; - /// The modified code of the selected context. - WString modifiedCode; - }; - -/*********************************************************************** -PartialParsingOutput -***********************************************************************/ - - /// A data structure storing the information for a candidate item. - struct ParsingCandidateItem - { - /// Semantic id. - vint semanticId = -1; - /// Display name. - WString name; - /// Tag object for any purpose, e.g., data binding. - description::Value tag; - }; - -/*********************************************************************** -ParsingContext -***********************************************************************/ - - /// A data structure storing the context of a token. - struct ParsingTokenContext - { - /// Token syntax tree for the selected token. - parsing::ParsingTreeToken* foundToken = nullptr; - /// The object syntax tree parent of the token. - parsing::ParsingTreeObject* tokenParent = nullptr; - /// Type of the parent. - WString type; - /// Field of the parent that contains the token. - WString field; - /// All acceptable semantic ids. - Ptr> acceptableSemanticIds; - - static bool RetriveContext(ParsingTokenContext& output, parsing::ParsingTreeNode* foundNode, RepeatingParsingExecutor* executor); - static bool RetriveContext(ParsingTokenContext& output, parsing::ParsingTextPos pos, parsing::ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor); - static bool RetriveContext(ParsingTokenContext& output, parsing::ParsingTextRange range, parsing::ParsingTreeObject* rootNode, RepeatingParsingExecutor* executor); - }; - -/*********************************************************************** -RepeatingParsingExecutor -***********************************************************************/ - - /// Repeating parsing executor. - class RepeatingParsingExecutor : public RepeatingTaskExecutor, public Description - { - public: - /// Callback. - class ICallback : public virtual Interface - { - public: - /// Callback when a parsing task is finished. - /// the result of the parsing. - virtual void OnParsingFinishedAsync(const RepeatingParsingOutput& output)=0; - /// Callback when requires enabling or disabling automatically repeating calling to the SubmitTask function. - /// Set to true to require an automatically repeating calling to the SubmitTask function - virtual void RequireAutoSubmitTask(bool enabled)=0; - }; - - /// Parsing analyzer. - class IParsingAnalyzer : public virtual Interface - { - private: - parsing::ParsingTreeNode* ToParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output); - parsing::ParsingTreeObject* ToChild(parsing::ParsingTreeObject* node, const RepeatingPartialParsingOutput* output); - Ptr ToChild(Ptr node, const RepeatingPartialParsingOutput* output); - - protected: - /// Get a syntax tree node's parent when the whole tree is in a partial modified state. You should use this function instead of ParsingTreeNode::GetParent when implementing this interface. - /// Returns the parent node. - /// The node. - /// The partial parsing output, which describes how the whole tree is partial modified. - parsing::ParsingTreeNode* GetParent(parsing::ParsingTreeNode* node, const RepeatingPartialParsingOutput* output); - /// Get a syntax tree node's member when the whole tree is in a partial modified state. You should use this function instead of ParsingTreeObject::GetMember when implementing this interface. - /// Returns the member node. - /// The node. - /// The name of the member. - /// The partial parsing output, which describes how the whole tree is partial modified. - Ptr GetMember(parsing::ParsingTreeObject* node, const WString& name, const RepeatingPartialParsingOutput* output); - /// Get a syntax tree node's item when the whole tree is in a partial modified state. You should use this function instead of ParsingTreeArray::GetItem when implementing this interface. - /// Returns the item node. - /// The node. - /// The index of the item. - /// The partial parsing output, which describes how the whole tree is partial modified. - Ptr GetItem(parsing::ParsingTreeArray* node, vint index, const RepeatingPartialParsingOutput* output); - - public: - /// Called when a is created. - /// The releated . - virtual void Attach(RepeatingParsingExecutor* executor) = 0; - - /// Called when a is destroyed. - /// The releated . - virtual void Detach(RepeatingParsingExecutor* executor) = 0; - - /// Called when a new parsing result is produced. A parsing analyzer can create a cache to be attached to the output containing anything necessary. This function does not run in UI thread. - /// The new parsing result. - /// The created cache object, which can be null. - virtual Ptr CreateCacheAsync(const RepeatingParsingOutput& output) = 0; - - /// Called when an semantic id for a token is needed. If an semantic id is returned, a context sensitive color can be assigned to this token. This functio does not run in UI thread, but it will only be called (for several times) after the cache object is initialized. - /// The token context. - /// The current parsing result. - /// The semantic id. - virtual vint GetSemanticIdForTokenAsync(const ParsingTokenContext& tokenContext, const RepeatingParsingOutput& output) = 0; - - /// Called when multiple auto complete candidate items for a token is needed. If nothing is written into the "candidateItems" parameter and the grammar also doesn't provide static candidate items, nothing will popup. This functio does not run in UI thread, but it will only be called (for several times) after the cache object is initialized. - /// The token context. - /// The partial parsing result. It contains the current parsing result, and an incremental parsing result. If the calculation of candidate items are is very context sensitive, then you should be very careful when traversing the syntax tree, by carefully looking at the "originalNode" and the "modifiedNode" in the "partialOutput" parameter. - /// The candidate items. - virtual void GetCandidateItemsAsync(const ParsingTokenContext& tokenContext, const RepeatingPartialParsingOutput& partialOutput, collections::List& candidateItems) = 0; - - /// Create a tag object for a candidate item without a tag object. An candidate item without a tag maybe created by calling or any token marked by a @Candidate attribute in the grammar. - /// The candidate item. - /// The tag object. In most of the case this object is used for data binding or any other purpose when you want to customize the auto complete control. Returns null if the specified [T.vl.presentation.controls.GuiTextBoxAutoCompleteBase.IAutoCompleteControlProvider] can handle null tag correctly. - virtual description::Value CreateTagForCandidateItem(ParsingCandidateItem& item) = 0; - }; - - /// A base class for implementing a callback. - class CallbackBase : public virtual ICallback, public virtual ICommonTextEditCallback - { - private: - bool callbackAutoPushing; - elements::GuiColorizedTextElement* callbackElement; - SpinLock* callbackElementModifyLock; - - protected: - Ptr parsingExecutor; - - public: - CallbackBase(Ptr _parsingExecutor); - ~CallbackBase(); - - void RequireAutoSubmitTask(bool enabled)override; - void Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - }; - - struct TokenMetaData - { - vint tableTokenIndex; - vint lexerTokenIndex; - vint defaultColorIndex; - bool hasContextColor; - bool hasAutoComplete; - bool isCandidate; - WString unescapedRegexText; - }; - - struct FieldMetaData - { - vint colorIndex; - Ptr> semantics; - }; - private: - Ptr grammarParser; - WString grammarRule; - Ptr analyzer; - collections::List callbacks; - collections::List activatedCallbacks; - ICallback* autoPushingCallback; - - typedef collections::Pair FieldDesc; - collections::Dictionary tokenIndexMap; - collections::SortedList semanticIndexMap; - collections::Dictionary tokenMetaDatas; - collections::Dictionary fieldMetaDatas; - - protected: - - void Execute(const RepeatingParsingInput& input)override; - void PrepareMetaData(); - - /// Called when semantic analyzing is needed. It is encouraged to set the "cache" fields in "context" argument. If there is an binded to the , this function can be automatically done. - /// The parsing result. - virtual void OnContextFinishedAsync(RepeatingParsingOutput& context); - public: - /// Initialize the parsing executor. - /// Parser generated from a grammar. - /// The rule name to parse a complete code. - /// The parsing analyzer to create semantic metadatas, it can be null. - RepeatingParsingExecutor(Ptr _grammarParser, const WString& _grammarRule, Ptr _analyzer = 0); - ~RepeatingParsingExecutor(); - - /// Get the internal parser that parse the text. - /// The internal parser. - Ptr GetParser(); - /// Detach callback. - /// Returns true if this operation succeeded. - /// The callback. - bool AttachCallback(ICallback* value); - /// Detach callback. - /// Returns true if this operation succeeded. - /// The callback. - bool DetachCallback(ICallback* value); - /// Activate a callback. Activating a callback means that the callback owner has an ability to watch a text box modification, e.g., an attached that is also an . The may require one of the activated callback to push code for parsing automatically via a call to . - /// Returns true if this operation succeeded. - /// The callback. - bool ActivateCallback(ICallback* value); - /// Deactivate a callback. See for deatils. - /// Returns true if this operation succeeded. - /// The callback. - bool DeactivateCallback(ICallback* value); - /// Get the parsing analyzer. - /// The parsing analyzer. - Ptr GetAnalyzer(); - - vint GetTokenIndex(const WString& tokenName); - vint GetSemanticId(const WString& name); - WString GetSemanticName(vint id); - const TokenMetaData& GetTokenMetaData(vint regexTokenIndex); - const FieldMetaData& GetFieldMetaData(const WString& type, const WString& field); - - Ptr GetAttribute(vint index, const WString& name, vint argumentCount); - Ptr GetColorAttribute(vint index); - Ptr GetContextColorAttribute(vint index); - Ptr GetSemanticAttribute(vint index); - Ptr GetCandidateAttribute(vint index); - Ptr GetAutoCompleteAttribute(vint index); - - /* - @Color(ColorName) - field: color of the token field when the token type is marked with @ContextColor - token: color of the token - @ContextColor() - token: the color of the token may be changed if the token field is marked with @Color or @Semantic - @Semantic(Type1, Type2, ...) - field: After resolved symbols for this field, only types of symbols that specified in the arguments are acceptable. - @Candidate() - token: when the token can be available after the editing caret, than it will be in the auto complete list. - @AutoComplete() - token: when the token is editing, an auto complete list will appear if possible - */ - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGEAUTOCOMPLETE.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUILANGUAGEAUTOCOMPLETE -#define VCZH_PRESENTATION_CONTROLS_GUILANGUAGEAUTOCOMPLETE - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -GuiGrammarAutoComplete -***********************************************************************/ - - /// Grammar based auto complete controller. - class GuiGrammarAutoComplete - : public GuiTextBoxAutoCompleteBase - , protected RepeatingParsingExecutor::CallbackBase - , private RepeatingTaskExecutor - { - public: - - /// The auto complete list data. - struct AutoCompleteData : ParsingTokenContext - { - /// Available candidate tokens (in lexer token index). - collections::List candidates; - /// Available candidate tokens (in lexer token index) that marked with @AutoCompleteCandidate(). - collections::List shownCandidates; - /// Candidate items. - collections::List candidateItems; - /// The start position of the editing token in global coordination. - TextPos startPosition; - }; - - /// The analysed data from an input code. - struct AutoCompleteContext : RepeatingPartialParsingOutput - { - /// The edit version of modified code. - vuint modifiedEditVersion = 0; - /// The analysed auto complete list data. - Ptr autoComplete; - }; - private: - Ptr grammarParser; - collections::SortedList leftRecursiveRules; - bool editing; - - SpinLock editTraceLock; - collections::List editTrace; - - SpinLock contextLock; - AutoCompleteContext context; - - void Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - void OnParsingFinishedAsync(const RepeatingParsingOutput& output)override; - void CollectLeftRecursiveRules(); - - vint UnsafeGetEditTraceIndex(vuint editVersion); - TextPos ChooseCorrectTextPos(TextPos pos, const regex::RegexTokens& tokens); - void ExecuteRefresh(AutoCompleteContext& newContext); - - bool NormalizeTextPos(AutoCompleteContext& newContext, elements::text::TextLines& lines, TextPos& pos); - void ExecuteEdit(AutoCompleteContext& newContext); - - void DeleteFutures(collections::List& futures); - regex::RegexToken* TraverseTransitions( - parsing::tabling::ParsingState& state, - parsing::tabling::ParsingTransitionCollector& transitionCollector, - TextPos stopPosition, - collections::List& nonRecoveryFutures, - collections::List& recoveryFutures - ); - regex::RegexToken* SearchValidInputToken( - parsing::tabling::ParsingState& state, - parsing::tabling::ParsingTransitionCollector& transitionCollector, - TextPos stopPosition, - AutoCompleteContext& newContext, - collections::SortedList& tableTokenIndices - ); - - TextPos GlobalTextPosToModifiedTextPos(AutoCompleteContext& newContext, TextPos pos); - TextPos ModifiedTextPosToGlobalTextPos(AutoCompleteContext& newContext, TextPos pos); - void ExecuteCalculateList(AutoCompleteContext& newContext); - - void Execute(const RepeatingParsingOutput& input)override; - void PostList(const AutoCompleteContext& newContext, bool byGlobalCorrection); - void Initialize(); - protected: - - /// Called when the context of the code is selected. It is encouraged to set the "candidateItems" field in "context.autoComplete" during the call. If there is an binded to the , this function can be automatically done. - /// The selected context. - virtual void OnContextFinishedAsync(AutoCompleteContext& context); - - /// Call this function in the derived class's destructor when it overrided . - void EnsureAutoCompleteFinished(); - public: - /// Create the auto complete controller with a created parsing executor. - /// The parsing executor. - GuiGrammarAutoComplete(Ptr _parsingExecutor); - /// Create the auto complete controller with a specified grammar and start rule to create a . - /// Parser generated from a grammar. - /// - GuiGrammarAutoComplete(Ptr _grammarParser, const WString& _grammarRule); - ~GuiGrammarAutoComplete(); - - /// Get the internal parsing executor. - /// The parsing executor. - Ptr GetParsingExecutor(); - }; - } - } -} - -#endif - -/*********************************************************************** -.\CONTROLS\TEXTEDITORPACKAGE\LANGUAGESERVICE\GUILANGUAGECOLORIZER.H -***********************************************************************/ -/*********************************************************************** -Vczh Library++ 3.0 -Developer: Zihan Chen(vczh) -GacUI::Control System - -Interfaces: -***********************************************************************/ - -#ifndef VCZH_PRESENTATION_CONTROLS_GUILANGUAGECOLORIZER -#define VCZH_PRESENTATION_CONTROLS_GUILANGUAGECOLORIZER - - -namespace vl -{ - namespace presentation - { - namespace controls - { - -/*********************************************************************** -GuiGrammarColorizer -***********************************************************************/ - - /// Grammar based colorizer. - class GuiGrammarColorizer : public GuiTextBoxRegexColorizer, protected RepeatingParsingExecutor::CallbackBase - { - typedef collections::Pair FieldDesc; - typedef collections::Dictionary FieldContextColors; - typedef collections::Dictionary FieldSemanticColors; - typedef elements::text::ColorEntry ColorEntry; - public: - /// Context for doing semantic colorizing. - struct SemanticColorizeContext : ParsingTokenContext - { - /// Output semantic id that comes from one the argument in the @Semantic attribute. - vint semanticId; - }; - private: - collections::Dictionary colorSettings; - collections::Dictionary semanticColorMap; - - SpinLock contextLock; - RepeatingParsingOutput context; - - void OnParsingFinishedAsync(const RepeatingParsingOutput& output)override; - protected: - /// Called when the node is parsed successfully before restarting colorizing. - /// The result of the parsing. - virtual void OnContextFinishedAsync(const RepeatingParsingOutput& context); - - void Attach(elements::GuiColorizedTextElement* _element, SpinLock& _elementModifyLock, compositions::GuiGraphicsComposition* _ownerComposition, vuint editVersion)override; - void Detach()override; - void TextEditPreview(TextEditPreviewStruct& arguments)override; - void TextEditNotify(const TextEditNotifyStruct& arguments)override; - void TextCaretChanged(const TextCaretChangedStruct& arguments)override; - void TextEditFinished(vuint editVersion)override; - - /// Called when a @SemanticColor attribute in a grammar is activated during colorizing to determine a color for the token. If there is an binded to the , this function can be automatically done. - /// Context for doing semantic colorizing. - /// The corressponding result from the . - virtual void OnSemanticColorize(SemanticColorizeContext& context, const RepeatingParsingOutput& input); - - /// Call this function in the derived class's destructor when it overrided . - void EnsureColorizerFinished(); - public: - /// Create the colorizer with a created parsing executor. - /// The parsing executor. - GuiGrammarColorizer(Ptr _parsingExecutor); - /// Create the colorizer with a specified grammar and start rule to create a . - /// Parser generated from a grammar. - /// - GuiGrammarColorizer(Ptr _grammarParser, const WString& _grammarRule); - ~GuiGrammarColorizer(); - - /// Reset all color settings. - void BeginSetColors(); - /// Get all color names. - /// All color names. - const collections::SortedList& GetColorNames(); - /// Get the color for a token theme name (@Color or @ContextColor("theme-name") in the grammar). - /// The color. - /// The token theme name. - ColorEntry GetColor(const WString& name); - /// Set a color for a token theme name (@Color or @ContextColor("theme-name") in the grammar). - /// The token theme name. - /// The color. - void SetColor(const WString& name, const ColorEntry& entry); - /// Set a color for a token theme name (@Color or @ContextColor("theme-name") in the grammar). - /// The token theme name. - /// The color. - void SetColor(const WString& name, const Color& color); - /// Submit all color settings. - void EndSetColors(); - void ColorizeTokenContextSensitive(vint lineIndex, const wchar_t* text, vint start, vint length, vint& token, vint& contextState)override; - - /// Get the internal parsing executor. - /// The parsing executor. - Ptr GetParsingExecutor(); - }; - } - } -} - -#endif - /*********************************************************************** .\CONTROLS\TOOLSTRIPPACKAGE\GUIMENUCONTROLS.H ***********************************************************************/ @@ -21948,6 +19003,1012 @@ Ribbon Gallery List #endif +/*********************************************************************** +.\GRAPHICSELEMENT\GUIGRAPHICSDOCUMENTELEMENT.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Element System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTELEMENT +#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTELEMENT + + +namespace vl +{ + namespace presentation + { + namespace elements + { + class IGuiDocumentElementCallback; + class GuiDocumentElementRenderer; + +/*********************************************************************** +Rich Content Document (element) +***********************************************************************/ + + /// Defines a rich text document element for rendering complex styled document. + class GuiDocumentElement : public GuiElementBase + { + friend class GuiElementBase; + static constexpr const wchar_t* ElementTypeName = L"RichDocument"; + protected: + Ptr document; + wchar_t passwordChar; + IGuiDocumentElementCallback* callback = nullptr; + bool paragraphPadding = true; + bool wrapLine = true; + TextPos caretBegin; + TextPos caretEnd; + bool caretVisible; + bool caretFrontSide; + Color caretColor; + + void UpdateCaret(); + + GuiDocumentElement(); + public: + /// Get the callback. + /// The callback. + IGuiDocumentElementCallback* GetCallback(); + /// Set the callback. + /// The callback. + void SetCallback(IGuiDocumentElementCallback* value); + + /// Get the document. + /// The document. + Ptr GetDocument(); + /// Set the document. When a document is set to this element, modifying the document without invoking will lead to undefined behavior. + /// The document. + void SetDocument(Ptr value); + /// Get whether paddings are inserted between paragraphs. + /// Returns true if paddings are inserted between paragraphs. + bool GetParagraphPadding(); + /// Set whether paddings are inserted between paragraphs + /// Set to true so that paddings are inserted between paragraphs. + void SetParagraphPadding(bool value); + /// Get line wrapping. + /// Return true if there is automatic line wrapping. + bool GetWrapLine(); + /// Set line wrapping. + /// Set to true so that there is automatic line wrapping. + void SetWrapLine(bool value); + /// Get the password char. A password char is a character that replaces every characters in the document while rendering. + /// Returns the passwrd char. 0 means no password char. + wchar_t GetPasswordChar(); + /// Set the password char. + /// Set to 0 to remove the password char. + void SetPasswordChar(wchar_t value); + + /// + /// Get the begin position of the selection area. + /// + /// The begin position of the selection area. + TextPos GetCaretBegin(); + /// + /// Get the end position of the selection area. + /// + /// The end position of the selection area. + TextPos GetCaretEnd(); + /// + /// Get the prefer side for the caret. + /// + /// Returns true if the caret is rendered for the front side. + bool IsCaretEndPreferFrontSide(); + /// + /// Set the end position of the selection area. + /// + /// The begin position of the selection area. + /// The end position of the selection area. + /// Set to true to show the caret for the character before it. This argument is ignored if begin and end are the same. + void SetCaret(TextPos begin, TextPos end, bool frontSide); + /// + /// Get the caret visibility. + /// + /// Returns true if the caret will be rendered. + bool GetCaretVisible(); + /// + /// Set the caret visibility. + /// + /// True if the caret will be rendered. + void SetCaretVisible(bool value); + /// + /// Get the color of the caret. + /// + /// The color of the caret. + Color GetCaretColor(); + /// + /// Set the color of the caret. + /// + /// The color of the caret. + void SetCaretColor(Color value); + + /// Calculate a caret using a specified comparing caret and a relative position. + /// The calculated caret. + /// The comparing caret. + /// The relative position. + /// Specify the side for the comparingCaret. Retrive the suggested side for the new caret. If the return caret equals compareCaret, this output is ignored. + TextPos CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide); + /// Calculate a caret using a specified point. + /// The calculated caret. + /// The specified point. + TextPos CalculateCaretFromPoint(Point point); + /// Get the bounds of a caret. + /// The bounds. + /// The caret. + /// Set to true to get the bounds for the character before it. + Rect GetCaretBounds(TextPos caret, bool frontSide); + + /// Notify that some paragraphs are updated. + /// The start paragraph index. + /// The number of paragraphs to be updated. + /// The number of updated paragraphs. + /// Set to true to notify that the text is updated. + void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); + /// Edit run in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new run. + /// Set to true to copy the model before editing. Otherwise, objects inside the model will be used directly + void EditRun(TextPos begin, TextPos end, Ptr model, bool copy); + /// Edit text in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// Set to true to use the text style in front of the specified range. + /// The new text. + void EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text); + /// Edit style in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new style. + void EditStyle(TextPos begin, TextPos end, Ptr style); + /// Edit image in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new image. + void EditImage(TextPos begin, TextPos end, Ptr image); + /// Set hyperlink in a specified range. + /// The index of the paragraph to edit. + /// The begin position of the range. + /// The end position of the range. + /// The reference of the hyperlink. + /// The normal style name of the hyperlink. + /// The active style name of the hyperlink. + void EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName=DocumentModel::NormalLinkStyleName, const WString& activeStyleName=DocumentModel::ActiveLinkStyleName); + /// Remove hyperlink in a specified range. + /// The index of the paragraph to edit. + /// The begin position of the range. + /// The end position of the range. + void RemoveHyperlink(vint paragraphIndex, vint begin, vint end); + /// Edit style name in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new style name. + void EditStyleName(TextPos begin, TextPos end, const WString& styleName); + /// Remove style name in a specified range. + /// The begin position of the range. + /// The end position of the range. + void RemoveStyleName(TextPos begin, TextPos end); + /// Rename a style. + /// The name of the style. + /// The new name. + void RenameStyle(const WString& oldStyleName, const WString& newStyleName); + /// Clear all styles in a specified range. + /// The begin position of the range. + /// The end position of the range. + void ClearStyle(TextPos begin, TextPos end); + /// Clear all styles and remove non-text contents in a specified range. + /// The begin position of the range. + /// The end position of the range. + void ConvertToPlainText(TextPos begin, TextPos end); + /// Summarize the text style in a specified range. + /// The text style summary. + /// The begin position of the range. + /// The end position of the range. + Ptr SummarizeStyle(TextPos begin, TextPos end); + /// Summarize the style name in a specified range. + /// The style name summary. + /// The begin position of the range. + /// The end position of the range. + Nullable SummarizeStyleName(TextPos begin, TextPos end); + /// Set the alignment of paragraphs in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The alignment for each paragraph. + void SetParagraphAlignment(TextPos begin, TextPos end, const collections::Array>& alignments); + /// Summarize the text alignment in a specified range. + /// The text alignment summary. + /// The begin position of the range. + /// The end position of the range. + Nullable SummarizeParagraphAlignment(TextPos begin, TextPos end); + + /// Get hyperlink from point. + /// Corressponding hyperlink id. Returns -1 indicates that the point is not in a hyperlink. + /// The point to get the hyperlink id. + Ptr GetHyperlinkFromPoint(Point point); + }; + } + } +} + +#endif + +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\EDITORCALLBACK\GUITEXTUNDOREDO.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUITEXTUNDOREDO +#define VCZH_PRESENTATION_CONTROLS_GUITEXTUNDOREDO + + +namespace vl +{ + namespace presentation + { + namespace controls + { + +/*********************************************************************** +Undo Redo +***********************************************************************/ + + class GuiGeneralUndoRedoProcessor : public Object + { + protected: + class IEditStep : public Interface + { + public: + virtual void Undo()=0; + virtual void Redo()=0; + }; + friend class collections::ArrayBase>; + + protected: + collections::List> steps; + vint firstFutureStep; + vint savedStep; + bool performingUndoRedo; + + void PushStep(Ptr step); + public: + GuiGeneralUndoRedoProcessor(); + ~GuiGeneralUndoRedoProcessor(); + + Event UndoRedoChanged; + Event ModifiedChanged; + + bool CanUndo(); + bool CanRedo(); + void ClearUndoRedo(); + bool GetModified(); + void NotifyModificationSaved(); + bool Undo(); + bool Redo(); + }; + +/*********************************************************************** +Undo Redo (Document) +***********************************************************************/ + + class GuiDocumentUndoRedoProcessor : public GuiGeneralUndoRedoProcessor + { + public: + struct ReplaceModelStruct + { + TextPos originalStart; + TextPos originalEnd; + Ptr originalModel; + TextPos inputStart; + TextPos inputEnd; + Ptr inputModel; + + ReplaceModelStruct() + { + } + }; + + struct RenameStyleStruct + { + WString oldStyleName; + WString newStyleName; + + RenameStyleStruct() + { + } + }; + + struct SetAlignmentStruct + { + vint start; + vint end; + collections::Array> originalAlignments; + collections::Array> inputAlignments; + }; + + protected: + elements::GuiDocumentElement* element; + compositions::GuiGraphicsComposition* ownerComposition; + + class ReplaceModelStep : public Object, public IEditStep + { + public: + GuiDocumentUndoRedoProcessor* processor; + ReplaceModelStruct arguments; + + void Undo(); + void Redo(); + }; + + class RenameStyleStep : public Object, public IEditStep + { + public: + GuiDocumentUndoRedoProcessor* processor; + RenameStyleStruct arguments; + + void Undo(); + void Redo(); + }; + + class SetAlignmentStep : public Object, public IEditStep + { + public: + GuiDocumentUndoRedoProcessor* processor; + Ptr arguments; + + void Undo(); + void Redo(); + }; + public: + + GuiDocumentUndoRedoProcessor(); + ~GuiDocumentUndoRedoProcessor(); + + void Setup(elements::GuiDocumentElement* _element, compositions::GuiGraphicsComposition* _ownerComposition); + void OnReplaceModel(const ReplaceModelStruct& arguments); + void OnRenameStyle(const RenameStyleStruct& arguments); + void OnSetAlignment(Ptr arguments); + }; + } + } +} + +#endif + +/*********************************************************************** +.\GRAPHICSELEMENT\GUIGRAPHICSDOCUMENTRENDERER.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Element System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTRENDERER +#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSDOCUMENTRENDERER + + +namespace vl +{ + namespace presentation + { + namespace elements + { + + namespace visitors + { + class SetPropertiesVisitor; + } + +/*********************************************************************** +Rich Content Document (element) +***********************************************************************/ + + /// Callback interface for this element. + class IGuiDocumentElementCallback : public virtual IDescriptable, public Description + { + public: + /// Called when the rendering is started. + virtual void OnStartRender() = 0; + + /// Called when the rendering is finished. + virtual void OnFinishRender() = 0; + + /// Called when an embedded object is being rendered. + /// Returns the new size of the rendered embedded object. + /// The name of the embedded object + /// The location of the embedded object, relative to the left-top corner of this element. + virtual Size OnRenderEmbeddedObject(const WString& name, const Rect& location) = 0; + }; + + class GuiDocumentElementRenderer : public GuiElementRendererBase, private IGuiGraphicsParagraphCallback + { + friend class visitors::SetPropertiesVisitor; + friend class GuiElementRendererBase; + protected: + struct EmbeddedObject + { + WString name; + Size size; + vint start; + bool resized = false; + }; + + typedef collections::Dictionary> IdEmbeddedObjectMap; + typedef collections::Dictionary NameIdMap; + typedef collections::List FreeIdList; + + struct ParagraphCache + { + WString fullText; + Ptr graphicsParagraph; + IdEmbeddedObjectMap embeddedObjects; + vint selectionBegin; + vint selectionEnd; + + ParagraphCache() + :selectionBegin(-1) + ,selectionEnd(-1) + { + } + }; + + typedef collections::Array> ParagraphCacheArray; + typedef collections::Array ParagraphSizeArray; + + private: + + Size OnRenderInlineObject(vint callbackId, Rect location)override; + protected: + vint paragraphDistance; + vint lastMaxWidth; + Size cachedTotalSize; + IGuiGraphicsLayoutProvider* layoutProvider; + ParagraphCacheArray paragraphCaches; + ParagraphSizeArray paragraphSizes; + + TextPos lastCaret; + Color lastCaretColor; + bool lastCaretFrontSide; + + NameIdMap nameCallbackIdMap; + FreeIdList freeCallbackIds; + vint usedCallbackIds = 0; + + vint renderingParagraph = -1; + Point renderingParagraphOffset; + + void InitializeInternal(); + void FinalizeInternal(); + void RenderTargetChangedInternal(IGuiGraphicsRenderTarget* oldRenderTarget, IGuiGraphicsRenderTarget* newRenderTarget); + Ptr EnsureAndGetCache(vint paragraphIndex, bool createParagraph); + bool GetParagraphIndexFromPoint(Point point, vint& top, vint& index); + public: + GuiDocumentElementRenderer(); + + void Render(Rect bounds)override; + void OnElementStateChanged()override; + void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); + Ptr GetHyperlinkFromPoint(Point point); + + void OpenCaret(TextPos caret, Color color, bool frontSide); + void CloseCaret(TextPos caret); + void SetSelection(TextPos begin, TextPos end); + TextPos CalculateCaret(TextPos comparingCaret, IGuiGraphicsParagraph::CaretRelativePosition position, bool& preferFrontSide); + TextPos CalculateCaretFromPoint(Point point); + Rect GetCaretBounds(TextPos caret, bool frontSide); + }; + } + } +} + +#endif + +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTCOMMONINTERFACE.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTCOMMONINTERFACE +#define VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTCOMMONINTERFACE + + +namespace vl +{ + namespace presentation + { + namespace compositions + { + class GuiShortcutKeyManager; + } + + namespace controls + { + class GuiDocumentCommonInterface; + +/*********************************************************************** +GuiDocumentItem +***********************************************************************/ + + /// Embedded object in a document. + class GuiDocumentItem : public Object, public Description + { + friend class GuiDocumentCommonInterface; + protected: + bool visible = false; + WString name; + compositions::GuiBoundsComposition* container; + bool owned = false; + public: + GuiDocumentItem(const WString& _name); + ~GuiDocumentItem(); + + /// Get the container for all embedded controls and compositions in this item. + /// The container. + compositions::GuiGraphicsComposition* GetContainer(); + + /// Get the name of the document item. + /// The name. + WString GetName(); + }; + +/*********************************************************************** +GuiDocumentCommonInterface +***********************************************************************/ + + /// Document displayer control common interface for displaying . + class GuiDocumentCommonInterface abstract + : protected virtual elements::IGuiDocumentElementCallback + , public Description + { + typedef collections::Dictionary> DocumentItemMap; + protected: + GuiDocumentConfigEvaluated config; + Ptr baselineDocument; + DocumentItemMap documentItems; + GuiControl* documentControl = nullptr; + elements::GuiDocumentElement* documentElement = nullptr; + compositions::GuiBoundsComposition* documentComposition = nullptr; + + compositions::GuiGraphicsComposition* documentMouseArea = nullptr; + Ptr onMouseMoveHandler; + Ptr onMouseDownHandler; + Ptr onMouseUpHandler; + Ptr onMouseLeaveHandler; + + Ptr activeHyperlinks; + bool dragging = false; + GuiDocumentEditMode editMode = GuiDocumentEditMode::ViewOnly; + + Ptr undoRedoProcessor; + Ptr internalShortcutKeyManager; + + protected: + void InvokeUndoRedoChanged(); + void InvokeModifiedChanged(); + void UpdateCaretPoint(); + void EnsureDocumentRectVisible(Rect bounds); + void Move(TextPos caret, bool shift, bool frontSide); + bool ProcessKey(VKEY code, bool shift, bool ctrl); + void InstallDocumentViewer( + GuiControl* _sender, + compositions::GuiGraphicsComposition* _mouseArea, + compositions::GuiGraphicsComposition* _container, + compositions::GuiGraphicsComposition* eventComposition, + compositions::GuiGraphicsComposition* focusableComposition + ); + void ReplaceMouseArea(compositions::GuiGraphicsComposition* _mouseArea); + + void SetActiveHyperlink(Ptr package); + void ActivateActiveHyperlink(bool activate); + void AddShortcutCommand(VKEY key, const Func& eventHandler); + void EditTextInternal(TextPos begin, TextPos end, const Func& editor); + void EditStyleInternal(TextPos begin, TextPos end, const Func& editor); + + void MergeBaselineAndDefaultFont(Ptr document); + void OnFontChanged(); + void OnCaretNotify(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnGotFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnLostFocus(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void OnKeyDown(compositions::GuiGraphicsComposition* sender, compositions::GuiKeyEventArgs& arguments); + void OnCharInput(compositions::GuiGraphicsComposition* sender, compositions::GuiCharEventArgs& arguments); + + void UpdateCursor(INativeCursor* cursor); + Point GetMouseOffset(); + void OnMouseMove(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); + void OnMouseDown(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); + void OnMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); + void OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + + virtual Point GetDocumentViewPosition() = 0; + virtual void EnsureRectVisible(Rect bounds) = 0; + + //================ callback + + void OnStartRender()override; + void OnFinishRender()override; + Size OnRenderEmbeddedObject(const WString& name, const Rect& location)override; + + protected: + + void UserInput_FixForPlainText(Ptr model, vint beginParagraph, vint endParagraph); + void UserInput_FixForSingleline(collections::List& paragraphTexts); + void UserInput_FixForSingleline(Ptr model); + void UserInput_FixForNonParagraph(WString& text); + void UserInput_FixForNonParagraph(Ptr paragraph); + + WString UserInput_ConvertDocumentToText(Ptr model); + void UserInput_FormatText(collections::List& paragraphTexts); + void UserInput_FormatText(const WString& text, collections::List& paragraphTexts); + void UserInput_FormatDocument(Ptr model); + + public: + GuiDocumentCommonInterface(const GuiDocumentConfig& _config); + ~GuiDocumentCommonInterface(); + + /// Active hyperlink changed event. + compositions::GuiNotifyEvent ActiveHyperlinkChanged; + /// Active hyperlink executed event. + compositions::GuiNotifyEvent ActiveHyperlinkExecuted; + + /// Selection changed event. + compositions::GuiNotifyEvent SelectionChanged; + /// Undo redo status changed event. + compositions::GuiNotifyEvent UndoRedoChanged; + /// Modified status changed event. + compositions::GuiNotifyEvent ModifiedChanged; + + /// Get the document. + /// The document. + Ptr GetDocument(); + /// Set the document. When a document is set to this element, modifying the document without invoking will lead to undefined behavior. + /// The document. + void SetDocument(Ptr value); + + //================ document items + + /// Add a document item. The name of the document item will display in the position of the <object> element with the same name in the document. + /// The document item. + /// Returns true if this operation succeeded. + bool AddDocumentItem(Ptr value); + + /// Remove a document item. + /// The document item. + /// Returns true if this operation succeeded. + bool RemoveDocumentItem(Ptr value); + + /// Get all document items. + /// All document items. + const DocumentItemMap& GetDocumentItems(); + + //================ caret operations + + /// + /// Get the begin position of the selection area. + /// + /// The begin position of the selection area. + TextPos GetCaretBegin(); + /// + /// Get the end position of the selection area. + /// + /// The end position of the selection area. + TextPos GetCaretEnd(); + /// + /// Set the end position of the selection area. + /// + /// The begin position of the selection area. + /// The end position of the selection area. + void SetCaret(TextPos begin, TextPos end); + /// Calculate a caret using a specified point. + /// The calculated caret. + /// The specified point. + TextPos CalculateCaretFromPoint(Point point); + /// Get the bounds of a caret. + /// The bounds. + /// The caret. + /// Set to true to get the bounds for the character before it. + Rect GetCaretBounds(TextPos caret, bool frontSide); + + //================ editing operations + + /// Notify that some paragraphs are updated. + /// The start paragraph index. + /// The number of paragraphs to be updated. + /// The number of updated paragraphs. + /// Set to true to notify that the text is updated. + void NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText); + /// Edit run in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new run. + /// Set to true to copy the model before editing. Otherwise, objects inside the model will be used directly + void EditRun(TextPos begin, TextPos end, Ptr model, bool copy); + /// Edit text in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// Set to true to use the text style in front of the specified range. + /// The new text. + void EditText(TextPos begin, TextPos end, bool frontSide, const collections::Array& text); + /// Edit style in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new style. + void EditStyle(TextPos begin, TextPos end, Ptr style); + /// Edit image in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new image. + void EditImage(TextPos begin, TextPos end, Ptr image); + /// Set hyperlink in a specified range. + /// The index of the paragraph to edit. + /// The begin position of the range. + /// The end position of the range. + /// The reference of the hyperlink. + /// The normal style name of the hyperlink. + /// The active style name of the hyperlink. + void EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName=DocumentModel::NormalLinkStyleName, const WString& activeStyleName=DocumentModel::ActiveLinkStyleName); + /// Remove hyperlink in a specified range. + /// The index of the paragraph to edit. + /// The begin position of the range. + /// The end position of the range. + void RemoveHyperlink(vint paragraphIndex, vint begin, vint end); + /// Edit style name in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The new style name. + void EditStyleName(TextPos begin, TextPos end, const WString& styleName); + /// Remove style name in a specified range. + /// The begin position of the range. + /// The end position of the range. + void RemoveStyleName(TextPos begin, TextPos end); + /// Rename a style. + /// The name of the style. + /// The new name. + void RenameStyle(const WString& oldStyleName, const WString& newStyleName); + /// Clear all styles in a specified range. + /// The begin position of the range. + /// The end position of the range. + void ClearStyle(TextPos begin, TextPos end); + /// Clear all styles and remove non-text contents in a specified range. + /// The begin position of the range. + /// The end position of the range. + void ConvertToPlainText(TextPos begin, TextPos end); + /// Summarize the text style in a specified range. + /// The text style summary. + /// The begin position of the range. + /// The end position of the range. + Ptr SummarizeStyle(TextPos begin, TextPos end); + /// Summarize the style name in a specified range. + /// The style name summary. + /// The begin position of the range. + /// The end position of the range. + Nullable SummarizeStyleName(TextPos begin, TextPos end); + /// Set the alignment of paragraphs in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The alignment for each paragraph. + void SetParagraphAlignments(TextPos begin, TextPos end, const collections::Array>& alignments); + /// Set the alignment of paragraphs in a specified range. + /// The begin position of the range. + /// The end position of the range. + /// The alignment for each paragraph. + void SetParagraphAlignment(TextPos begin, TextPos end, Nullable alignment); + /// Summarize the text alignment in a specified range. + /// The text alignment summary. + /// The begin position of the range. + /// The end position of the range. + Nullable SummarizeParagraphAlignment(TextPos begin, TextPos end); + + //================ editing control + + /// Get the href attribute of the active hyperlink. + /// The href attribute of the active hyperlink. + WString GetActiveHyperlinkReference(); + /// Get the edit mode of this control. + /// The edit mode. + GuiDocumentEditMode GetEditMode(); + /// Set the edit mode of this control. + /// The edit mode. + void SetEditMode(GuiDocumentEditMode value); + + //================ selection operations + + /// Select all text. + void SelectAll(); + /// Get the selected text. + /// The selected text. + WString GetSelectionText(); + /// Set the selected text. + /// The selected text. + void SetSelectionText(const WString& value); + /// Get the selected model. + /// The selected model. + Ptr GetSelectionModel(); + /// Set the selected model. + /// The selected model. + void SetSelectionModel(Ptr value); + + //================ clipboard operations + + /// Test can the selection be cut. + /// Returns true if the selection can be cut. + bool CanCut(); + /// Test can the selection be copied. + /// Returns true if the selection can be cut. + bool CanCopy(); + /// Test can the content in the clipboard be pasted. + /// Returns true if the content in the clipboard can be pasted. + bool CanPaste(); + /// Cut the selection text. + /// Returns true if this operation succeeded. + bool Cut(); + /// Copy the selection text. + /// Returns true if this operation succeeded. + bool Copy(); + /// Paste the content from the clipboard and replace the selected text. + /// Returns true if this operation succeeded. + bool Paste(); + + //================ undo redo control + + /// Test can undo. + /// Returns true if this action can be performed. + bool CanUndo(); + /// Test can redo. + /// Returns true if this action can be performed. + bool CanRedo(); + /// Clear all undo and redo information. + void ClearUndoRedo(); + /// Test is the text box modified. + /// Returns true if the text box is modified. + bool GetModified(); + /// Notify the text box that the current status is considered saved. + void NotifyModificationSaved(); + /// Perform the undo action. + /// Returns true if this operation succeeded. + bool Undo(); + /// Perform the redo action. + /// Returns true if this operation succeeded. + bool Redo(); + }; + } + } +} + +#endif + + +/*********************************************************************** +.\CONTROLS\TEXTEDITORPACKAGE\GUIDOCUMENTVIEWER.H +***********************************************************************/ +/*********************************************************************** +Vczh Library++ 3.0 +Developer: Zihan Chen(vczh) +GacUI::Control System + +Interfaces: +***********************************************************************/ + +#ifndef VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTVIEWER +#define VCZH_PRESENTATION_CONTROLS_GUIDOCUMENTVIEWER + + +namespace vl +{ + namespace presentation + { + namespace controls + { + +/*********************************************************************** +GuiDocumentViewer +***********************************************************************/ + + /// Scrollable document viewer for displaying . + class GuiDocumentViewer : public GuiScrollContainer, public GuiDocumentCommonInterface, public Description + { + GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(DocumentViewerTemplate, GuiScrollContainer) + protected: + + void UpdateDisplayFont()override; + Point GetDocumentViewPosition()override; + void EnsureRectVisible(Rect bounds)override; + + static GuiDocumentConfig FixConfig(const GuiDocumentConfig& config); + public: + /// Create a control with a specified style provider. + /// The theme name for retriving a default control template. + /// (Optional): configuration of document editing and rendering behavior. + GuiDocumentViewer(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); + ~GuiDocumentViewer(); + + const WString& GetText()override; + void SetText(const WString& value)override; + }; + + /// Scrollable text box for displaying multiple lines of text. + class GuiMultilineTextBox : public GuiDocumentViewer, public Description + { + public: + /// Create a control with a specified style provider. + /// The theme name for retriving a default control template. + /// (Optional): configuration of document editing and rendering behavior. + GuiMultilineTextBox(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); + ~GuiMultilineTextBox(); + }; + +/*********************************************************************** +GuiDocumentLabel +***********************************************************************/ + + /// Static document viewer for displaying . + class GuiDocumentLabel : public GuiControl, public GuiDocumentCommonInterface, public Description + { + GUI_SPECIFY_CONTROL_TEMPLATE_TYPE(DocumentLabelTemplate, GuiControl) + protected: + compositions::GuiBoundsComposition* scrollingContainer = nullptr; + compositions::GuiBoundsComposition* documentContainer = nullptr; + + void UpdateDisplayFont()override; + Point GetDocumentViewPosition()override; + void EnsureRectVisible(Rect bounds)override; + void scrollingContainer_CachedBoundsChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + void documentContainer_CachedMinSizeChanged(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); + + static GuiDocumentConfig FixConfig(const GuiDocumentConfig& config); + public: + /// Create a control with a specified default theme. + /// The theme name for retriving a default control template. + /// (Optional): configuration of document editing and rendering behavior. + GuiDocumentLabel(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); + ~GuiDocumentLabel(); + + const WString& GetText()override; + void SetText(const WString& value)override; + }; + + /// Scrollable text box for displaying single line of text. + class GuiSinglelineTextBox : public GuiDocumentLabel, public Description + { + public: + /// Create a control with a specified style provider. + /// The theme name for retriving a default control template. + /// (Optional): configuration of document editing and rendering behavior. + GuiSinglelineTextBox(theme::ThemeName themeName, const GuiDocumentConfig& _config = {}); + ~GuiSinglelineTextBox(); + + /// Get the password char. A password char is a character that replaces every characters in the document while rendering. + /// Returns the passwrd char. 0 means no password char. + wchar_t GetPasswordChar(); + /// Set the password char. + /// Set to 0 to remove the password char. + void SetPasswordChar(wchar_t value); + }; + } + } +} + +#endif + + /*********************************************************************** .\CONTROLS\INCLUDEALL.H ***********************************************************************/ @@ -23367,22 +21428,6 @@ namespace vl::presentation::elements_remoteprotocol void SendUpdateElementMessages(bool fullContent) override; }; - - class GuiColorizedTextElementRenderer : public GuiRemoteProtocolElementRenderer, protected GuiColorizedTextElement::ICallback - { - friend class GuiElementRendererBase; - using TBase = GuiRemoteProtocolElementRenderer; - protected: - void ColorChanged() override; - void FontChanged() override; - void InitializeInternal(); - void FinalizeInternal(); - public: - GuiColorizedTextElementRenderer(); - - void OnElementStateChanged() override; - void SendUpdateElementMessages(bool fullContent) override; - }; } #endif @@ -26081,7 +24126,6 @@ External Functions { return Ptr(T::Create()); } - extern presentation::elements::text::TextLines* GuiColorizedTextElement_GetLines(presentation::elements::GuiColorizedTextElement* thisObject); extern void GuiTableComposition_SetRows(presentation::compositions::GuiTableComposition* thisObject, vint value); extern void GuiTableComposition_SetColumns(presentation::compositions::GuiTableComposition* thisObject, vint value); diff --git a/Import/GacUIReflection.cpp b/Import/GacUIReflection.cpp index 50d05a85..2a73e9bc 100644 --- a/Import/GacUIReflection.cpp +++ b/Import/GacUIReflection.cpp @@ -1662,7 +1662,6 @@ namespace vl using namespace presentation::controls; using namespace presentation::controls::list; using namespace presentation::controls::tree; - using namespace presentation::elements::text; using namespace presentation::theme; #ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA @@ -3023,57 +3022,16 @@ Type Declaration (Class) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE_2(GuiDocumentLabel, const GuiDocumentConfig&, config) END_CLASS_MEMBER(GuiDocumentLabel) - BEGIN_CLASS_MEMBER(GuiTextBoxCommonInterface) - CLASS_MEMBER_GUIEVENT(SelectionChanged) - CLASS_MEMBER_GUIEVENT(UndoRedoChanged) - - CLASS_MEMBER_PROPERTY_FAST(Readonly) - CLASS_MEMBER_PROPERTY_EVENT_FAST(SelectionText, SelectionChanged) - CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(CaretBegin, SelectionChanged) - CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(CaretEnd, SelectionChanged) - CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(CaretSmall, SelectionChanged) - CLASS_MEMBER_PROPERTY_EVENT_READONLY_FAST(CaretLarge, SelectionChanged) - CLASS_MEMBER_PROPERTY_READONLY_FAST(RowCount) - CLASS_MEMBER_PROPERTY_READONLY_FAST(RowHeight) - CLASS_MEMBER_PROPERTY_READONLY_FAST(MaxWidth) - CLASS_MEMBER_PROPERTY_READONLY_FAST(MaxHeight) - CLASS_MEMBER_PROPERTY_READONLY_FAST(EditVersion) - CLASS_MEMBER_PROPERTY_GUIEVENT_READONLY_FAST(Modified) - - CLASS_MEMBER_METHOD(CanCut, NO_PARAMETER) - CLASS_MEMBER_METHOD(CanCopy, NO_PARAMETER) - CLASS_MEMBER_METHOD(CanPaste, NO_PARAMETER) - CLASS_MEMBER_METHOD(Cut, NO_PARAMETER) - CLASS_MEMBER_METHOD(Copy, NO_PARAMETER) - CLASS_MEMBER_METHOD(Paste, NO_PARAMETER) - CLASS_MEMBER_METHOD(SelectAll, NO_PARAMETER) - CLASS_MEMBER_METHOD(Select, {L"begin" _ L"end"}) - CLASS_MEMBER_METHOD(SetSelectionTextAsKeyInput, {L"value"}) - CLASS_MEMBER_METHOD(GetRowText, {L"row"}) - CLASS_MEMBER_METHOD(GetFragmentText, {L"start" _ L"end"}) - CLASS_MEMBER_METHOD(GetRowWidth, {L"row"}) - CLASS_MEMBER_METHOD(GetTextPosFromPoint, {L"point"}) - CLASS_MEMBER_METHOD(GetPointFromTextPos, {L"pos"}) - CLASS_MEMBER_METHOD(GetRectFromTextPos, {L"pos"}) - CLASS_MEMBER_METHOD(GetNearestTextPos, {L"point"}) - CLASS_MEMBER_METHOD(CanUndo, NO_PARAMETER) - CLASS_MEMBER_METHOD(CanRedo, NO_PARAMETER) - CLASS_MEMBER_METHOD(ClearUndoRedo, NO_PARAMETER) - CLASS_MEMBER_METHOD(NotifyModificationSaved, NO_PARAMETER) - CLASS_MEMBER_METHOD(Undo, NO_PARAMETER) - CLASS_MEMBER_METHOD(Redo, NO_PARAMETER) - END_CLASS_MEMBER(GuiTextBoxCommonInterface) - BEGIN_CLASS_MEMBER(GuiMultilineTextBox) - CLASS_MEMBER_BASE(GuiScrollView) - CLASS_MEMBER_BASE(GuiTextBoxCommonInterface) + CLASS_MEMBER_BASE(GuiDocumentViewer) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE(GuiMultilineTextBox) + CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE_2(GuiMultilineTextBox, const GuiDocumentConfig&, config) END_CLASS_MEMBER(GuiMultilineTextBox) BEGIN_CLASS_MEMBER(GuiSinglelineTextBox) - CLASS_MEMBER_BASE(GuiControl) - CLASS_MEMBER_BASE(GuiTextBoxCommonInterface) + CLASS_MEMBER_BASE(GuiDocumentLabel) CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE(GuiSinglelineTextBox) + CONTROL_CONSTRUCTOR_CONTROLT_TEMPLATE_2(GuiSinglelineTextBox, const GuiDocumentConfig&, config) CLASS_MEMBER_PROPERTY_FAST(PasswordChar) END_CLASS_MEMBER(GuiSinglelineTextBox) @@ -3279,41 +3237,6 @@ Type Declaration (Extra) ENUM_NAMESPACE_ITEM(Backslash) END_ENUM_ITEM(GuiGradientBackgroundElement::Direction) - BEGIN_CLASS_MEMBER(text::TextLines) - CLASS_MEMBER_PROPERTY_READONLY_FAST(Count) - CLASS_MEMBER_PROPERTY_FAST(TabSpaceCount) - CLASS_MEMBER_PROPERTY_READONLY_FAST(RowHeight) - CLASS_MEMBER_PROPERTY_READONLY_FAST(MaxWidth) - CLASS_MEMBER_PROPERTY_READONLY_FAST(MaxHeight) - CLASS_MEMBER_PROPERTY_FAST(PasswordChar) - - CLASS_MEMBER_METHOD_OVERLOAD(GetText, NO_PARAMETER, WString(text::TextLines::*)()) - CLASS_MEMBER_METHOD_OVERLOAD(GetText, {L"start" _ L"end"}, WString(text::TextLines::*)(TextPos _ TextPos)) - CLASS_MEMBER_METHOD(SetText, {L"value"}) - CLASS_MEMBER_METHOD(RemoveLines, {L"start" _ L"end"}) - CLASS_MEMBER_METHOD(IsAvailable, {L"pos"}) - CLASS_MEMBER_METHOD(Normalize, {L"pos"}) - CLASS_MEMBER_METHOD_OVERLOAD(Modify, {L"start" _ L"end" _ L"input"}, TextPos(text::TextLines::*)(TextPos _ TextPos _ const WString&)) - CLASS_MEMBER_METHOD(Clear, NO_PARAMETER) - CLASS_MEMBER_METHOD(ClearMeasurement, NO_PARAMETER) - CLASS_MEMBER_METHOD(MeasureRow, {L"row"}) - CLASS_MEMBER_METHOD(GetRowWidth, {L"row"}) - CLASS_MEMBER_METHOD(GetTextPosFromPoint, {L"point"}) - CLASS_MEMBER_METHOD(GetPointFromTextPos, {L"pos"}) - CLASS_MEMBER_METHOD(GetRectFromTextPos, {L"pos"}) - END_CLASS_MEMBER(text::TextLines) - - BEGIN_STRUCT_MEMBER(text::ColorItem) - STRUCT_MEMBER(text) - STRUCT_MEMBER(background) - END_STRUCT_MEMBER(text::ColorItem) - - BEGIN_STRUCT_MEMBER(text::ColorEntry) - STRUCT_MEMBER(normal) - STRUCT_MEMBER(selectedFocused) - STRUCT_MEMBER(selectedUnfocused) - END_STRUCT_MEMBER(text::ColorEntry) - /*********************************************************************** Type Declaration (Class) ***********************************************************************/ @@ -3425,25 +3348,6 @@ Type Declaration (Class) CLASS_MEMBER_PROPERTY_FAST(BackgroundColor) END_CLASS_MEMBER(GuiPolygonElement) - BEGIN_CLASS_MEMBER(GuiColorizedTextElement) - CLASS_MEMBER_BASE(IGuiGraphicsElement) - ELEMENT_CONSTRUCTOR(GuiColorizedTextElement) - - CLASS_MEMBER_PROPERTY_FAST(Font) - CLASS_MEMBER_PROPERTY_FAST(PasswordChar) - CLASS_MEMBER_PROPERTY_FAST(ViewPosition) - CLASS_MEMBER_PROPERTY_FAST(VisuallyEnabled) - CLASS_MEMBER_PROPERTY_FAST(Focused) - CLASS_MEMBER_PROPERTY_FAST(CaretBegin) - CLASS_MEMBER_PROPERTY_FAST(CaretEnd) - CLASS_MEMBER_PROPERTY_FAST(CaretVisible) - CLASS_MEMBER_PROPERTY_FAST(CaretColor) - - CLASS_MEMBER_EXTERNALMETHOD(GetLines, NO_PARAMETER, text::TextLines*(GuiColorizedTextElement::*)(), vl::reflection::description::GuiColorizedTextElement_GetLines) - CLASS_MEMBER_PROPERTY_READONLY(Lines, GetLines) - CLASS_MEMBER_PROPERTY_FAST(Colors) - END_CLASS_MEMBER(GuiColorizedTextElement) - BEGIN_CLASS_MEMBER(GuiDocumentElement) CLASS_MEMBER_BASE(IGuiGraphicsElement) ELEMENT_CONSTRUCTOR(GuiDocumentElement) @@ -3451,6 +3355,7 @@ Type Declaration (Class) CLASS_MEMBER_PROPERTY_FAST(Document) CLASS_MEMBER_PROPERTY_FAST(ParagraphPadding) CLASS_MEMBER_PROPERTY_FAST(WrapLine) + CLASS_MEMBER_PROPERTY_FAST(PasswordChar) CLASS_MEMBER_PROPERTY_READONLY_FAST(CaretBegin) CLASS_MEMBER_PROPERTY_READONLY_FAST(CaretEnd) CLASS_MEMBER_PROPERTY_FAST(CaretVisible) diff --git a/Import/GacUIReflection.h b/Import/GacUIReflection.h index c0e2af41..5103fdc6 100644 --- a/Import/GacUIReflection.h +++ b/Import/GacUIReflection.h @@ -213,9 +213,6 @@ Type List (Elements) F(presentation::elements::ElementShape)\ F(presentation::elements::Gui3DSplitterElement::Direction)\ F(presentation::elements::GuiGradientBackgroundElement::Direction)\ - F(presentation::elements::text::TextLines)\ - F(presentation::elements::text::ColorItem)\ - F(presentation::elements::text::ColorEntry)\ #define GUIREFLECTIONELEMENT_CLASS_TYPELIST(F)\ F(presentation::elements::GuiFocusRectangleElement)\ @@ -228,7 +225,6 @@ Type List (Elements) F(presentation::elements::GuiSolidLabelElement)\ F(presentation::elements::GuiImageFrameElement)\ F(presentation::elements::GuiPolygonElement)\ - F(presentation::elements::GuiColorizedTextElement)\ F(presentation::elements::GuiDocumentElement)\ #define GUIREFLECTIONELEMENT_TYPELIST(F)\ @@ -421,7 +417,6 @@ Type List (Controls) F(presentation::controls::GuiDocumentConfig)\ F(presentation::controls::GuiDocumentItem)\ F(presentation::controls::GuiDocumentCommonInterface)\ - F(presentation::controls::GuiTextBoxCommonInterface)\ F(presentation::controls::list::IDataGridContext)\ F(presentation::controls::list::IDataVisualizerFactory)\ F(presentation::controls::list::IDataVisualizer)\