Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Align feature class naming to a new scheme. #78

Merged
merged 5 commits into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 7 additions & 53 deletions src/undo.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import UndoEngine from './undoengine';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';

import undoIcon from '../theme/icons/undo.svg';
import redoIcon from '../theme/icons/redo.svg';
import UndoEditing from './undoediting';
import UndoUI from './undoui';

/**
* The undo feature. It introduces the Undo and Redo buttons to the editor.
* The undo feature.
*
* It loads the {@link module:undo/undoediting~UndoEditing undo editing feature}
* and {@link module:undo/undoui~UndoUI undo UI feature}.
*
* Below is the explanation of the undo mechanism working together with {@link module:engine/model/history~History History}:
*
Expand Down Expand Up @@ -106,7 +106,7 @@ export default class Undo extends Plugin {
* @inheritDoc
*/
static get requires() {
return [ UndoEngine ];
return [ UndoEditing, UndoUI ];
}

/**
Expand All @@ -115,50 +115,4 @@ export default class Undo extends Plugin {
static get pluginName() {
return 'Undo';
}

/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const t = editor.t;

this._addButton( 'undo', t( 'Undo' ), 'CTRL+Z', undoIcon );
this._addButton( 'redo', t( 'Redo' ), 'CTRL+Y', redoIcon );

editor.keystrokes.set( 'CTRL+Z', 'undo' );
editor.keystrokes.set( 'CTRL+Y', 'redo' );
editor.keystrokes.set( 'CTRL+SHIFT+Z', 'redo' );
}

/**
* Creates a button for the specified command.
*
* @private
* @param {String} name Command name.
* @param {String} label Button label.
* @param {String} keystroke Command keystroke.
* @param {String} Icon Source of the icon.
*/
_addButton( name, label, keystroke, Icon ) {
const editor = this.editor;
const command = editor.commands.get( name );

editor.ui.componentFactory.add( name, locale => {
const view = new ButtonView( locale );

view.set( {
label,
icon: Icon,
keystroke,
tooltip: true
} );

view.bind( 'isEnabled' ).to( command, 'isEnabled' );

this.listenTo( view, 'execute', () => editor.execute( name ) );

return view;
} );
}
}
24 changes: 15 additions & 9 deletions src/undoengine.js → src/undoediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

/**
* @module undo/undoengine
* @module undo/undoediting
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
Expand All @@ -19,7 +19,7 @@ import RedoCommand from './redocommand';
*
* @extends module:core/plugin~Plugin
*/
export default class UndoEngine extends Plugin {
export default class UndoEditing extends Plugin {
/**
* @inheritDoc
*/
Expand All @@ -31,15 +31,15 @@ export default class UndoEngine extends Plugin {
* Created and registered during the {@link #init feature initialization}.
*
* @private
* @member {undo.UndoEngineCommand} #_undoCommand
* @member {module:undo/undocommand~UndoCommand} #_undoCommand
*/

/**
* The command that manages redo {@link module:engine/model/batch~Batch batches} stack (history).
* Created and registered during the {@link #init feature initialization}.
*
* @private
* @member {undo.UndoEngineCommand} #_redoCommand
* @member {module:undo/undocommand~UndoCommand} #_redoCommand
*/

/**
Expand All @@ -55,15 +55,17 @@ export default class UndoEngine extends Plugin {
* @inheritDoc
*/
init() {
const editor = this.editor;

// Create commands.
this._undoCommand = new UndoCommand( this.editor );
this._redoCommand = new RedoCommand( this.editor );
this._undoCommand = new UndoCommand( editor );
this._redoCommand = new RedoCommand( editor );

// Register command to the editor.
this.editor.commands.add( 'undo', this._undoCommand );
this.editor.commands.add( 'redo', this._redoCommand );
editor.commands.add( 'undo', this._undoCommand );
editor.commands.add( 'redo', this._redoCommand );

this.listenTo( this.editor.model, 'applyOperation', ( evt, args ) => {
this.listenTo( editor.model, 'applyOperation', ( evt, args ) => {
const operation = args[ 0 ];

// Do not register batch if the operation is not a document operation.
Expand Down Expand Up @@ -99,5 +101,9 @@ export default class UndoEngine extends Plugin {
this.listenTo( this._undoCommand, 'revert', ( evt, undoneBatch, undoingBatch ) => {
this._redoCommand.addBatch( undoingBatch );
} );

editor.keystrokes.set( 'CTRL+Z', 'undo' );
editor.keystrokes.set( 'CTRL+Y', 'redo' );
editor.keystrokes.set( 'CTRL+SHIFT+Z', 'redo' );
}
}
63 changes: 63 additions & 0 deletions src/undoui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module undo/undoui
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';

import undoIcon from '../theme/icons/undo.svg';
import redoIcon from '../theme/icons/redo.svg';

/**
* The undo UI feature. It introduces the Undo and Redo buttons to the editor.
*
* @extends module:core/plugin~Plugin
*/
export default class UndoUI extends Plugin {
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const t = editor.t;

this._addButton( 'undo', t( 'Undo' ), 'CTRL+Z', undoIcon );
this._addButton( 'redo', t( 'Redo' ), 'CTRL+Y', redoIcon );
}

/**
* Creates a button for the specified command.
*
* @private
* @param {String} name Command name.
* @param {String} label Button label.
* @param {String} keystroke Command keystroke.
* @param {String} Icon Source of the icon.
*/
_addButton( name, label, keystroke, Icon ) {
const editor = this.editor;

editor.ui.componentFactory.add( name, locale => {
const command = editor.commands.get( name );
const view = new ButtonView( locale );

view.set( {
label,
icon: Icon,
keystroke,
tooltip: true
} );

view.bind( 'isEnabled' ).to( command, 'isEnabled' );

this.listenTo( view, 'execute', () => editor.execute( name ) );

return view;
} );
}
}
131 changes: 6 additions & 125 deletions tests/undo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,135 +3,16 @@
* For licensing, see LICENSE.md.
*/

/* globals document */

import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
import Undo from '../src/undo';
import UndoEngine from '../src/undoengine';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';

testUtils.createSinonSandbox();
import UndoEditing from '../src/undoediting';
import UndoUI from '../src/undoui';

describe( 'Undo', () => {
let editor, editorElement;

beforeEach( () => {
editorElement = document.createElement( 'div' );
document.body.appendChild( editorElement );

return ClassicTestEditor.create( editorElement, { plugins: [ Undo ] } )
.then( newEditor => {
editor = newEditor;
} );
} );

afterEach( () => {
editorElement.remove();

return editor.destroy();
} );

it( 'should be loaded', () => {
expect( editor.plugins.get( Undo ) ).to.be.instanceOf( Undo );
} );

it( 'should load UndoEngine', () => {
expect( editor.plugins.get( UndoEngine ) ).to.be.instanceOf( UndoEngine );
} );

testButton( 'undo', 'Undo', 'CTRL+Z' );
testButton( 'redo', 'Redo', 'CTRL+Y' );

it( 'should set CTRL+Z keystroke', () => {
const spy = sinon.stub( editor, 'execute' );

const wasHandled = editor.keystrokes.press( {
keyCode: keyCodes.z,
ctrlKey: true,
preventDefault: sinon.spy(),
stopPropagation: sinon.spy()
} );

expect( wasHandled ).to.be.true;
expect( spy.calledWithExactly( 'undo' ) ).to.be.true;
} );

it( 'should set CTRL+Y keystroke', () => {
const spy = sinon.stub( editor, 'execute' );

const wasHandled = editor.keystrokes.press( {
keyCode: keyCodes.y,
ctrlKey: true,
preventDefault: sinon.spy(),
stopPropagation: sinon.spy()
} );

expect( wasHandled ).to.be.true;
expect( spy.calledWithExactly( 'redo' ) ).to.be.true;
it( 'should be named', () => {
expect( Undo.pluginName ).to.equal( 'Undo' );
} );

it( 'should set CTRL+SHIFT+Z keystroke', () => {
const spy = sinon.stub( editor, 'execute' );
const keyEventData = {
keyCode: keyCodes.z,
ctrlKey: true,
shiftKey: true,
preventDefault: sinon.spy(),
stopPropagation: sinon.spy()
};

const wasHandled = editor.keystrokes.press( keyEventData );

expect( wasHandled ).to.be.true;
expect( spy.calledWithExactly( 'redo' ) ).to.be.true;
expect( keyEventData.preventDefault.calledOnce ).to.be.true;
it( 'should require UndoEditing and UndoUI', () => {
expect( Undo.requires ).to.deep.equal( [ UndoEditing, UndoUI ] );
} );

function testButton( featureName, label, featureKeystroke ) {
describe( `${ featureName } button`, () => {
let button;

beforeEach( () => {
button = editor.ui.componentFactory.create( featureName );
} );

it( 'should register feature component', () => {
expect( button ).to.be.instanceOf( ButtonView );
} );

it( 'should create UI component with correct attribute values', () => {
expect( button.isOn ).to.be.false;
expect( button.label ).to.equal( label );
expect( button.icon ).to.match( /<svg / );
expect( button.keystroke ).to.equal( featureKeystroke );
} );

it( `should execute ${ featureName } command on model execute event`, () => {
const executeSpy = testUtils.sinon.stub( editor, 'execute' );

button.fire( 'execute' );

sinon.assert.calledOnce( executeSpy );
sinon.assert.calledWithExactly( executeSpy, featureName );
} );

it( `should bind model to ${ featureName } command`, () => {
const command = editor.commands.get( featureName );

expect( button.isOn ).to.be.false;

const initState = command.isEnabled;
expect( button.isEnabled ).to.equal( initState );

command.isEnabled = !initState;
expect( button.isEnabled ).to.equal( !initState );
} );

it( 'should set keystroke in the model', () => {
expect( button.keystroke ).to.equal( featureKeystroke );
} );
} );
}
} );
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,28 @@ import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'
import Range from '@ckeditor/ckeditor5-engine/src/model/range';
import Position from '@ckeditor/ckeditor5-engine/src/model/position';
import Batch from '@ckeditor/ckeditor5-engine/src/model/batch';
import UndoEngine from '../src/undoengine';
import UndoEditing from '../src/undoediting';

import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import HeadingEngine from '@ckeditor/ckeditor5-heading/src/headingengine';
import HeadingEditing from '@ckeditor/ckeditor5-heading/src/headingediting';
import Typing from '@ckeditor/ckeditor5-typing/src/typing';
import Enter from '@ckeditor/ckeditor5-enter/src/enter';
import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
import BoldEngine from '@ckeditor/ckeditor5-basic-styles/src/boldengine';
import BoldEditing from '@ckeditor/ckeditor5-basic-styles/src/bold/boldediting';

import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';

import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';

describe( 'UndoEngine integration', () => {
describe( 'UndoEditing integration', () => {
let editor, model, doc, root, div;

beforeEach( () => {
div = document.createElement( 'div' );
document.body.appendChild( div );

return ClassicEditor.create( div, { plugins: [ Paragraph, HeadingEngine, Typing, Enter, Clipboard, BoldEngine, UndoEngine ] } )
return ClassicEditor.create( div, { plugins: [ Paragraph, HeadingEditing, Typing, Enter, Clipboard, BoldEditing, UndoEditing ] } )
.then( newEditor => {
editor = newEditor;

Expand Down
Loading