Update release

This commit is contained in:
vczh
2025-09-06 07:21:59 -07:00
parent 4bec8e9fc6
commit 27e37c5bf3
10 changed files with 579 additions and 344 deletions
+143 -34
View File
@@ -8776,7 +8776,7 @@ WindowsGDIParagraph
if (paragraph->BuildUniscribeData(renderTarget->GetDC())) if (paragraph->BuildUniscribeData(renderTarget->GetDC()))
{ {
vint width = paragraph->lastAvailableWidth == -1 ? 65536 : paragraph->lastAvailableWidth; vint width = paragraph->lastAvailableWidth == -1 ? 65536 : paragraph->lastAvailableWidth;
paragraph->Layout(width, paragraph->paragraphAlignment); paragraph->Layout(paragraph->lastWrapLine, width, paragraph->paragraphAlignment);
} }
} }
@@ -8829,18 +8829,13 @@ WindowsGDIParagraph
bool GetWrapLine()override bool GetWrapLine()override
{ {
return paragraph->wrapLine; return paragraph->lastWrapLine;
} }
void SetWrapLine(bool value)override void SetWrapLine(bool value)override
{ {
CHECK_ERROR(value, L"vl::presentation::elements_windows_gdi::WindowsGDIParagraph::SetWrapLine(bool)#Non-wrapline not implemented.");
if (paragraph->wrapLine != value)
{
paragraph->wrapLine = value;
paragraph->BuildUniscribeData(renderTarget->GetDC()); paragraph->BuildUniscribeData(renderTarget->GetDC());
paragraph->Layout(paragraph->lastAvailableWidth, paragraph->paragraphAlignment); paragraph->Layout(value, paragraph->lastAvailableWidth, paragraph->paragraphAlignment);
}
} }
vint GetMaxWidth()override vint GetMaxWidth()override
@@ -8851,7 +8846,7 @@ WindowsGDIParagraph
void SetMaxWidth(vint value)override void SetMaxWidth(vint value)override
{ {
paragraph->BuildUniscribeData(renderTarget->GetDC()); paragraph->BuildUniscribeData(renderTarget->GetDC());
paragraph->Layout(value, paragraph->paragraphAlignment); paragraph->Layout(paragraph->lastWrapLine, value, paragraph->paragraphAlignment);
} }
Alignment GetParagraphAlignment()override Alignment GetParagraphAlignment()override
@@ -8862,7 +8857,7 @@ WindowsGDIParagraph
void SetParagraphAlignment(Alignment value)override void SetParagraphAlignment(Alignment value)override
{ {
paragraph->BuildUniscribeData(renderTarget->GetDC()); paragraph->BuildUniscribeData(renderTarget->GetDC());
paragraph->Layout(paragraph->lastAvailableWidth, value); paragraph->Layout(paragraph->lastWrapLine, paragraph->lastAvailableWidth, value);
} }
bool SetFont(vint start, vint length, const WString& value)override bool SetFont(vint start, vint length, const WString& value)override
@@ -8976,7 +8971,7 @@ WindowsGDIParagraph
{ {
PrepareUniscribeData(); PrepareUniscribeData();
return Size( return Size(
(paragraph->wrapLine ? 0 : paragraph->bounds.Width()), (paragraph->lastWrapLine ? 0 : paragraph->bounds.Width()),
paragraph->bounds.Height()); paragraph->bounds.Height());
} }
@@ -9000,6 +8995,31 @@ WindowsGDIParagraph
return true; return true;
} }
bool IsCaretBoundsFromTextRun(vint caret, bool caretFrontSide)
{
if (!paragraph->IsValidCaret(caret)) return false;
vint frontLine = 0;
vint backLine = 0;
paragraph->GetLineIndexFromTextPos(caret, frontLine, backLine);
if (frontLine == -1 || backLine == -1) return false;
vint lineIndex = caretFrontSide ? frontLine : backLine;
lineIndex = lineIndex < 0 ? 0 : lineIndex > paragraph->lines.Count() - 1 ? paragraph->lines.Count() - 1 : lineIndex;
Ptr<UniscribeLine> line = paragraph->lines[caretFrontSide ? frontLine : backLine];
vint frontRun = -1;
vint backRun = -1;
paragraph->GetRunIndexFromTextPos(caret, lineIndex, frontRun, backRun);
if (frontRun == -1 || backRun == -1) return false;
vint runIndex = caretFrontSide ? frontRun : backRun;
runIndex = runIndex < 0 ? 0 : runIndex > line->scriptRuns.Count() - 1 ? line->scriptRuns.Count() - 1 : runIndex;
Ptr<UniscribeRun> run = line->scriptRuns[runIndex];
return run.Cast<UniscribeTextRun>();
}
void Render(Rect bounds)override void Render(Rect bounds)override
{ {
PrepareUniscribeData(); PrepareUniscribeData();
@@ -9015,7 +9035,7 @@ WindowsGDIParagraph
Rect caretBounds = GetCaretBounds(caret, caretFrontSide); Rect caretBounds = GetCaretBounds(caret, caretFrontSide);
vint x = caretBounds.x1 + bounds.x1; vint x = caretBounds.x1 + bounds.x1;
vint y1 = caretBounds.y1 + bounds.y1; vint y1 = caretBounds.y1 + bounds.y1;
vint y2=y1+(vint)(caretBounds.Height()*1.5); vint y2 = y1 + (vint)(caretBounds.Height() * (IsCaretBoundsFromTextRun(caret, caretFrontSide) ? 1.5 : 1));
WinDC* dc = renderTarget->GetDC(); WinDC* dc = renderTarget->GetDC();
dc->SetPen(caretPen); dc->SetPen(caretPen);
@@ -10838,7 +10858,7 @@ UniscribeTextRun
return SumHeight(); return SumHeight();
} }
void UniscribeTextRun::SearchForLineBreak(vint tempStart, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances) void UniscribeTextRun::SearchForLineBreak(vint tempStart, bool wrapLine, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)
{ {
vint width=0; vint width=0;
charLength=0; charLength=0;
@@ -10847,7 +10867,7 @@ UniscribeTextRun
{ {
if(i==length || scriptItem->charLogattrs[i+(startFromLine-scriptItem->startFromLine)].fSoftBreak==TRUE) if(i==length || scriptItem->charLogattrs[i+(startFromLine-scriptItem->startFromLine)].fSoftBreak==TRUE)
{ {
if(width<=maxWidth || (firstRun && charLength==0)) if(!wrapLine || width<=maxWidth || (firstRun && charLength==0))
{ {
charLength=i-tempStart; charLength=i-tempStart;
charAdvances=width; charAdvances=width;
@@ -11030,9 +11050,9 @@ UniscribeEmbeddedObjectRun
return 0; return 0;
} }
void UniscribeEmbeddedObjectRun::SearchForLineBreak(vint tempStart, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances) void UniscribeEmbeddedObjectRun::SearchForLineBreak(vint tempStart, bool wrapLine, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)
{ {
if (firstRun || properties.size.x <= maxWidth) if (firstRun || !wrapLine || properties.size.x <= maxWidth)
{ {
charLength = length - tempStart; charLength = length - tempStart;
charAdvances = properties.size.x; charAdvances = properties.size.x;
@@ -11299,7 +11319,7 @@ UniscribeLine
return false; return false;
} }
void UniscribeLine::Layout(vint availableWidth, Alignment alignment, vint top, vint& totalHeight) void UniscribeLine::Layout(bool wrapLine, vint availableWidth, Alignment alignment, vint top, vint& totalHeight)
{ {
vint cx = 0; vint cx = 0;
vint cy = top; vint cy = top;
@@ -11327,6 +11347,7 @@ UniscribeLine
while (startRun < scriptRuns.Count()) while (startRun < scriptRuns.Count())
{ {
vint lastCompletedRunOffset = 0;
vint currentWidth = 0; vint currentWidth = 0;
bool firstRun = true; bool firstRun = true;
// search for a range to fit in the given width // search for a range to fit in the given width
@@ -11335,19 +11356,28 @@ UniscribeLine
vint charLength = 0; vint charLength = 0;
vint charAdvances = 0; vint charAdvances = 0;
UniscribeRun* run = scriptRuns[i].Obj(); UniscribeRun* run = scriptRuns[i].Obj();
run->SearchForLineBreak(lastRunOffset, availableWidth-currentWidth, firstRun, charLength, charAdvances); run->SearchForLineBreak(lastRunOffset, wrapLine, availableWidth - currentWidth, firstRun, charLength, charAdvances);
firstRun = false; firstRun = false;
if (charLength == run->length - lastRunOffset) if (charLength == run->length - lastRunOffset)
{ {
lastCompletedRunOffset = lastRunOffset;
lastRun = i + 1; lastRun = i + 1;
lastRunOffset = 0; lastRunOffset = 0;
currentWidth += charAdvances; currentWidth += charAdvances;
} }
else else
{
if (lastRunOffset == 0 && charLength == 0)
{
lastRun--;
lastRunOffset = lastCompletedRunOffset;
}
else
{ {
lastRun = i; lastRun = i;
lastRunOffset = lastRunOffset + charLength; lastRunOffset = lastRunOffset + charLength;
}
break; break;
} }
} }
@@ -11525,7 +11555,7 @@ UniscribeParagraph
***********************************************************************/ ***********************************************************************/
UniscribeParagraph::UniscribeParagraph() UniscribeParagraph::UniscribeParagraph()
:wrapLine(true) :lastWrapLine(true)
,lastAvailableWidth(-1) ,lastAvailableWidth(-1)
,paragraphAlignment(Alignment::Left) ,paragraphAlignment(Alignment::Left)
,built(false) ,built(false)
@@ -11638,19 +11668,25 @@ UniscribeParagraph (Initialization)
return true; return true;
} }
void UniscribeParagraph::Layout(vint availableWidth, Alignment alignment) void UniscribeParagraph::Layout(bool wrapLine, vint availableWidth, Alignment alignment)
{ {
if(lastAvailableWidth==availableWidth && paragraphAlignment==alignment) if (lastWrapLine == wrapLine && lastAvailableWidth == availableWidth && paragraphAlignment == alignment)
{ {
return; return;
} }
lastWrapLine = wrapLine;
lastAvailableWidth = availableWidth; lastAvailableWidth = availableWidth;
paragraphAlignment = alignment; paragraphAlignment = alignment;
if (lastAvailableWidth == -1)
{
return;
}
vint cy = 0; vint cy = 0;
for (auto line : lines) for (auto line : lines)
{ {
line->Layout(availableWidth, alignment, cy, cy); line->Layout(wrapLine, availableWidth, alignment, cy, cy);
} }
// calculate paragraph bounds // calculate paragraph bounds
@@ -12122,6 +12158,51 @@ UniscribeParagraph (Caret Helper)
} }
} }
void UniscribeParagraph::GetRunIndexFromTextPos(vint textPos, vint lineIndex, vint& frontRun, vint& backRun)
{
frontRun = -1;
backRun = -1;
if (!IsValidTextPos(textPos)) return;
if (lineIndex < 0 || lineIndex >= lines.Count()) return;
Ptr<UniscribeLine> line = lines[lineIndex];
vint start = 0;
vint end = line->scriptRuns.Count() - 1;
while (start <= end)
{
vint middle = (start + end) / 2;
Ptr<UniscribeRun> run = line->scriptRuns[middle];
vint lineStart = line->startFromParagraph + run->startFromLine;
vint lineEnd = line->startFromParagraph + run->startFromLine + run->length;
if (textPos < lineStart)
{
end = middle - 1;
}
else if (textPos > lineEnd)
{
start = middle + 1;
}
else if (textPos == lineStart)
{
frontRun = middle == 0 ? 0 : middle - 1;
backRun = middle;
return;
}
else if (textPos == lineEnd)
{
frontRun = middle;
backRun = middle == line->scriptItems.Count() - 1 ? middle : middle + 1;
return;
}
else
{
frontRun = middle;
backRun = middle;
return;
}
}
}
Rect UniscribeParagraph::GetCaretBoundsWithLine(vint caret, vint lineIndex, vint virtualLineIndex, bool frontSide) Rect UniscribeParagraph::GetCaretBoundsWithLine(vint caret, vint lineIndex, vint virtualLineIndex, bool frontSide)
{ {
Ptr<UniscribeLine> line = lines[lineIndex]; Ptr<UniscribeLine> line = lines[lineIndex];
@@ -12133,8 +12214,6 @@ UniscribeParagraph (Caret Helper)
for (vint i = virtualLine->firstRunIndex; i <= virtualLine->lastRunIndex; i++) for (vint i = virtualLine->firstRunIndex; i <= virtualLine->lastRunIndex; i++)
{ {
Ptr<UniscribeRun> run = line->scriptRuns[i]; Ptr<UniscribeRun> run = line->scriptRuns[i];
if(Ptr<UniscribeTextRun> textRun=run.Cast<UniscribeTextRun>())
{
vint firstBounds = i == virtualLine->firstRunIndex ? virtualLine->firstRunBoundsIndex : 0; vint firstBounds = i == virtualLine->firstRunIndex ? virtualLine->firstRunBoundsIndex : 0;
vint lastBounds = i == virtualLine->lastRunIndex ? virtualLine->lastRunBoundsIndex : run->fragmentBounds.Count() - 1; vint lastBounds = i == virtualLine->lastRunIndex ? virtualLine->lastRunBoundsIndex : run->fragmentBounds.Count() - 1;
@@ -12171,6 +12250,8 @@ UniscribeParagraph (Caret Helper)
} }
} }
else if (boundsStart < caret && caret < boundsStart + bounds.length) else if (boundsStart < caret && caret < boundsStart + bounds.length)
{
if (Ptr<UniscribeTextRun> textRun = run.Cast<UniscribeTextRun>())
{ {
vint accumulatedWidth = 0; vint accumulatedWidth = 0;
vint lastRunChar = bounds.startFromRun; vint lastRunChar = bounds.startFromRun;
@@ -12234,6 +12315,17 @@ UniscribeParagraph (Caret Helper)
} }
} }
} }
else
{
if (frontSide == !run->scriptItem->scriptItem.a.fRTL)
{
return Rect(bounds.bounds.x1, bounds.bounds.y1, bounds.bounds.x1, bounds.bounds.y2);
}
else
{
return Rect(bounds.bounds.x2, bounds.bounds.y1, bounds.bounds.x2, bounds.bounds.y2);
}
}
} }
} }
} }
@@ -12628,17 +12720,28 @@ UniscribeParagraph (Caret)
return textPos; return textPos;
} }
vint frontItem=-1; vint frontRun = -1;
vint backItem=-1; vint backRun = -1;
GetItemIndexFromTextPos(textPos, frontLine, frontItem, backItem); GetRunIndexFromTextPos(textPos, frontLine, frontRun, backRun);
if(frontItem==-1 || backItem==-1) return -1; if (frontRun == -1 || backRun == -1) return -1;
if(frontItem!=backItem) return textPos; if (frontRun != backRun)
{
return textPos;
}
Ptr<UniscribeItem> item=line->scriptItems[frontItem]; Ptr<UniscribeRun> run = line->scriptRuns[frontRun];
if (auto objectRun = run.Cast<UniscribeEmbeddedObjectRun>())
{
return frontSide
? line->startFromParagraph + run->startFromLine
: line->startFromParagraph + run->startFromLine + run->length
;
}
vint lineTextPos = textPos - line->startFromParagraph; vint lineTextPos = textPos - line->startFromParagraph;
if(lineTextPos==item->startFromLine) return textPos; if (lineTextPos == run->startFromLine) return textPos;
if(lineTextPos==item->startFromLine+item->length) return textPos; if (lineTextPos == run->startFromLine + run->length) return textPos;
auto item = run->scriptItem;
vint itemTextPos = lineTextPos - item->startFromLine; vint itemTextPos = lineTextPos - item->startFromLine;
if (item->charLogattrs[itemTextPos].fCharStop) return textPos; if (item->charLogattrs[itemTextPos].fCharStop) return textPos;
@@ -12646,7 +12749,10 @@ UniscribeParagraph (Caret)
{ {
for (vint i = itemTextPos - 1; i >= 0; i--) for (vint i = itemTextPos - 1; i >= 0; i--)
{ {
if(item->charLogattrs[i].fCharStop) return i+line->startFromParagraph+item->startFromLine; if (item->charLogattrs[i].fCharStop)
{
return i + line->startFromParagraph + item->startFromLine;
}
} }
return line->startFromParagraph + item->startFromLine; return line->startFromParagraph + item->startFromLine;
} }
@@ -12654,7 +12760,10 @@ UniscribeParagraph (Caret)
{ {
for (vint i = itemTextPos + 1; i < item->length; i++) for (vint i = itemTextPos + 1; i < item->length; i++)
{ {
if(item->charLogattrs[i].fCharStop) return i+line->startFromParagraph+item->startFromLine; if (item->charLogattrs[i].fCharStop)
{
return i + line->startFromParagraph + item->startFromLine;
}
} }
return line->startFromParagraph + item->startFromLine + item->length; return line->startFromParagraph + item->startFromLine + item->length;
} }
+7 -6
View File
@@ -1261,7 +1261,7 @@ UniscribeRun
virtual vint SumWidth(vint charStart, vint charLength)=0; virtual vint SumWidth(vint charStart, vint charLength)=0;
virtual vint SumHeight()=0; virtual vint SumHeight()=0;
virtual vint SumTextHeight()=0; virtual vint SumTextHeight()=0;
virtual void SearchForLineBreak(vint tempStart, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)=0; virtual void SearchForLineBreak(vint tempStart, bool wrapLine, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)=0;
virtual void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)=0; virtual void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)=0;
}; };
@@ -1289,7 +1289,7 @@ UniscribeTextRun
vint SumWidth(vint charStart, vint charLength)override; vint SumWidth(vint charStart, vint charLength)override;
vint SumHeight()override; vint SumHeight()override;
vint SumTextHeight()override; vint SumTextHeight()override;
void SearchForLineBreak(vint tempStart, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)override; void SearchForLineBreak(vint tempStart, bool wrapLine, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)override;
void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)override; void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)override;
}; };
@@ -1310,7 +1310,7 @@ UniscribeElementRun
vint SumWidth(vint charStart, vint charLength)override; vint SumWidth(vint charStart, vint charLength)override;
vint SumHeight()override; vint SumHeight()override;
vint SumTextHeight()override; vint SumTextHeight()override;
void SearchForLineBreak(vint tempStart, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)override; void SearchForLineBreak(vint tempStart, bool wrapLine, vint maxWidth, bool firstRun, vint& charLength, vint& charAdvances)override;
void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)override; void Render(IRendererCallback* callback, vint fragmentBoundsIndex, vint offsetX, vint offsetY, bool renderBackground)override;
}; };
@@ -1357,7 +1357,7 @@ UniscribeLine
void ClearUniscribeData(); void ClearUniscribeData();
bool BuildUniscribeData(WinDC* dc); bool BuildUniscribeData(WinDC* dc);
void Layout(vint availableWidth, Alignment alignment, vint top, vint& totalHeight); void Layout(bool wrapLine, vint availableWidth, Alignment alignment, vint top, vint& totalHeight);
void Render(UniscribeRun::IRendererCallback* callback, vint offsetX, vint offsetY, bool renderBackground); void Render(UniscribeRun::IRendererCallback* callback, vint offsetX, vint offsetY, bool renderBackground);
}; };
@@ -1376,7 +1376,7 @@ UniscribeParagraph
//***************************** Uniscribe Data //***************************** Uniscribe Data
List<Ptr<UniscribeLine>> lines; List<Ptr<UniscribeLine>> lines;
//***************************** Layout Data //***************************** Layout Data
bool wrapLine; bool lastWrapLine;
vint lastAvailableWidth; vint lastAvailableWidth;
Rect bounds; Rect bounds;
@@ -1385,7 +1385,7 @@ UniscribeParagraph
void ClearUniscribeData(); void ClearUniscribeData();
bool BuildUniscribeData(WinDC* dc); bool BuildUniscribeData(WinDC* dc);
void Layout(vint availableWidth, Alignment alignment); void Layout(bool wrapLine, vint availableWidth, Alignment alignment);
void Render(UniscribeRun::IRendererCallback* callback, bool renderBackground); void Render(UniscribeRun::IRendererCallback* callback, bool renderBackground);
void SearchFragment(vint start, vint length, vint& fs, vint& ss, vint& fe, vint& se); void SearchFragment(vint start, vint length, vint& fs, vint& ss, vint& fe, vint& se);
@@ -1403,6 +1403,7 @@ UniscribeParagraph
void GetLineIndexFromTextPos(vint textPos, vint& frontLine, vint& backLine); void GetLineIndexFromTextPos(vint textPos, vint& frontLine, vint& backLine);
void GetVirtualLineIndexFromTextPos(vint textPos, vint lineIndex, vint& frontLine, vint& backLine); void GetVirtualLineIndexFromTextPos(vint textPos, vint lineIndex, vint& frontLine, vint& backLine);
void GetItemIndexFromTextPos(vint textPos, vint lineIndex, vint& frontItem, vint& backItem); void GetItemIndexFromTextPos(vint textPos, vint lineIndex, vint& frontItem, vint& backItem);
void GetRunIndexFromTextPos(vint textPos, vint lineIndex, vint& frontRun, vint& backRun);
Rect GetCaretBoundsWithLine(vint caret, vint lineIndex, vint virtualLineIndex, bool frontSide); Rect GetCaretBoundsWithLine(vint caret, vint lineIndex, vint virtualLineIndex, bool frontSide);
vint GetCaretFromXWithTextRunBounds(vint x, vint lineIndex, vint runIndex, vint runBoundsIndex); vint GetCaretFromXWithTextRunBounds(vint x, vint lineIndex, vint runIndex, vint runBoundsIndex);
vint GetCaretFromXWithLine(vint x, vint lineIndex, vint virtualLineIndex); vint GetCaretFromXWithLine(vint x, vint lineIndex, vint virtualLineIndex);
+197 -90
View File
@@ -18697,15 +18697,6 @@ GuiDocumentCommonInterface
SetActiveHyperlink(nullptr); SetActiveHyperlink(nullptr);
} }
Point GuiDocumentCommonInterface::GetDocumentViewPosition()
{
return Point(0, 0);
}
void GuiDocumentCommonInterface::EnsureRectVisible(Rect bounds)
{
}
//================ callback //================ callback
void GuiDocumentCommonInterface::OnStartRender() void GuiDocumentCommonInterface::OnStartRender()
@@ -18743,11 +18734,120 @@ GuiDocumentCommonInterface
//================ basic //================ basic
void GuiDocumentCommonInterface::UserInput_FixForPlainText(Ptr<DocumentModel> model, vint beginParagraph, vint endParagraph)
{
if (beginParagraph > endParagraph) return;
RunRangeMap runRanges;
document_editor::GetRunRange(model->paragraphs[endParagraph].Obj(), runRanges);
TextPos begin(beginParagraph, 0);
TextPos end(endParagraph, runRanges[model->paragraphs[endParagraph].Obj()].end);
model->ConvertToPlainText(begin, end);
for (vint i = beginParagraph; i <= endParagraph; i++)
{
model->paragraphs[i]->alignment.Reset();
}
}
void GuiDocumentCommonInterface::UserInput_FixForSingleline(collections::List<WString>& paragraphTexts)
{
auto line = stream::GenerateToStream([&](stream::StreamWriter& writer)
{
for(auto [paragraph, index] : indexed(paragraphTexts))
{
if (index > 0 && config.spaceForFlattenedLineBreak)
{
writer.WriteChar(L' ');
}
writer.WriteString(paragraph);
}
});
paragraphTexts.Clear();
paragraphTexts.Add(line);
}
void GuiDocumentCommonInterface::UserInput_FixForSingleline(Ptr<DocumentModel> model)
{
auto firstParagraph = model->paragraphs[0];
for (auto paragraph : From(model->paragraphs).Skip(1))
{
if (config.spaceForFlattenedLineBreak)
{
auto textRun = Ptr(new DocumentTextRun);
textRun->text = WString::Unmanaged(L" ");
firstParagraph->runs.Add(textRun);
}
CopyFrom(firstParagraph->runs, paragraph->runs, true);
}
model->paragraphs.Clear();
model->paragraphs.Add(firstParagraph);
}
void GuiDocumentCommonInterface::UserInput_FixForNonParagraph(WString& text)
{
text = stream::GenerateToStream([&](stream::StreamWriter& writer)
{
for (vint j = 0; j < text.Length(); j++)
{
if (text[j] == L'\n')
{
if (config.spaceForFlattenedLineBreak)
{
writer.WriteChar(L' ');
}
}
else if (text[j] != L'\r')
{
writer.WriteChar(text[j]);
}
}
});
}
void GuiDocumentCommonInterface::UserInput_FixForNonParagraph(Ptr<DocumentParagraphRun> paragraph)
{
List<Ptr<DocumentContainerRun>> containers;
containers.Add(paragraph);
for (vint i = 0; i < containers.Count(); i++)
{
auto container = containers[i];
for (auto run : container->runs)
{
if (auto subContainer = run.Cast<DocumentContainerRun>())
{
containers.Add(subContainer);
}
else if (auto textRun = run.Cast<DocumentTextRun>())
{
UserInput_FixForNonParagraph(textRun->text);
}
}
}
}
WString GuiDocumentCommonInterface::UserInput_ConvertDocumentToText(Ptr<DocumentModel> model) WString GuiDocumentCommonInterface::UserInput_ConvertDocumentToText(Ptr<DocumentModel> model)
{ {
return model->GetTextForReading(WString::Unmanaged(config.doubleLineBreaksBetweenParagraph ? L"\r\n\r\n" : L"\r\n")); return model->GetTextForReading(WString::Unmanaged(config.doubleLineBreaksBetweenParagraph ? L"\r\n\r\n" : L"\r\n"));
} }
void GuiDocumentCommonInterface::UserInput_FormatText(collections::List<WString>& paragraphTexts)
{
if (config.paragraphMode != GuiDocumentParagraphMode::Paragraph)
{
for (vint i = 0; i < paragraphTexts.Count(); i++)
{
UserInput_FixForNonParagraph(paragraphTexts[i]);
}
}
if (config.paragraphMode == GuiDocumentParagraphMode::Singleline)
{
UserInput_FixForSingleline(paragraphTexts);
}
}
void GuiDocumentCommonInterface::UserInput_FormatText(const WString& text, collections::List<WString>& paragraphTexts) void GuiDocumentCommonInterface::UserInput_FormatText(const WString& text, collections::List<WString>& paragraphTexts)
{ {
stream::StringReader reader(text); stream::StringReader reader(text);
@@ -18800,22 +18900,9 @@ GuiDocumentCommonInterface
{ {
paragraphTexts.Add(paragraph); paragraphTexts.Add(paragraph);
} }
if (config.paragraphMode == GuiDocumentParagraphMode::Singleline) if (config.paragraphMode == GuiDocumentParagraphMode::Singleline)
{ {
auto line = stream::GenerateToStream([&](stream::StreamWriter& writer) UserInput_FixForSingleline(paragraphTexts);
{
for(auto [paragraph, index] : indexed(paragraphTexts))
{
if (index > 0 && config.spaceForFlattenedLineBreak)
{
writer.WriteChar(L' ');
}
writer.WriteString(paragraph);
}
});
paragraphTexts.Clear();
paragraphTexts.Add(line);
} }
} }
@@ -18824,21 +18911,7 @@ GuiDocumentCommonInterface
if (!model) return; if (!model) return;
if (config.pasteAsPlainText) if (config.pasteAsPlainText)
{ {
if (model->paragraphs.Count() > 0) UserInput_FixForPlainText(model, 0, model->paragraphs.Count() - 1);
{
RunRangeMap runRanges;
vint lastParagraphIndex = model->paragraphs.Count() - 1;
document_editor::GetRunRange(model->paragraphs[lastParagraphIndex].Obj(), runRanges);
TextPos begin(0, 0);
TextPos end(lastParagraphIndex, runRanges[model->paragraphs[lastParagraphIndex].Obj()].end);
model->ConvertToPlainText(begin, end);
for (auto paragraph : model->paragraphs)
{
paragraph->alignment.Reset();
}
}
if (baselineDocument) if (baselineDocument)
{ {
@@ -18857,60 +18930,14 @@ GuiDocumentCommonInterface
if (config.paragraphMode != GuiDocumentParagraphMode::Paragraph) if (config.paragraphMode != GuiDocumentParagraphMode::Paragraph)
{ {
List<Ptr<DocumentContainerRun>> containers;
for (auto paragraph : model->paragraphs) for (auto paragraph : model->paragraphs)
{ {
containers.Add(paragraph); UserInput_FixForNonParagraph(paragraph);
}
for (vint i = 0; i < containers.Count(); i++)
{
auto container = containers[i];
for (auto run : container->runs)
{
if (auto subContainer = run.Cast<DocumentContainerRun>())
{
containers.Add(subContainer);
}
else if (auto textRun = run.Cast<DocumentTextRun>())
{
textRun->text = stream::GenerateToStream([&](stream::StreamWriter& writer)
{
for (vint j = 0; j < textRun->text.Length(); j++)
{
if (textRun->text[j] == L'\n')
{
if (config.spaceForFlattenedLineBreak)
{
writer.WriteChar(L' ');
} }
} }
else if (textRun->text[j] != L'\r')
{
writer.WriteChar(textRun->text[j]);
}
}
});
}
}
}
}
if (config.paragraphMode == GuiDocumentParagraphMode::Singleline) if (config.paragraphMode == GuiDocumentParagraphMode::Singleline)
{ {
auto firstParagraph = model->paragraphs[0]; UserInput_FixForSingleline(model);
for(auto paragraph:From(model->paragraphs).Skip(1))
{
if (config.spaceForFlattenedLineBreak)
{
auto textRun = Ptr(new DocumentTextRun);
textRun->text = WString::Unmanaged(L" ");
firstParagraph->runs.Add(textRun);
}
CopyFrom(firstParagraph->runs, paragraph->runs, true);
}
model->paragraphs.Clear();
model->paragraphs.Add(firstParagraph);
} }
} }
@@ -19027,11 +19054,44 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText) void GuiDocumentCommonInterface::NotifyParagraphUpdated(vint index, vint oldCount, vint newCount, bool updatedText)
{ {
#define ERROR_MESSAGE_PREFIX L"vl::presentation::controls::GuiDocumentCommonInterface::NotifyParagraphUpdated(vint, vint, vint, bool)#"
auto model = documentElement->GetDocument();
if (config.paragraphMode == GuiDocumentParagraphMode::Singleline)
{
CHECK_ERROR(model->paragraphs.Count() <= 1, ERROR_MESSAGE_PREFIX L"In Singleline mode, there should be no more than 1 paragraphs in the document.");
}
if (0 <= index && index + newCount <= model->paragraphs.Count())
{
if (config.pasteAsPlainText && updatedText)
{
UserInput_FixForPlainText(model, index, index + newCount - 1);
if (baselineDocument)
{
CopyFrom(model->styles, baselineDocument->styles);
}
else
{
model->styles.Clear();
}
}
if (config.paragraphMode != GuiDocumentParagraphMode::Paragraph)
{
for (vint i = index; i < index + newCount; i++)
{
UserInput_FixForNonParagraph(model->paragraphs[i]);
}
}
documentElement->NotifyParagraphUpdated(index, oldCount, newCount, updatedText); documentElement->NotifyParagraphUpdated(index, oldCount, newCount, updatedText);
} }
#undef ERROR_MESSAGE_PREFIX
}
void GuiDocumentCommonInterface::EditRun(TextPos begin, TextPos end, Ptr<DocumentModel> model, bool copy) void GuiDocumentCommonInterface::EditRun(TextPos begin, TextPos end, Ptr<DocumentModel> model, bool copy)
{ {
UserInput_FormatDocument(model);
EditTextInternal(begin, end, [=, this](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) EditTextInternal(begin, end, [=, this](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength)
{ {
documentElement->EditRun(begin, end, model, copy); documentElement->EditRun(begin, end, model, copy);
@@ -19044,14 +19104,26 @@ GuiDocumentCommonInterface
{ {
EditTextInternal(begin, end, [=, this, &text](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) EditTextInternal(begin, end, [=, this, &text](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength)
{ {
documentElement->EditText(begin, end, frontSide, text); Array<WString> updatedText;
paragraphCount=text.Count(); bool useUpdatedText = config.paragraphMode != GuiDocumentParagraphMode::Paragraph;
lastParagraphLength=paragraphCount==0?0:text[paragraphCount-1].Length(); if (useUpdatedText)
{
List<WString> paragraphTexts;
CopyFrom(paragraphTexts, text);
UserInput_FormatText(paragraphTexts);
CopyFrom(updatedText, paragraphTexts);
}
const Array<WString>& textToUse = useUpdatedText ? updatedText : text;
documentElement->EditText(begin, end, frontSide, textToUse);
paragraphCount = textToUse.Count();
lastParagraphLength = paragraphCount == 0 ? 0 : textToUse[paragraphCount - 1].Length();
}); });
} }
void GuiDocumentCommonInterface::EditStyle(TextPos begin, TextPos end, Ptr<DocumentStyleProperties> style) void GuiDocumentCommonInterface::EditStyle(TextPos begin, TextPos end, Ptr<DocumentStyleProperties> style)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end) EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end)
{ {
documentElement->EditStyle(begin, end, style); documentElement->EditStyle(begin, end, style);
@@ -19060,6 +19132,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::EditImage(TextPos begin, TextPos end, Ptr<GuiImageData> image) void GuiDocumentCommonInterface::EditImage(TextPos begin, TextPos end, Ptr<GuiImageData> image)
{ {
if (config.pasteAsPlainText) return;
EditTextInternal(begin, end, [=, this](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength) EditTextInternal(begin, end, [=, this](TextPos begin, TextPos end, vint& paragraphCount, vint& lastParagraphLength)
{ {
documentElement->EditImage(begin, end, image); documentElement->EditImage(begin, end, image);
@@ -19070,6 +19143,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName) void GuiDocumentCommonInterface::EditHyperlink(vint paragraphIndex, vint begin, vint end, const WString& reference, const WString& normalStyleName, const WString& activeStyleName)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=, this](TextPos begin, TextPos end) EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=, this](TextPos begin, TextPos end)
{ {
documentElement->EditHyperlink(begin.row, begin.column, end.column, reference, normalStyleName, activeStyleName); documentElement->EditHyperlink(begin.row, begin.column, end.column, reference, normalStyleName, activeStyleName);
@@ -19078,6 +19152,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::RemoveHyperlink(vint paragraphIndex, vint begin, vint end) void GuiDocumentCommonInterface::RemoveHyperlink(vint paragraphIndex, vint begin, vint end)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=, this](TextPos begin, TextPos end) EditStyleInternal(TextPos(paragraphIndex, begin), TextPos(paragraphIndex, end), [=, this](TextPos begin, TextPos end)
{ {
documentElement->RemoveHyperlink(begin.row, begin.column, end.column); documentElement->RemoveHyperlink(begin.row, begin.column, end.column);
@@ -19086,6 +19161,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::EditStyleName(TextPos begin, TextPos end, const WString& styleName) void GuiDocumentCommonInterface::EditStyleName(TextPos begin, TextPos end, const WString& styleName)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end) EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end)
{ {
documentElement->EditStyleName(begin, end, styleName); documentElement->EditStyleName(begin, end, styleName);
@@ -19094,6 +19170,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::RemoveStyleName(TextPos begin, TextPos end) void GuiDocumentCommonInterface::RemoveStyleName(TextPos begin, TextPos end)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end) EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end)
{ {
documentElement->RemoveStyleName(begin, end); documentElement->RemoveStyleName(begin, end);
@@ -19102,6 +19179,7 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::RenameStyle(const WString& oldStyleName, const WString& newStyleName) void GuiDocumentCommonInterface::RenameStyle(const WString& oldStyleName, const WString& newStyleName)
{ {
if (config.pasteAsPlainText) return;
documentElement->RenameStyle(oldStyleName, newStyleName); documentElement->RenameStyle(oldStyleName, newStyleName);
// submit redo-undo // submit redo-undo
@@ -19113,12 +19191,21 @@ GuiDocumentCommonInterface
void GuiDocumentCommonInterface::ClearStyle(TextPos begin, TextPos end) void GuiDocumentCommonInterface::ClearStyle(TextPos begin, TextPos end)
{ {
if (config.pasteAsPlainText) return;
EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end) EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end)
{ {
documentElement->ClearStyle(begin, end); documentElement->ClearStyle(begin, end);
}); });
} }
void GuiDocumentCommonInterface::ConvertToPlainText(TextPos begin, TextPos end)
{
EditStyleInternal(begin, end, [=, this](TextPos begin, TextPos end)
{
documentElement->ConvertToPlainText(begin, end);
});
}
Ptr<DocumentStyleProperties> GuiDocumentCommonInterface::SummarizeStyle(TextPos begin, TextPos end) Ptr<DocumentStyleProperties> GuiDocumentCommonInterface::SummarizeStyle(TextPos begin, TextPos end)
{ {
if (begin>end) if (begin>end)
@@ -19472,7 +19559,8 @@ GuiDocumentViewer
Point GuiDocumentViewer::GetDocumentViewPosition() Point GuiDocumentViewer::GetDocumentViewPosition()
{ {
return GetViewBounds().LeftTop(); // the document does not move in containerComposition
return { 0,0 };
} }
void GuiDocumentViewer::EnsureRectVisible(Rect bounds) void GuiDocumentViewer::EnsureRectVisible(Rect bounds)
@@ -33854,6 +33942,25 @@ GuiDocumentElement
} }
} }
void GuiDocumentElement::ConvertToPlainText(TextPos begin, TextPos end)
{
if (auto elementRenderer = renderer.Cast<GuiDocumentElementRenderer>())
{
if (begin > end)
{
TextPos temp = begin;
begin = end;
end = temp;
}
if (document->ConvertToPlainText(begin, end))
{
elementRenderer->NotifyParagraphUpdated(begin.row, end.row - begin.row + 1, end.row - begin.row + 1, false);
}
InvokeOnCompositionStateChanged();
}
}
Ptr<DocumentStyleProperties> GuiDocumentElement::SummarizeStyle(TextPos begin, TextPos end) Ptr<DocumentStyleProperties> GuiDocumentElement::SummarizeStyle(TextPos begin, TextPos end)
{ {
if (auto elementRenderer = renderer.Cast<GuiDocumentElementRenderer>()) if (auto elementRenderer = renderer.Cast<GuiDocumentElementRenderer>())
+17 -2
View File
@@ -13113,6 +13113,10 @@ Rich Content Document (element)
/// <param name="begin">The begin position of the range.</param> /// <param name="begin">The begin position of the range.</param>
/// <param name="end">The end position of the range.</param> /// <param name="end">The end position of the range.</param>
void ClearStyle(TextPos begin, TextPos end); void ClearStyle(TextPos begin, TextPos end);
/// <summary>Clear all styles and remove non-text contents in a specified range.</summary>
/// <param name="begin">The begin position of the range.</param>
/// <param name="end">The end position of the range.</param>
void ConvertToPlainText(TextPos begin, TextPos end);
/// <summary>Summarize the text style in a specified range.</summary> /// <summary>Summarize the text style in a specified range.</summary>
/// <returns>The text style summary.</returns> /// <returns>The text style summary.</returns>
/// <param name="begin">The begin position of the range.</param> /// <param name="begin">The begin position of the range.</param>
@@ -16851,8 +16855,8 @@ GuiDocumentCommonInterface
void OnMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments); void OnMouseUp(compositions::GuiGraphicsComposition* sender, compositions::GuiMouseEventArgs& arguments);
void OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments); void OnMouseLeave(compositions::GuiGraphicsComposition* sender, compositions::GuiEventArgs& arguments);
virtual Point GetDocumentViewPosition(); virtual Point GetDocumentViewPosition() = 0;
virtual void EnsureRectVisible(Rect bounds); virtual void EnsureRectVisible(Rect bounds) = 0;
//================ callback //================ callback
@@ -16862,7 +16866,14 @@ GuiDocumentCommonInterface
protected: protected:
void UserInput_FixForPlainText(Ptr<DocumentModel> model, vint beginParagraph, vint endParagraph);
void UserInput_FixForSingleline(collections::List<WString>& paragraphTexts);
void UserInput_FixForSingleline(Ptr<DocumentModel> model);
void UserInput_FixForNonParagraph(WString& text);
void UserInput_FixForNonParagraph(Ptr<DocumentParagraphRun> paragraph);
WString UserInput_ConvertDocumentToText(Ptr<DocumentModel> model); WString UserInput_ConvertDocumentToText(Ptr<DocumentModel> model);
void UserInput_FormatText(collections::List<WString>& paragraphTexts);
void UserInput_FormatText(const WString& text, collections::List<WString>& paragraphTexts); void UserInput_FormatText(const WString& text, collections::List<WString>& paragraphTexts);
void UserInput_FormatDocument(Ptr<DocumentModel> model); void UserInput_FormatDocument(Ptr<DocumentModel> model);
@@ -16993,6 +17004,10 @@ GuiDocumentCommonInterface
/// <param name="begin">The begin position of the range.</param> /// <param name="begin">The begin position of the range.</param>
/// <param name="end">The end position of the range.</param> /// <param name="end">The end position of the range.</param>
void ClearStyle(TextPos begin, TextPos end); void ClearStyle(TextPos begin, TextPos end);
/// <summary>Clear all styles and remove non-text contents in a specified range.</summary>
/// <param name="begin">The begin position of the range.</param>
/// <param name="end">The end position of the range.</param>
void ConvertToPlainText(TextPos begin, TextPos end);
/// <summary>Summarize the text style in a specified range.</summary> /// <summary>Summarize the text style in a specified range.</summary>
/// <returns>The text style summary.</returns> /// <returns>The text style summary.</returns>
/// <param name="begin">The begin position of the range.</param> /// <param name="begin">The begin position of the range.</param>
+2
View File
@@ -2988,6 +2988,7 @@ Type Declaration (Class)
CLASS_MEMBER_METHOD(RemoveStyleName, {L"begin" _ L"end" _ L"image"}) CLASS_MEMBER_METHOD(RemoveStyleName, {L"begin" _ L"end" _ L"image"})
CLASS_MEMBER_METHOD(RenameStyle, {L"oldStyleName" _ L"newStyleName"}) CLASS_MEMBER_METHOD(RenameStyle, {L"oldStyleName" _ L"newStyleName"})
CLASS_MEMBER_METHOD(ClearStyle, {L"begin" _ L"end"}) CLASS_MEMBER_METHOD(ClearStyle, {L"begin" _ L"end"})
CLASS_MEMBER_METHOD(ConvertToPlainText, { L"begin" _ L"end" })
CLASS_MEMBER_METHOD(SummarizeStyle, {L"begin" _ L"end"}) CLASS_MEMBER_METHOD(SummarizeStyle, {L"begin" _ L"end"})
CLASS_MEMBER_METHOD(SummarizeStyleName, { L"begin" _ L"end" }) CLASS_MEMBER_METHOD(SummarizeStyleName, { L"begin" _ L"end" })
CLASS_MEMBER_METHOD(SetParagraphAlignments, { L"begin" _ L"end" _ L"alignments" }) CLASS_MEMBER_METHOD(SetParagraphAlignments, { L"begin" _ L"end" _ L"alignments" })
@@ -3471,6 +3472,7 @@ Type Declaration (Class)
CLASS_MEMBER_METHOD(RemoveStyleName, {L"begin" _ L"end" _ L"image"}) CLASS_MEMBER_METHOD(RemoveStyleName, {L"begin" _ L"end" _ L"image"})
CLASS_MEMBER_METHOD(RenameStyle, {L"oldStyleName" _ L"newStyleName"}) CLASS_MEMBER_METHOD(RenameStyle, {L"oldStyleName" _ L"newStyleName"})
CLASS_MEMBER_METHOD(ClearStyle, {L"begin" _ L"end"}) CLASS_MEMBER_METHOD(ClearStyle, {L"begin" _ L"end"})
CLASS_MEMBER_METHOD(ConvertToPlainText, { L"begin" _ L"end" })
CLASS_MEMBER_METHOD(SummarizeStyle, {L"begin" _ L"end"}) CLASS_MEMBER_METHOD(SummarizeStyle, {L"begin" _ L"end"})
CLASS_MEMBER_METHOD(SummarizeStyleName, { L"begin" _ L"end" }) CLASS_MEMBER_METHOD(SummarizeStyleName, { L"begin" _ L"end" })
CLASS_MEMBER_METHOD(SetParagraphAlignment, {L"begin" _ L"end" _ L"alignments"}) CLASS_MEMBER_METHOD(SetParagraphAlignment, {L"begin" _ L"end" _ L"alignments"})
+1
View File
@@ -1621,6 +1621,7 @@ UnitTest
case FailureMode::Copilot: case FailureMode::Copilot:
PrintMessage(L"Failures cause immediate exit.", MessageKind::Info); PrintMessage(L"Failures cause immediate exit.", MessageKind::Info);
break; break;
default:;
} }
auto current = testHead; auto current = testHead;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.