8
0
Просмотр исходного кода

Replace recently used colors with document colors.

Mateusz Samsel 6 лет назад
Родитель
Сommit
9af59d6387

+ 40 - 44
packages/ckeditor5-font/src/ui/colortableview.js

@@ -37,9 +37,10 @@ export default class ColorTableView extends View {
 	 * be displayed in the table.
 	 * @param {Number} config.columns The number of columns in the color grid.
 	 * @param {String} config.removeButtonLabel The label of the button responsible for removing the color.
-	 * @param {String} config.recentlyUsedLabel The label for the section with the recently used color inside the dropdown.
+	 * @param {String} config.documentColorsLabel The label for the section with the document colors.
+	 * @param {String} config.documentColorsCount The number of colors in document colors section inside dropdown.
 	 */
-	constructor( locale, { colors, columns, removeButtonLabel, recentlyUsedLabel } ) {
+	constructor( locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount } ) {
 		super( locale );
 
 		/**
@@ -88,11 +89,11 @@ export default class ColorTableView extends View {
 		this.removeButtonLabel = removeButtonLabel;
 
 		/**
-		 * The label for the section with the recently used color inside the dropdown.
+		 * The label for the section with document colors.
 		 *
 		 * @type {String}
 		 */
-		this.recentlyUsedLabel = recentlyUsedLabel;
+		this.documentColorsLabel = documentColorsLabel;
 
 		/**
 		 * The number of columns in the color grid.
@@ -107,7 +108,15 @@ export default class ColorTableView extends View {
 		 * @readonly
 		 * @member {module:utils/collection~Collection}
 		 */
-		this.recentlyUsedColors = new Collection();
+		this.documentColors = new Collection();
+
+		/**
+		 * Maximum number of colors in document colors section.
+		 *
+		 * @readonly
+		 * @type {Number}
+		 */
+		this.documentColorsCount = documentColorsCount;
 
 		/**
 		 * Helps cycling over focusable {@link #items} in the list.
@@ -129,7 +138,6 @@ export default class ColorTableView extends View {
 			}
 		} );
 
-		this.initRecentCollection();
 		this.setTemplate( {
 			tag: 'div',
 			attributes: {
@@ -142,8 +150,11 @@ export default class ColorTableView extends View {
 		} );
 
 		this.items.add( this.removeColorButton() );
-		this.items.add( this.createStaticColorTable() );
-		this.items.add( this.recentlyUsed() );
+		this.items.add( this.createStaticColorGrid() );
+
+		if ( documentColorsCount ) {
+			this.items.add( this.createDocumentColors() );
+		}
 	}
 
 	/**
@@ -174,7 +185,7 @@ export default class ColorTableView extends View {
 	 *
 	 * @private
 	 */
-	createStaticColorTable() {
+	createStaticColorGrid() {
 		const colorGrid = new ColorGridView( this.locale, {
 			colorDefinitions: this.colorDefinitions,
 			columns: this.columns
@@ -187,22 +198,27 @@ export default class ColorTableView extends View {
 	}
 
 	/**
-	 * Adds recently used colors section view and binds it to {@link #recentlyUsedColors}.
+	 * Adds document colors section view and binds it to {@link #documentColors}.
+	 * It also initialize empty color placeholders with {@link #initEmptyDocumentColorsCollection}.
 	 *
 	 * @private
 	 */
-	recentlyUsed() {
-		const recentViews = new ColorGridView( this.locale, { columns: this.columns, gridLabel: this.recentlyUsedLabel } );
+	createDocumentColors() {
+		const documentColors = new ColorGridView( this.locale, {
+			columns: this.columns,
+			gridLabel: this.documentColorsLabel
+		} );
 
-		recentViews.bind( 'selectedColor' ).to( this );
+		documentColors.delegate( 'execute' ).to( this );
+		documentColors.bind( 'selectedColor' ).to( this );
 
-		recentViews.items.bindTo( this.recentlyUsedColors ).using(
+		documentColors.items.bindTo( this.documentColors ).using(
 			colorObj => {
 				const colorTile = new ColorTileView();
 
 				colorTile.set( {
 					color: colorObj.color,
-					hasBorder: colorObj.hasBorder
+					hasBorder: colorObj.options || colorObj.options.hasBorder
 				} );
 
 				if ( colorObj.label ) {
@@ -212,15 +228,17 @@ export default class ColorTableView extends View {
 					} );
 				}
 
-				if ( colorObj.isEnabled === false ) {
+				if ( colorObj.options && colorObj.options.isEnabled === false ) {
 					colorTile.set( 'isEnabled', false );
 				}
 
 				colorTile.on( 'execute', () => {
 					this.fire( 'execute', {
 						value: colorObj.color,
-						hasBorder: colorObj.hasBorder,
-						label: colorObj.label
+						label: colorObj.label,
+						options: {
+							hasBorder: colorObj.hasBorder,
+						}
 					} );
 				} );
 
@@ -228,37 +246,15 @@ export default class ColorTableView extends View {
 			}
 		);
 
-		this.recentlyUsedColors.on( 'add', ( evt, item ) => {
-			const duplicates = this.recentlyUsedColors.filter( element => element.color === item.color, this );
+		this.documentColors.on( 'add', ( evt, item ) => {
+			const duplicates = this.documentColors.filter( element => element.color === item.color, this );
 
 			if ( duplicates.length === 2 ) {
-				this.recentlyUsedColors.remove( duplicates[ 1 ] );
-			}
-
-			if ( this.recentlyUsedColors.length > this.columns ) {
-				this.recentlyUsedColors.remove( this.recentlyUsedColors.length - 1 );
+				this.documentColors.remove( duplicates[ 1 ] );
 			}
 		} );
 
-		recentViews.delegate( 'execute' ).to( this );
-
-		return recentViews;
-	}
-
-	/**
-	 * Populates {@link #recentlyUsedColors} with empty non-clickable buttons, which represent placeholders
-	 * for colors.
-	 *
-	 * @private
-	 */
-	initRecentCollection() {
-		for ( let i = 0; i < this.columns; i++ ) {
-			this.recentlyUsedColors.add( {
-				color: 'hsla(0, 0%, 0%, 0)',
-				isEnabled: false,
-				hasBorder: true
-			} );
-		}
+		return documentColors;
 	}
 
 	/**

+ 37 - 34
packages/ckeditor5-font/src/ui/colorui.js

@@ -86,6 +86,7 @@ export default class ColorUI extends Plugin {
 		const command = editor.commands.get( this.commandName );
 		const colorsConfig = normalizeColorOptions( editor.config.get( this.componentName ).colors );
 		const localizedColors = getLocalizedColorOptions( editor, colorsConfig );
+		const documentColorsCount = editor.config.get( `${ this.componentName }.documentColors` );
 
 		// Register the UI component.
 		editor.ui.componentFactory.add( this.componentName, locale => {
@@ -101,7 +102,8 @@ export default class ColorUI extends Plugin {
 				} ) ),
 				columns: this.columns,
 				removeButtonLabel: t( 'Remove color' ),
-				recentlyUsedLabel: t( 'Recently used:' )
+				documentColorsLabel: documentColorsCount !== 0 ? t( 'Document colors' ) : undefined,
+				documentColorsCount: documentColorsCount === undefined ? this.columns : documentColorsCount
 			} );
 
 			this.colorTableView.bind( 'selectedColor' ).to( command, 'value' );
@@ -125,39 +127,36 @@ export default class ColorUI extends Plugin {
 				editor.editing.view.focus();
 			} );
 
-			return dropdownView;
-		} );
-
-		// Update recently used colors when user change data in editor.
-		editor.model.document.on( 'change:data', () => {
-			const model = editor.model;
-			const changes = model.document.differ.getChanges();
-			changes.forEach( change => {
-				switch ( change.type ) {
-					case 'insert': {
-						const position = change.position;
-						const range = model.createRange( position, position.getShiftedBy( change.length ) );
-						const walker = range.getWalker( { ignoreElementEnd: true } );
-						let item = walker.next();
-						while ( !item.done ) {
-							if ( item.value.type === 'text' ) {
-								// Only text nodes can have color attributes.
-								const color = item.value.item.getAttribute( this.componentName );
-								if ( color ) {
-									this.addColorToRecentlyUsed( color );
+			if ( documentColorsCount !== 0 ) {
+				dropdownView.on( 'change:isOpen', ( evt, name, val ) => {
+					if ( val ) {
+						const model = editor.model;
+						const document = model.document;
+						const rootNames = document.getRootNames();
+						const maxCount = this.colorTableView.documentColorsCount;
+						const documentColors = this.colorTableView.documentColors;
+						documentColors.clear();
+
+						for ( const rootName of rootNames ) {
+							if ( documentColors.length >= maxCount ) {
+								break;
+							}
+							const root = document.getRoot( rootName );
+							const range = model.createRangeIn( root );
+							for ( const node of range.getItems() ) {
+								if ( node.is( 'textProxy' ) && node.hasAttribute( this.componentName ) ) {
+									this.addColorToDocumentColors( node.getAttribute( this.componentName ) );
+									if ( documentColors.length >= maxCount ) {
+										break;
+									}
 								}
 							}
-							item = walker.next();
 						}
-						break;
 					}
-					case 'attribute':
-						if ( change.attributeKey === this.componentName && change.attributeNewValue ) {
-							this.addColorToRecentlyUsed( change.attributeNewValue );
-						}
-						break;
-				}
-			} );
+				} );
+			}
+
+			return dropdownView;
 		} );
 	}
 
@@ -166,15 +165,19 @@ export default class ColorUI extends Plugin {
 	 *
 	 * @param {String} color String which stores value of recently applied color
 	 */
-	addColorToRecentlyUsed( color ) {
+	addColorToDocumentColors( color ) {
 		const predefinedColor = this.colorTableView.colorDefinitions
 			.find( definition => definition.color === color );
 		if ( !predefinedColor ) {
-			this.colorTableView.recentlyUsedColors.add( {
+			this.colorTableView.documentColors.add( {
 				color,
 				label: color,
-				hasBorder: false
-			}, 0 );
+				options: {
+					hasBorder: false
+				}
+			} );
+		} else {
+			this.colorTableView.documentColors.add( Object.assign( {}, predefinedColor ) );
 		}
 	}
 }

+ 4 - 3
packages/ckeditor5-font/src/utils.js

@@ -109,12 +109,13 @@ export function normalizeColorOptions( options ) {
  * @param {Array.<module:ui/colorgrid/colorgrid~ColorDefinition>} config.colors An array with definitions
  * representing colors to be displayed in the color table.
  * @param {String} config.removeButtonLabel The label for the button responsible for removing the color.
- * @param {String} config.recentlyUsedLabel The label for the section with the recently used color inside the dropdown.
+ * @param {String} config.documentColorsLabel The label for the section with document colors.
+ * @param {String} config.documentColorsCount The number of document colors inside dropdown.
  * @returns {module:font/ui/colortableview~ColorTableView} The new color table view.
  */
-export function addColorTableToDropdown( { dropdownView, colors, columns, removeButtonLabel, recentlyUsedLabel } ) {
+export function addColorTableToDropdown( { dropdownView, colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount } ) {
 	const locale = dropdownView.locale;
-	const colorTableView = new ColorTableView( locale, { colors, columns, removeButtonLabel, recentlyUsedLabel } );
+	const colorTableView = new ColorTableView( locale, { colors, columns, removeButtonLabel, documentColorsLabel, documentColorsCount } );
 
 	dropdownView.colorTableView = colorTableView;
 	dropdownView.panelView.children.add( colorTableView );

+ 4 - 1
packages/ckeditor5-font/tests/manual/font-color.js

@@ -30,7 +30,10 @@ ClassicEditor
 			'blockQuote',
 			'undo',
 			'redo'
-		]
+		],
+		fontColor: {
+			documentColors: 7
+		}
 	} )
 	.then( editor => {
 		window.editor = editor;