|
@@ -359,6 +359,14 @@ export default class DocumentSelection {
|
|
|
return this._selection.hasAttribute( key );
|
|
return this._selection.hasAttribute( key );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Refreshes selection attributes and markers according to the current position in the model.
|
|
|
|
|
+ */
|
|
|
|
|
+ refresh() {
|
|
|
|
|
+ this._selection._updateMarkers();
|
|
|
|
|
+ this._selection._updateAttributes( false );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Checks whether object is of given type following the convention set by
|
|
* Checks whether object is of given type following the convention set by
|
|
|
* {@link module:engine/model/node~Node#is `Node#is()`}.
|
|
* {@link module:engine/model/node~Node#is `Node#is()`}.
|
|
@@ -598,6 +606,26 @@ class LiveSelection extends Selection {
|
|
|
// @type {Set}
|
|
// @type {Set}
|
|
|
this._overriddenGravityRegister = new Set();
|
|
this._overriddenGravityRegister = new Set();
|
|
|
|
|
|
|
|
|
|
+ // Ensure selection is correct after each operation.
|
|
|
|
|
+ this.listenTo( this._model, 'applyOperation', ( evt, args ) => {
|
|
|
|
|
+ const operation = args[ 0 ];
|
|
|
|
|
+
|
|
|
|
|
+ if ( !operation.isDocumentOperation || operation.type == 'marker' || operation.type == 'rename' || operation.type == 'noop' ) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while ( this._fixGraveyardRangesData.length ) {
|
|
|
|
|
+ const { liveRange, sourcePosition } = this._fixGraveyardRangesData.shift();
|
|
|
|
|
+
|
|
|
|
|
+ this._fixGraveyardSelection( liveRange, sourcePosition );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( this._hasChangedRange ) {
|
|
|
|
|
+ this._hasChangedRange = false;
|
|
|
|
|
+ this.fire( 'change:range', { directChange: false } );
|
|
|
|
|
+ }
|
|
|
|
|
+ }, { priority: 'lowest' } );
|
|
|
|
|
+
|
|
|
// Ensure selection is correct and up to date after each range change.
|
|
// Ensure selection is correct and up to date after each range change.
|
|
|
this.on( 'change:range', () => {
|
|
this.on( 'change:range', () => {
|
|
|
for ( const range of this.getRanges() ) {
|
|
for ( const range of this.getRanges() ) {
|
|
@@ -615,38 +643,12 @@ class LiveSelection extends Selection {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- this._updateMarkers();
|
|
|
|
|
- this._updateAttributes( false );
|
|
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
// Update markers data stored by the selection after each marker change.
|
|
// Update markers data stored by the selection after each marker change.
|
|
|
this.listenTo( this._model.markers, 'update', () => this._updateMarkers() );
|
|
this.listenTo( this._model.markers, 'update', () => this._updateMarkers() );
|
|
|
|
|
|
|
|
- // Ensure selection is correct and up to date after each operation.
|
|
|
|
|
- this.listenTo( this._model, 'applyOperation', ( evt, args ) => {
|
|
|
|
|
- const operation = args[ 0 ];
|
|
|
|
|
-
|
|
|
|
|
- if ( !operation.isDocumentOperation || operation.type == 'marker' || operation.type == 'rename' || operation.type == 'noop' ) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- while ( this._fixGraveyardRangesData.length ) {
|
|
|
|
|
- const { liveRange, sourcePosition } = this._fixGraveyardRangesData.shift();
|
|
|
|
|
-
|
|
|
|
|
- this._fixGraveyardSelection( liveRange, sourcePosition );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if ( this._hasChangedRange ) {
|
|
|
|
|
- this._hasChangedRange = false;
|
|
|
|
|
- this.fire( 'change:range', { directChange: false } );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- this._updateMarkers();
|
|
|
|
|
- this._updateAttributes( false );
|
|
|
|
|
- }, { priority: 'lowest' } );
|
|
|
|
|
-
|
|
|
|
|
- // Clear selection attributes from element if no longer empty.
|
|
|
|
|
|
|
+ // Ensure selection is up to date after each change block.
|
|
|
this.listenTo( this._document, 'change', ( evt, batch ) => {
|
|
this.listenTo( this._document, 'change', ( evt, batch ) => {
|
|
|
clearAttributesStoredInElement( this._model, batch );
|
|
clearAttributesStoredInElement( this._model, batch );
|
|
|
} );
|
|
} );
|
|
@@ -715,12 +717,12 @@ class LiveSelection extends Selection {
|
|
|
|
|
|
|
|
setTo( selectable, optionsOrPlaceOrOffset, options ) {
|
|
setTo( selectable, optionsOrPlaceOrOffset, options ) {
|
|
|
super.setTo( selectable, optionsOrPlaceOrOffset, options );
|
|
super.setTo( selectable, optionsOrPlaceOrOffset, options );
|
|
|
- this._refreshAttributes();
|
|
|
|
|
|
|
+ this._updateAttributes( true );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
setFocus( itemOrPosition, offset ) {
|
|
setFocus( itemOrPosition, offset ) {
|
|
|
super.setFocus( itemOrPosition, offset );
|
|
super.setFocus( itemOrPosition, offset );
|
|
|
- this._refreshAttributes();
|
|
|
|
|
|
|
+ this._updateAttributes( true );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
setAttribute( key, value ) {
|
|
setAttribute( key, value ) {
|
|
@@ -747,7 +749,7 @@ class LiveSelection extends Selection {
|
|
|
this._overriddenGravityRegister.add( overrideUid );
|
|
this._overriddenGravityRegister.add( overrideUid );
|
|
|
|
|
|
|
|
if ( this._overriddenGravityRegister.size === 1 ) {
|
|
if ( this._overriddenGravityRegister.size === 1 ) {
|
|
|
- this._refreshAttributes();
|
|
|
|
|
|
|
+ this._updateAttributes( true );
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return overrideUid;
|
|
return overrideUid;
|
|
@@ -773,15 +775,10 @@ class LiveSelection extends Selection {
|
|
|
|
|
|
|
|
// Restore gravity only when all overriding have been restored.
|
|
// Restore gravity only when all overriding have been restored.
|
|
|
if ( !this.isGravityOverridden ) {
|
|
if ( !this.isGravityOverridden ) {
|
|
|
- this._refreshAttributes();
|
|
|
|
|
|
|
+ this._updateAttributes( true );
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Removes all attributes from the selection and sets attributes according to the surrounding nodes.
|
|
|
|
|
- _refreshAttributes() {
|
|
|
|
|
- this._updateAttributes( true );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
_popRange() {
|
|
_popRange() {
|
|
|
this._ranges.pop().detach();
|
|
this._ranges.pop().detach();
|
|
|
}
|
|
}
|