From 5a1a6a3bacf02b824d40ed47e8e493452fdbb47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 7 Dec 2013 00:16:17 +0100 Subject: [PATCH] TextDocumentView: Preparations for selection support Added methods to deal with caret offset and selection anchor, constructing a BShape enclosing the selection range and drawing it. Added mouse event stubs. --- .../haiku-depot/textview/TextDocumentView.cpp | 165 +++++++++++++++++- .../haiku-depot/textview/TextDocumentView.h | 18 ++ 2 files changed, 182 insertions(+), 1 deletion(-) diff --git a/src/apps/haiku-depot/textview/TextDocumentView.cpp b/src/apps/haiku-depot/textview/TextDocumentView.cpp index 9da75b56e0..2ac29ef9c4 100644 --- a/src/apps/haiku-depot/textview/TextDocumentView.cpp +++ b/src/apps/haiku-depot/textview/TextDocumentView.cpp @@ -8,6 +8,7 @@ #include #include +#include TextDocumentView::TextDocumentView(const char* name) @@ -16,7 +17,14 @@ TextDocumentView::TextDocumentView(const char* name) fInsetLeft(0.0f), fInsetTop(0.0f), fInsetRight(0.0f), - fInsetBottom(0.0f) + fInsetBottom(0.0f), + + fSelectionAnchorOffset(0), + fCaretOffset(0), + fCaretAnchorX(0.0f), + fShowCaret(false), + + fMouseDown(false) { fTextDocumentLayout.SetWidth(_TextLayoutWidth(Bounds().Width())); @@ -37,6 +45,28 @@ TextDocumentView::Draw(BRect updateRect) fTextDocumentLayout.SetWidth(_TextLayoutWidth(Bounds().Width())); fTextDocumentLayout.Draw(this, BPoint(fInsetLeft, fInsetTop), updateRect); + + if (fSelectionAnchorOffset == fCaretOffset) + return; + + int32 start; + int32 end; + if (fSelectionAnchorOffset <= fCaretOffset) { + start = fSelectionAnchorOffset; + end = fCaretOffset; + } else { + start = fCaretOffset; + end = fSelectionAnchorOffset; + } + + BShape shape; + _GetSelectionShape(shape, start, end); + + SetHighColor(60, 40, 0); + SetDrawingMode(B_OP_SUBTRACT); + + MovePenTo(fInsetLeft, fInsetTop); + FillShape(&shape); } @@ -55,6 +85,25 @@ TextDocumentView::FrameResized(float width, float height) } +void +TextDocumentView::MouseDown(BPoint where) +{ +} + + +void +TextDocumentView::MouseUp(BPoint where) +{ +} + + +void +TextDocumentView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ +} + + BSize TextDocumentView::MinSize() { @@ -106,6 +155,11 @@ TextDocumentView::SetTextDocument(const TextDocumentRef& document) { fTextDocument = document; fTextDocumentLayout.SetTextDocument(fTextDocument); + + fSelectionAnchorOffset = 0; + fCaretOffset = 0; + fCaretAnchorX = 0.0f; + InvalidateLayout(); Invalidate(); _UpdateScrollBars(); @@ -192,3 +246,112 @@ TextDocumentView::_UpdateScrollBars() } } + +void +TextDocumentView::_SetCaretOffset(int32 offset, bool updateAnchor, + bool lockSelectionAnchor) +{ + if (offset < 0) + offset = 0; + int32 length = fTextDocument->Length(); + if (offset > length) + offset = length; + + if (offset == fCaretOffset && (lockSelectionAnchor + || offset == fSelectionAnchorOffset)) { + return; + } + + if (!lockSelectionAnchor) + fSelectionAnchorOffset = offset; + + fCaretOffset = offset; + fShowCaret = true; + + if (updateAnchor) { + float x1; + float y1; + float x2; + float y2; + + fTextDocumentLayout.GetTextBounds(fCaretOffset, x1, y1, x2, y2); + fCaretAnchorX = x1; + } + + Invalidate(); +} + + +// _GetSelectionShape +void +TextDocumentView::_GetSelectionShape(BShape& shape, + int32 start, int32 end) +{ + float startX1; + float startY1; + float startX2; + float startY2; + fTextDocumentLayout.GetTextBounds(start, startX1, startY1, startX2, + startY2); + + float endX1; + float endY1; + float endX2; + float endY2; + fTextDocumentLayout.GetTextBounds(end, endX1, endY1, endX2, endY2); + + int32 startLineIndex = fTextDocumentLayout.LineIndexForOffset(start); + int32 endLineIndex = fTextDocumentLayout.LineIndexForOffset(end); + + if (startLineIndex == endLineIndex) { + // Selection on one line + BPoint lt(startX1, startY1); + BPoint rt(endX1, endY1); + BPoint rb(endX1, endY2); + BPoint lb(startX1, startY2); + + shape.MoveTo(lt); + shape.LineTo(rt); + shape.LineTo(rb); + shape.LineTo(lb); + shape.Close(); + } else if (startLineIndex == endLineIndex - 1 && endX1 <= startX1) { + // Selection on two lines, with gap: + // --------- + // ------### + // ##------- + // --------- + BPoint lt(startX1, startY1); + BPoint rt(fTextDocumentLayout.Width(), startY1); + BPoint rb(fTextDocumentLayout.Width(), startY2); + BPoint lb(startX1, startY2); + + shape.MoveTo(lt); + shape.LineTo(rt); + shape.LineTo(rb); + shape.LineTo(lb); + shape.Close(); + + lt = BPoint(0, endY1); + rt = BPoint(endX1, endY1); + rb = BPoint(endX1, endY2); + lb = BPoint(0, endY2); + + shape.MoveTo(lt); + shape.LineTo(rt); + shape.LineTo(rb); + shape.LineTo(lb); + shape.Close(); + } else { + // Selection over multiple lines + shape.MoveTo(BPoint(startX1, startY1)); + shape.LineTo(BPoint(fTextDocumentLayout.Width(), startY1)); + shape.LineTo(BPoint(fTextDocumentLayout.Width(), endY1)); + shape.LineTo(BPoint(endX1, endY1)); + shape.LineTo(BPoint(endX1, endY2)); + shape.LineTo(BPoint(0, endY2)); + shape.LineTo(BPoint(0, startY2)); + shape.LineTo(BPoint(startX1, startY2)); + shape.Close(); + } +} diff --git a/src/apps/haiku-depot/textview/TextDocumentView.h b/src/apps/haiku-depot/textview/TextDocumentView.h index f8c69c04b2..0d5bf6e12b 100644 --- a/src/apps/haiku-depot/textview/TextDocumentView.h +++ b/src/apps/haiku-depot/textview/TextDocumentView.h @@ -22,6 +22,11 @@ public: virtual void AttachedToWindow(); virtual void FrameResized(float width, float height); + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + virtual BSize MinSize(); virtual BSize MaxSize(); virtual BSize PreferredSize(); @@ -42,6 +47,12 @@ private: void _UpdateScrollBars(); + void _SetCaretOffset(int32 offset, bool updateAnchor, + bool lockSelectionAnchor); + + void _GetSelectionShape(BShape& shape, + int32 start, int32 end); + private: TextDocumentRef fTextDocument; TextDocumentLayout fTextDocumentLayout; @@ -50,6 +61,13 @@ private: float fInsetTop; float fInsetRight; float fInsetBottom; + + int32 fSelectionAnchorOffset; + int32 fCaretOffset; + float fCaretAnchorX; + bool fShowCaret; + + bool fMouseDown; }; #endif // TEXT_DOCUMENT_VIEW_H