1919 readonly property string selectedText: root .text .substring (
2020 root .selectionStart , root .selectionEnd )
2121
22- readonly property real margin: root .strokeSize / 2
22+ readonly property int margin: Math . ceil ( root .strokeSize / 2.0 )
2323
2424 signal clicked ()
2525 signal doubleClicked ()
@@ -142,131 +142,107 @@ Item {
142142 id: repeaterShape
143143
144144 model: root .makeTextModel (root .text )
145- delegate: Shape {
146- id: shape
145+ delegate: Item {
146+ id: delegateItem
147147 anchors .horizontalCenter : parent .horizontalCenter
148- antialiasing: true
149- layer .enabled : true
150- layer .samples : 4
151- layer .smooth : true
152-
153- // This draws the background
154- ShapePath {
155- fillColor: root .background
156- strokeColor: " transparent"
157- strokeWidth: 0
158-
159- PathRectangle {
160- x: 0
161- y: 0
162- width: shape .width
163- height: shape .height
164- }
165- }
166-
167- // This draws the text stroke
168- ShapePath {
169- strokeWidth: root .strokeSize
170- strokeColor: root .stroke
171- fillColor: " transparent"
172- fillRule: ShapePath .WindingFill
173- joinStyle: ShapePath .RoundJoin
174- capStyle: ShapePath .RoundCap
175-
176- PathText {
177- id: pathTextStroke
178- x: root .margin
179- y: root .margin
180- font: root .font
181- text: modelData .text
182- }
148+ width: Math .max (shape .width , textMetrics .tightBoundingRect .width )
149+ height: Math .max (shape .height , textMetrics .tightBoundingRect .height )
150+ clip: true
151+
152+ TextMetrics {
153+ id: textMetrics
154+ font: textEdit .font
155+ text: textEdit .text
156+ renderType: textEdit .renderType
183157 }
184158
185- // This draws the selection if there is one
186- ShapePath {
187- id: selectionPath
188-
189- strokeWidth: 0
190- fillColor: MementoPalette .highlight
191-
192- readonly property rect area: selectionPath .getSelectionBounds (
193- root .selectionStart , root .selectionEnd )
194-
195- /**
196- * Returns a rectangle of the area to draw.
197- * @param start The starting index in root.text (inclusive)
198- * @param end The ending index in root.text (exclusive)
199- * @return A rect representing the area to draw on this line
200- */
201- function getSelectionBounds (start , end ) {
202- const minIndex = modelData .offset ;
203- const maxIndex = minIndex + modelData .text .length ;
204-
205- const overlap = minIndex <= end && start <= maxIndex;
206- if (! overlap)
207- {
208- return Qt .rect (0 , 0 , 0 , 0 );
159+ Shape {
160+ id: shape
161+ antialiasing: true
162+ layer .enabled : true
163+ layer .samples : 4
164+ layer .smooth : true
165+
166+ // This draws the background
167+ ShapePath {
168+ fillColor: root .background
169+ strokeColor: " transparent"
170+ strokeWidth: 0
171+
172+ PathRectangle {
173+ x: 0
174+ y: 0
175+ width: shape .width
176+ height: shape .height
209177 }
210-
211- start = Math .max (start - minIndex, 0 );
212- end = Math .min (end - minIndex, modelData .text .length );
213- if (start >= end)
214- {
215- return Qt .rect (0 , 0 , 0 , 0 );
216- }
217-
218- const startRect = textEdit .positionToRectangle (start);
219- const endRect = textEdit .positionToRectangle (end);
220-
221- const startX = root .margin + startRect .x ;
222- const endX = root .margin + endRect .x + endRect .width ;
223- const startY = 0
224- const endY = shape .height ;
225- return Qt .rect (startX, startY, endX - startX, endY - startY);
226- }
227-
228- PathRectangle {
229- x: selectionPath .area .x
230- y: selectionPath .area .y
231- width: selectionPath .area .width
232- height: selectionPath .area .height
233178 }
234- }
235-
236- // This fills in the text on top of the stroke layer
237- ShapePath {
238- strokeWidth: 0
239- fillColor: root .color
240- fillRule: ShapePath .WindingFill
241179
242- PathText {
243- id: pathTextFill
244- x: root .margin
245- y: root .margin
246- font: root .font
247- text: modelData .text
180+ // This draws the text stroke
181+ ShapePath {
182+ strokeWidth: root .strokeSize
183+ strokeColor: root .stroke
184+ fillColor: " transparent"
185+ fillRule: ShapePath .WindingFill
186+ joinStyle: ShapePath .RoundJoin
187+ capStyle: ShapePath .RoundCap
188+
189+ PathText {
190+ id: pathTextStroke
191+ x: root .margin
192+ y: root .margin
193+ font: root .font
194+ text: modelData .text
195+ }
248196 }
249197 }
250198
251- // This text edit is only used for hit testing, it is not shown
252199 TextEdit {
253200 id: textEdit
254201
255202 x: root .margin
256203 y: root .margin - (textMetrics .tightBoundingRect .y - textMetrics .boundingRect .y )
257204 font: root .font
258- color: " transparent "
205+ color: root . color
259206 readOnly: true
260207 selectByMouse: false
261208 selectByKeyboard: false
209+ selectionColor: MementoPalette .highlight
262210 wrapMode: TextEdit .NoWrap
263211 text: modelData .text
264212
265- TextMetrics {
266- id: textMetrics
267- font: textEdit .font
268- text: textEdit .text
269- renderType: textEdit .renderType
213+ Connections {
214+ target: root
215+ function onSelectionStartChanged () {
216+ textEdit .updateSelection ();
217+ }
218+ }
219+ Connections {
220+ target: root
221+ function onSelectionEndChanged () {
222+ textEdit .updateSelection ();
223+ }
224+ }
225+
226+ /**
227+ * Update the selection with the new selectionStart and selectionEnd values.
228+ */
229+ function updateSelection () {
230+ if (root .selectionStart < 0 || root .selectionEnd < 0 )
231+ {
232+ textEdit .deselect ();
233+ return ;
234+ }
235+
236+ let start = root .selectionStart - modelData .offset ;
237+ start = Math .max (start, 0 );
238+ let end = root .selectionEnd - modelData .offset ;
239+ end = Math .min (end, textEdit .text .length );
240+ if (start >= end)
241+ {
242+ textEdit .deselect ();
243+ return ;
244+ }
245+ textEdit .select (start, end);
270246 }
271247
272248 /**
@@ -291,7 +267,7 @@ Item {
291267 cursorShape: root .cursorShape
292268 onPositionChanged : function (mouse ) {
293269 let x = mouse .x - root .margin ;
294- if (x >= 0 )
270+ if (x >= 0 && x < textEdit . width )
295271 {
296272 let index = textEdit .getCharacterIndexAt (x);
297273 root .hoverIndex = index;
0 commit comments