Finalize text selection handles.

Signed-off-by: Gökay Şatır <gokaysatir@collabora.com>
Change-Id: I3d7a9a01903455c2b4c9303a27dd37702650cbb3
pull/9012/head
Gökay Şatır 2024-04-30 18:43:55 +03:00 committed by Gökay ŞATIR
parent 8a0843764b
commit 932b99cf12
16 changed files with 125 additions and 103 deletions

View File

@ -9,7 +9,7 @@
margin-left: 1px !important;
transform: translateY(-12px);
}
#tb_formulabar_item_formula .inputbar_selection_handles .leaflet-selection-marker-start{
#tb_formulabar_item_formula .inputbar_selection_handles .text-selection-handle-start{
margin-left: -20px !important;
}

View File

@ -1,16 +1,12 @@
.leaflet-selection-marker-start {
.text-selection-handle-start {
position: absolute;
margin-left: -30px;
margin-top: -2px;
width: 30px;
height: 44px;
background-image: url('images/handle_start.svg');
}
.leaflet-selection-marker-end {
.text-selection-handle-end {
position: absolute;
margin-left: 0;
margin-top: -2px;
width: 30px;
height: 44px;
background-image: url('images/handle_end.svg');

View File

@ -187,8 +187,8 @@ L.Control.LokDialog = L.Control.extend({
},
_isSelectionHandle: function(el) {
return L.DomUtil.hasClass(el, 'leaflet-selection-marker-start') ||
L.DomUtil.hasClass(el, 'leaflet-selection-marker-end');
return L.DomUtil.hasClass(el, 'text-selection-handle-start') ||
L.DomUtil.hasClass(el, 'text-selection-handle-end');
},
// Given a prefixed dialog id like 'lokdialog-323', gives a raw id, 323.

View File

@ -955,8 +955,8 @@ L.CanvasTileLayer = L.Layer.extend({
// Initiate selection handles.
this._selectionHandles = {};
this._selectionHandles.start = new app.definitions.textSelectionHandleSection('selection_start_handle', 30, 44, new app.definitions.simplePoint(0, 0), 'leaflet-selection-marker-start', false);
this._selectionHandles.end = new app.definitions.textSelectionHandleSection('selection_end_handle', 30, 44, new app.definitions.simplePoint(0, 0), 'leaflet-selection-marker-end', false);
this._selectionHandles.start = new app.definitions.textSelectionHandleSection('selection_start_handle', 30, 44, new app.definitions.simplePoint(0, 0), 'text-selection-handle-start', false);
this._selectionHandles.end = new app.definitions.textSelectionHandleSection('selection_end_handle', 30, 44, new app.definitions.simplePoint(0, 0), 'text-selection-handle-end', false);
this._selectionHandles.active = false;
setTimeout(function() {
@ -3259,12 +3259,6 @@ L.CanvasTileLayer = L.Layer.extend({
this._selectionContentRequest = setTimeout(L.bind(function () {
app.socket.sendMessage('gettextselection mimetype=text/html,text/plain;charset=utf-8');}, this), 100);
}
this._selectionHandles.start.showSection = true;
this._selectionHandles.end.showSection = true;
this._selectionHandles.start.setHTMLObjectVisibility(true);
this._selectionHandles.end.setHTMLObjectVisibility(true);
this._selectionHandles.active = true;
}
else {
this._selectionHandles.start.showSection = false;
@ -3524,6 +3518,8 @@ L.CanvasTileLayer = L.Layer.extend({
this._updateScrollOnCellSelection(oldSelection, this._textSelectionEnd);
this._updateMarkers();
this._selectionHandles.end.showSection = true;
this._selectionHandles.end.setHTMLObjectVisibility(true);
}
else {
this._textSelectionEnd = null;
@ -3545,6 +3541,10 @@ L.CanvasTileLayer = L.Layer.extend({
this._twipsToLatLng(bottomRightTwips, this._map.getZoom()));
this._updateScrollOnCellSelection(oldSelection, this._textSelectionStart);
this._selectionHandles.start.showSection = true;
this._selectionHandles.start.setHTMLObjectVisibility(true);
this._selectionHandles.active = true;
}
else {
this._textSelectionStart = null;
@ -4814,33 +4814,41 @@ L.CanvasTileLayer = L.Layer.extend({
var startPos = this._map._docLayer._latLngToCorePixels(this._textSelectionStart.getSouthWest());
var endPos = this._map._docLayer._latLngToCorePixels(this._textSelectionEnd.getSouthWest());
var startMarkerPos = this._selectionHandles.start.getPosition();
// CalcRTL: position from core are in document coordinates. Conversion to layer coordinates for each maker is done
// in L.Layer.getLayerPositionVisibility(). Icons of RTL "start" and "end" has to be interchanged.
var calcRTL = this.isCalcRTL();
if (startMarkerPos.pDistanceTo([endPos.x, endPos.y]) < startMarkerPos.pDistanceTo([startPos.x, startPos.y])) {
// If the start handle is actually closer to the end of the selection, reverse icons and markers.
L.DomUtil.removeClass(this._selectionHandles.start.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-end' : 'leaflet-selection-marker-start');
L.DomUtil.removeClass(this._selectionHandles.end.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-start' : 'leaflet-selection-marker-end');
L.DomUtil.addClass(this._selectionHandles.start.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-start' : 'leaflet-selection-marker-end');
L.DomUtil.addClass(this._selectionHandles.end.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-end' : 'leaflet-selection-marker-start');
var tmp = this._selectionHandles.start;
if (app.map._docLayer.isCalcRTL()) {
// Mirror position from right to left.
startPos.x = app.sectionContainer.getDocumentBounds()[2] - (startPos.x - app.sectionContainer.getDocumentBounds()[0]);
endPos.x = app.sectionContainer.getDocumentBounds()[2] - (endPos.x - app.sectionContainer.getDocumentBounds()[0]);
}
const oldStart = this._selectionHandles.start.getPosition();
const oldEnd = this._selectionHandles.end.getPosition();
startPos.x -= 30 * app.dpiScale;
this._selectionHandles.start.setPosition(startPos.x, startPos.y);
let newStart = this._selectionHandles.start.getPosition();
this._selectionHandles.end.setPosition(endPos.x, endPos.y);
const newEnd = this._selectionHandles.end.getPosition();
if (app.map._docLayer.isCalcRTL() && (newStart.y < newEnd.y || (newStart.y <= newEnd.y && newStart.x < newEnd.x))) {
// If the start handle is actually closer to the end of the selection, reverse positions (Right To Left case).
this._selectionHandles.start.setPosition(newEnd.pX, newEnd.pY);
this._selectionHandles.end.setPosition(newStart.pX, newStart.pY);
}
else if (
!app.map._docLayer.isCalcRTL() &&
(oldEnd.distanceTo(newStart.toArray()) < 20 || oldStart.distanceTo(newEnd.toArray()) < 20)
) {
/*
If the start handle is actually closer to the end of the selection, reverse positions.
This seems to be a core side issue to me. I think the start and end positions are switched but the handlers aren't on the core side.
*/
const temp = this._selectionHandles.start;
this._selectionHandles.start = this._selectionHandles.end;
this._selectionHandles.end = tmp;
this._selectionHandles.end = temp;
}
else {
// normal markers and normal icons
L.DomUtil.removeClass(this._selectionHandles.start.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-start' : 'leaflet-selection-marker-end');
L.DomUtil.removeClass(this._selectionHandles.end.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-end' : 'leaflet-selection-marker-start');
L.DomUtil.addClass(this._selectionHandles.start.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-end' : 'leaflet-selection-marker-start');
L.DomUtil.addClass(this._selectionHandles.end.getHTMLObject(), calcRTL ? 'leaflet-selection-marker-start' : 'leaflet-selection-marker-end');
}
let newPosition = this._map._docLayer._latLngToCorePixels(this._textSelectionStart.getSouthWest());
this._selectionHandles.start.setPosition(newPosition.x, newPosition.y);
newPosition = this._map._docLayer._latLngToCorePixels(this._textSelectionEnd.getSouthEast());
this._selectionHandles.end.setPosition(newPosition.x, newPosition.y);
},
hasGraphicSelection: function() {

View File

@ -53,7 +53,7 @@ class HTMLObjectSection extends CanvasSectionObject {
tempFunction(elementToAdd);
}, 100);
}
}
};
tempFunction(this.sectionProperties.objectDiv);
if (!visible)
@ -95,7 +95,8 @@ class HTMLObjectSection extends CanvasSectionObject {
}
public getPosition(): cool.SimplePoint {
return new cool.SimplePoint(this.position[0], this.position[1]);
const twips = [Math.round(this.position[0] * app.pixelsToTwips), Math.round(this.position[1] * app.pixelsToTwips)];
return new cool.SimplePoint(twips[0], twips[1]);
}
public onRemove(): void {

View File

@ -15,38 +15,66 @@ class TextSelectionHandle extends HTMLObjectSection {
super(sectionName, objectWidth, objectHeight, documentPosition, extraClass, visible);
}
onDrag(point: number[], dragDistance: number[], e: MouseEvent) {
onDrag(point: number[]) {
(<any>window).IgnorePanning = true;
this.setPosition(point[0], point[1]);
app.map.fire('handleautoscroll', {pos: { x: point[0] / app.dpiScale, y: point[1] / app.dpiScale }, map: app.map});
const candidateX = Math.round((this.myTopLeft[0] + point[0]) / app.dpiScale);
const candidateY = Math.round((this.myTopLeft[1] + point[1]) / app.dpiScale);
this.sectionProperties.objectDiv.style.left = candidateX + 'px';
this.sectionProperties.objectDiv.style.top = candidateY + 'px';
app.map.fire('handleautoscroll', {pos: { x: candidateX, y: candidateY }, map: app.map});
}
setOpacity(value: number) {
this.getHTMLObject().style.opacity = value;
}
onDragEnd(point: number[], e: MouseEvent) {
onDragEnd(point: number[]) {
(<any>window).IgnorePanning = undefined;
app.map.fire('scrollvelocity', {vx: 0, vy: 0});
let x = this.position[0] + point[0];
const y = this.position[1] + point[1];
this.setPosition(x, y);
if (this.name === 'selection_start_handle') {
app.map._docLayer._postSelectTextEvent('start', point[0] * app.pixelsToTwips, point[1] * app.pixelsToTwips);
app.map.fire('scrollvelocity', {vx: 0, vy: 0});
const type = this.name === 'selection_start_handle' ? 'start' : 'end';
if (type === 'start')
x += 30 / app.dpiScale;
if (!app.map._docLayer.isCalcRTL()) {
app.map._docLayer._postSelectTextEvent(type, Math.round(x * app.pixelsToTwips), Math.round(y * app.pixelsToTwips));
}
else if (this.name === 'selection_end_handle') {
app.map._docLayer._postSelectTextEvent('end', point[0] * app.pixelsToTwips, point[1] * app.pixelsToTwips);
else {
const referenceX = app.file.viewedRectangle.pX1 + (app.file.viewedRectangle.pX2 - this.position[0]);
app.map._docLayer._postSelectTextEvent(type, Math.round(referenceX * app.pixelsToTwips), Math.round(y * app.pixelsToTwips));
}
}
onMouseMove(point: number[], dragDistance: number[], e: MouseEvent): void {
e.stopPropagation();
if (this.containerObject.isDraggingSomething()) {
this.onDrag(point, dragDistance, e);
this.stopPropagating();
this.onDrag(point);
}
}
onClick(point: number[], e: MouseEvent): void {
e.stopPropagation();
this.stopPropagating();
}
onMouseDown(point: number[], e: MouseEvent): void {
e.stopPropagation();
this.stopPropagating();
}
onMouseUp(point: number[], e: MouseEvent): void {
e.stopPropagation();
if (this.containerObject.isDraggingSomething()) {
this.onDragEnd(point, e);
this.stopPropagating();
this.onDragEnd(point);
}
}
}

View File

@ -906,11 +906,11 @@ function getCursorPos(offsetProperty, aliasName, cursorSelector = '.cursor-overl
function textSelectionShouldExist() {
cy.log('>> textSelectionShouldExist - start');
cy.cGet('.leaflet-selection-marker-start').should('exist');
cy.cGet('.leaflet-selection-marker-end').should('exist');
cy.cGet('.text-selection-handle-start').should('exist');
cy.cGet('.text-selection-handle-end').should('exist');
// One of the marker should be visible at least (if not both).
cy.cGet('.leaflet-selection-marker-start, .leaflet-selection-marker-end').should('be.visible');
cy.cGet('.text-selection-handle-start, .text-selection-handle-end').should('be.visible');
cy.log('<< textSelectionShouldExist - end');
}
@ -919,8 +919,8 @@ function textSelectionShouldExist() {
function textSelectionShouldNotExist() {
cy.log('>> textSelectionShouldNotExist - start');
cy.cGet('.leaflet-selection-marker-start').should('not.exist');
cy.cGet('.leaflet-selection-marker-end').should('not.exist');
cy.cGet('.text-selection-handle-start').should('not.be.visible');
cy.cGet('.text-selection-handle-end').should('not.be.visible');
cy.log('<< textSelectionShouldNotExist - end');
}

View File

@ -100,10 +100,7 @@ function selectTableInTheCenter() {
cy.cGet('body').click(XPos, YPos);
});
return cy.cGet('.leaflet-marker-pane')
.then(function (pane) {
return pane[0].children.length !== 0;
});
return cy.cGet('.text-selection-handle-start').should('be.visible');
});
cy.cGet('.leaflet-marker-icon.table-row-resize-marker').should($el => { expect(Cypress.dom.isDetached($el)).to.eq(false); }).should('be.visible');
@ -170,10 +167,7 @@ function selectTextOfShape() {
cy.waitUntil(function() {
cy.cGet('svg g svg').dblclick({force: true});
helper.typeIntoDocument('{ctrl}a');
return cy.cGet('.leaflet-marker-pane')
.then(function(markerPane) {
return markerPane.children().length !== 0;
});
return cy.cGet('.text-selection-handle-start').should('be.visible');
});
helper.textSelectionShouldExist();

View File

@ -13,14 +13,9 @@ function selectAllTextOfDoc() {
cy.log('>> selectAllTextOfDoc - start');
// Remove selection if exist
cy.cGet('.leaflet-marker-pane')
.then(function(body) {
if (body.find('.leaflet-selection-marker-start').length !== 0) {
helper.typeIntoDocument('{downarrow}');
}
});
helper.typeIntoDocument('{downarrow}');
cy.cGet('.leaflet-selection-marker-start').should('not.exist');
cy.cGet('.text-selection-handle-start').should('not.be.visible');
helper.selectAllText();

View File

@ -39,7 +39,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.getCursorPos('left', 'cursorOrigLeft');
@ -50,7 +50,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -67,7 +67,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -89,7 +89,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -101,7 +101,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -119,7 +119,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -139,7 +139,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -149,7 +149,7 @@ describe.skip(['tagdesktop'], 'Searching via search bar' ,function() {
cy.cGet('.transform-handler--rotate')
.should('not.exist');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('not.exist');
cy.cGet('input#search-input')

View File

@ -9,7 +9,7 @@ describe(['tagdesktop', 'tagnextcloud', 'tagproxy'], 'Clipboard operations.', fu
// Select some text
helper.selectAllText();
cy.cGet('.leaflet-marker-icon')
cy.cGet('.html-object-section')
.then(function(marker) {
expect(marker).to.have.lengthOf(2);
var XPos = (marker[0].getBoundingClientRect().right + marker[1].getBoundingClientRect().left) / 2;

View File

@ -207,7 +207,7 @@ describe.skip(['tagmobile'], 'Trigger hamburger menu options.', function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.should('be.visible');
});

View File

@ -23,7 +23,7 @@ describe.skip('Searching via search bar.', function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.get('.leaflet-selection-marker-start')
cy.get('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -53,7 +53,7 @@ describe.skip('Searching via search bar.', function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.getCursorPos('left', 'cursorOrigLeft');
@ -64,7 +64,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -81,7 +81,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -102,7 +102,7 @@ describe.skip('Searching via search bar.', function() {
// A shape and some text should be selected
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.get('.leaflet-selection-marker-start')
cy.get('.text-selection-handle-start')
.should('be.visible');
helper.expectTextForClipboard('a');
@ -114,7 +114,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -131,7 +131,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -151,7 +151,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');
@ -159,7 +159,7 @@ describe.skip('Searching via search bar.', function() {
searchHelper.cancelSearch();
cy.cGet('.transform-handler--rotate').should('not.exist');
cy.cGet('.leaflet-selection-marker-start').should('not.exist');
cy.cGet('.text-selection-handle-start').should('not.exist');
cy.cGet('input#search-input').should('be.visible');
});
@ -170,7 +170,7 @@ describe.skip('Searching via search bar.', function() {
//cy.get('.transform-handler--rotate')
// .should('be.not.visible');
cy.cGet('.leaflet-selection-marker-start').should('be.visible');
cy.cGet('.text-selection-handle-start').should('be.visible');
helper.expectTextForClipboard('a');

View File

@ -37,8 +37,8 @@ describe(['tagmobile', 'tagnextcloud', 'tagproxy'], 'Text cursor tests.', functi
writerHelper.selectAllTextOfDoc();
cy.cGet('.blinking-cursor').should('be.visible');
// Blinking cursor and so the view should be at the end of the text selection.
cy.cGet('.leaflet-selection-marker-end').should('be.visible');
cy.cGet('.leaflet-selection-marker-start').should('not.be.visible');
cy.cGet('.text-selection-handle-end').should('be.visible');
cy.cGet('.text-selection-handle-start').should('not.be.visible');
});
it('Move cursor through table.', function() {

View File

@ -171,9 +171,9 @@ describe.skip(['tagmobile'], 'Trigger hamburger menu options.', function() {
// No actual text sent from core because of the removal.
helper.expectTextForClipboard('\n\n');
// We have a multiline selection
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.then(function(firstMarker) {
cy.cGet('.leaflet-selection-marker-end')
cy.cGet('.text-selection-handle-end')
.then(function(secondMarker) {
expect(firstMarker.offset().top).to.be.lessThan(secondMarker.offset().top);
expect(firstMarker.offset().left).to.be.lessThan(secondMarker.offset().left);
@ -190,9 +190,9 @@ describe.skip(['tagmobile'], 'Trigger hamburger menu options.', function() {
helper.typeIntoDocument('{ctrl}a');
// Both selection markers should be in the same line
cy.cGet('.leaflet-selection-marker-start')
cy.cGet('.text-selection-handle-start')
.then(function(firstMarker) {
cy.cGet('.leaflet-selection-marker-end')
cy.cGet('.text-selection-handle-end')
.then(function(secondMarker) {
expect(firstMarker.offset().top).to.be.equal(secondMarker.offset().top);
expect(firstMarker.offset().left).to.be.lessThan(secondMarker.offset().left);

View File

@ -22,9 +22,9 @@ describe.skip('Spell checking menu.', function() {
.then(function(markers) {
expect(markers.length).to.have.greaterThan(1);
for (var i = 0; i < markers.length; i++) {
if (markers[i].classList.contains('leaflet-selection-marker-start')) {
if (markers[i].classList.contains('text-selection-handle-start')) {
var startPos = markers[i].getBoundingClientRect();
} else if (markers[i].classList.contains('leaflet-selection-marker-end')) {
} else if (markers[i].classList.contains('text-selection-handle-end')) {
var endPos = markers[i].getBoundingClientRect();
}
}