Explorar o código

Code refactoring and docs in the ToolbarView class.

Aleksander Nowodzinski %!s(int64=6) %!d(string=hai) anos
pai
achega
3edf24ece8
Modificáronse 1 ficheiros con 205 adicións e 119 borrados
  1. 205 119
      packages/ckeditor5-ui/src/toolbar/toolbarview.js

+ 205 - 119
packages/ckeditor5-ui/src/toolbar/toolbarview.js

@@ -14,7 +14,7 @@ import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
 import FocusCycler from '../focuscycler';
 import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
 import ToolbarSeparatorView from './toolbarseparatorview';
-import getResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/resizeobserver';
+import getResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/getresizeobserver';
 import preventDefault from '../bindings/preventdefault.js';
 import Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
@@ -53,7 +53,11 @@ export default class ToolbarView extends View {
 		this.set( 'ariaLabel', t( 'Editor toolbar' ) );
 
 		/**
-		 * Collection of the toolbar items (like buttons).
+		 * Collection of the toolbar items (buttons, drop–downs, etc.).
+		 *
+		 * **Note:** When {@link #shouldGroupWhenFull} is `true`, items that do not fit into a single
+		 * row of a toolbar will be moved to the {@link #groupedItems} collection. Check out
+		 * {@link #shouldGroupWhenFull} to learn more.
 		 *
 		 * @readonly
 		 * @member {module:ui/viewcollection~ViewCollection}
@@ -61,7 +65,18 @@ export default class ToolbarView extends View {
 		this.items = this.createCollection();
 
 		/**
-		 * Tracks information about DOM focus in the list.
+		 * Collection of the toolbar items (buttons, drop–downs, etc.) that do not fit into a single
+		 * row of the toolbar, created on demand when {@link #shouldGroupWhenFull} is `true`. The
+		 * toolbar transfers its items between {@link #items} and this collection dynamically as
+		 * the geometry changes.
+		 *
+		 * @readonly
+		 * @member {module:ui/viewcollection~ViewCollection}
+		 */
+		this.groupedItems = null;
+
+		/**
+		 * Tracks information about DOM focus in the toolbar.
 		 *
 		 * @readonly
 		 * @member {module:utils/focustracker~FocusTracker}
@@ -69,7 +84,8 @@ export default class ToolbarView extends View {
 		this.focusTracker = new FocusTracker();
 
 		/**
-		 * Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
+		 * Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}
+		 * to handle keyboard navigation in the toolbar.
 		 *
 		 * @readonly
 		 * @member {module:utils/keystrokehandler~KeystrokeHandler}
@@ -77,17 +93,30 @@ export default class ToolbarView extends View {
 		this.keystrokes = new KeystrokeHandler();
 
 		/**
-		 * The dropdown that aggregates items that overflow. It is displayed
-		 * at the end of the toolbar and offers a nested toolbar which displays items
-		 * that would normally overflow.
+		 * The dropdown that aggregates {@link #items} that do not fit into a single row of the toolbar.
+		 * It is displayed at the end of the toolbar and offers another (nested) toolbar which displays
+		 * items that would normally overflow. Its content corresponds to the {@link #groupedItems}
+		 * collection.
 		 *
-		 * **Note:** It is created on demand when the space in the toolbar is scarce and only
-		 * if {@link #shouldGroupWhenFull} is `true`.
+		 * **Note:** Created on demand when there is not enough space in the toolbar and only
+		 * if {@link #shouldGroupWhenFull} is `true`. If the geometry of the toolbar changes allowing
+		 * all items in a single row again, the dropdown will hide.
 		 *
 		 * @readonly
-		 * @member {module:ui/dropdown/dropdownview~DropdownView} #overflowedItemsDropdown
+		 * @member {module:ui/dropdown/dropdownview~DropdownView} #groupedItemsDropdown
 		 */
-		this.overflowedItemsDropdown = null;
+		this.groupedItemsDropdown = null;
+
+		/**
+		 * A view containing toolbar {@link #items}.
+		 *
+		 * **Note:** When {@link #shouldGroupWhenFull} is `true`, items that do not fit into a single
+		 * row of a toolbar will be moved to the {@link #groupedItemsDropdown}.
+		 *
+		 * @readonly
+		 * @member {module:ui/toolbar/toolbarview~ToolbarItemsView}
+		 */
+		this.itemsView = this._createItemsView();
 
 		/**
 		 * Controls the orientation of toolbar items.
@@ -106,7 +135,13 @@ export default class ToolbarView extends View {
 		this.set( 'class' );
 
 		/**
-		 * TODO
+		 * When set `true`, the toolbar will automatically group {@link #items} that would normally
+		 * wrap to the next line, when there is not enough space to display them in a single row,
+		 * for instance, if the parent container is narrow.
+		 *
+		 * Grouped items land in the {@link #groupedItemsDropdown drop–down} displayed on–demand
+		 * at the end of the toolbar. When the geometry of the toolbar allows all items to be displayed
+		 * in a single row again, they will be moved from the drop–down back to the main space.
 		 *
 		 * @observable
 		 * @member {Boolean} #shouldGroupWhenFull
@@ -121,24 +156,26 @@ export default class ToolbarView extends View {
 		} );
 
 		/**
-		 * TODO
+		 * A flag used by {@link #_updateGroupedItems} method to make sure no concurrent updates
+		 * are performed to the {@link #items} and {@link #groupedItems}. Because {@link #_updateGroupedItems}
+		 * manages those collections but also is executed upon changes in those collections, this flag
+		 * ensures no infinite loops occur.
 		 *
-		 * @readonly
-		 * @member {itemsView}
-		 */
-		this.itemsView = this._createItemsView();
-
-		/**
-		 * TODO
+		 * **Note:** Used only when {@link #shouldGroupWhenFull} is `true`.
 		 *
 		 * @readonly
 		 * @protected
 		 * @member {Boolean}
 		 */
-		this._updateLock = false;
+		this._updateGroupedItemsLock = false;
 
 		/**
-		 * TODO
+		 * A cached value of the horizontal padding style used by {@link #_updateGroupedItems}
+		 * to manage the {@link #items} that do not fit into a single toolbar line. This value
+		 * can be reused between updates because it is unlikely that the padding will change
+		 * and re–using `Window.getComputedStyle()` is expensive.
+		 *
+		 * **Note:** Set only when {@link #shouldGroupWhenFull} is `true`.
 		 *
 		 * @readonly
 		 * @protected
@@ -147,19 +184,26 @@ export default class ToolbarView extends View {
 		this._horizontalPadding = null;
 
 		/**
-		 * TODO
+		 * An instance of the resize observer that helps dynamically determine the geometry of the toolbar
+		 * and manage items that do not fit into a single row.
+		 *
+		 * **Note:** Created dynamically only when {@link #shouldGroupWhenFull} is `true`.
 		 *
 		 * @readonly
 		 * @protected
-		 * @member {}
+		 * @member {module:utils/dom/getresizeobserver~ResizeObserver}
 		 */
 		this._resizeObserver = null;
 
 		/**
+		 * A top–level collection aggregating building blocks of the toolbar. It mainly exists to
+		 * make sure {@link #items} do not mix up with the {@link #groupedItemsDropdown}, which helps
+		 * a lot with the {@link #shouldGroupWhenFull} logic (no re–ordering issues, exclusions, etc.).
+		 *
 		 *	┌────────────────────────────────── #_components ──────────────────────────────────────┐
 		 *	|                                                                                      |
 		 *	|    ┌──── #itemsView───────┐ ┌──────────────────────┐ ┌──────────────────────────┐    |
-		 *	|    |         ...          | | ToolbarSeparatorView | | #overflowedItemsDropdown |    |
+		 *	|    |         ...          | | ToolbarSeparatorView | |  #groupedItemsDropdown   |    |
 		 *	|    └─────────────────────-┘ └──────────────────────┘ └──────────────────────────┘    |
 		 *	|                             \---------- only when #shouldGroupWhenFull ---------/    |
 		 *	+──────────────────────────────────────────────────────────────────────────────────────┘
@@ -172,7 +216,10 @@ export default class ToolbarView extends View {
 		this._components.add( this.itemsView );
 
 		/**
-		 * Helps cycling over focusable {@link #items} in the toolbar.
+		 * Helps cycling over focusable {@link #items} in the toolbar residing in the {@link #itemsView}.
+		 *
+		 * The top–level cycling (e.g. between the items and the {@link #groupedItemsDropdown}) is
+		 * handled by the {@link #_componentsFocusCycler}.
 		 *
 		 * @readonly
 		 * @protected
@@ -183,15 +230,25 @@ export default class ToolbarView extends View {
 			focusTracker: this.itemsView.focusTracker,
 		} );
 
+		/**
+		 * Helps cycling over building blocks ({@link #_components}) of the toolbar, mainly over
+		 * the {@link #itemsView} and the {@link #groupedItemsDropdown}.
+		 *
+		 * The {@link #items}–level cycling is handled by the {@link #_itemsFocusCycler}.
+		 *
+		 * @readonly
+		 * @protected
+		 * @member {module:ui/focuscycler~FocusCycler}
+		 */
 		this._componentsFocusCycler = new FocusCycler( {
 			focusables: this._components,
 			focusTracker: this.focusTracker,
 		} );
 
-		this.keystrokes.set( 'arrowleft', this._onKeyboardPrevious.bind( this ) );
-		this.keystrokes.set( 'arrowup', this._onKeyboardPrevious.bind( this ) );
-		this.keystrokes.set( 'arrowright', this._onKeyboardNext.bind( this ) );
-		this.keystrokes.set( 'arrowdown', this._onKeyboardNext.bind( this ) );
+		this.keystrokes.set( 'arrowleft', this._focusPrevious.bind( this ) );
+		this.keystrokes.set( 'arrowup', this._focusPrevious.bind( this ) );
+		this.keystrokes.set( 'arrowright', this._focusNext.bind( this ) );
+		this.keystrokes.set( 'arrowdown', this._focusNext.bind( this ) );
 
 		this.setTemplate( {
 			tag: 'div',
@@ -236,11 +293,11 @@ export default class ToolbarView extends View {
 		} );
 
 		this.items.on( 'add', () => {
-			this.update();
+			this._updateGroupedItems();
 		} );
 
 		this.items.on( 'remove', () => {
-			this.update();
+			this._updateGroupedItems();
 		} );
 
 		// Start listening for the keystrokes coming from #element.
@@ -253,8 +310,8 @@ export default class ToolbarView extends View {
 	destroy() {
 		// The dropdown may not be in #items at the moment of toolbar destruction
 		// so let's make sure it's actually destroyed along with the toolbar.
-		if ( this.overflowedItemsDropdown ) {
-			this.overflowedItemsDropdown.destroy();
+		if ( this.groupedItemsDropdown ) {
+			this.groupedItemsDropdown.destroy();
 		}
 
 		if ( this._resizeObserver ) {
@@ -319,36 +376,40 @@ export default class ToolbarView extends View {
 	}
 
 	/**
-	 * When called, if {@link #shouldGroupWhenFull} is `true`, it will check if any of the {@link #items} overflow
-	 * and if so, it will move it to the {@link #overflowedItemsDropdown}.
+	 * When called, if {@link #shouldGroupWhenFull} is `true`, it will check if any of the {@link #items}
+	 * do not fit into a single row of the toolbar, and it will move them to the {@link #groupedItems}
+	 * when it happens.
 	 *
 	 * At the same time, it will also check if there is enough space in the toolbar for the first of the
-	 * "grouped" items in the {@link #overflowedItemsDropdown} to be returned back.
+	 * {@link #groupedItems} to be returned back to {@link #items} and still fit into a single row
+	 * without the toolbar wrapping.
 	 */
-	update() {
+	_updateGroupedItems() {
 		if ( !this.shouldGroupWhenFull ) {
 			return;
 		}
 
-		// Do not check when another check is going to avoid infinite loops.
-		// This method is called upon adding and removing #items and it adds and removes
-		// #items itself, so that would be a disaster.
-		if ( this._updateLock ) {
+		// Do not check when another check is going on to avoid infinite loops.
+		// This method is called when adding and removing #items but at the same time it adds and removes
+		// #items itself.
+		if ( this._updateGroupedItemsLock ) {
 			return;
 		}
 
-		// There's no way to check overflow when there is no element (before #render()).
-		// Or when element has no parent because ClientRects won't work when #element not in DOM.
+		// There's no way to make any decisions concerning geometry when there is no element to work with
+		// (before #render()). Or when element has no parent because ClientRects won't work when
+		// #element is not in DOM.
 		if ( !this.element || !this.element.parentNode ) {
 			return;
 		}
 
-		this._updateLock = true;
+		this._updateGroupedItemsLock = true;
 
 		let wereItemsGrouped;
 
-		// Group #items as long as any overflows. This will happen, for instance,
-		// when the toolbar is getting narrower and there's less and less space in it.
+		// Group #items as long as some wrap to the next row. This will happen, for instance,
+		// when the toolbar is getting narrow and there is not enough space to display all items in
+		// a single row.
 		while ( this._areItemsOverflowing ) {
 			this._groupLastItem();
 
@@ -356,49 +417,33 @@ export default class ToolbarView extends View {
 		}
 
 		// If none were grouped now but there were some items already grouped before,
-		// then maybe let's see if some of them can be ungrouped. This happens when,
+		// then, what the hell, maybe let's see if some of them can be ungrouped. This happens when,
 		// for instance, the toolbar is stretching and there's more space in it than before.
-		if ( !wereItemsGrouped && this._hasOverflowedItemsDropdown ) {
+		if ( !wereItemsGrouped && this.groupedItems && this.groupedItems.length ) {
 			// Ungroup items as long as none are overflowing or there are none to ungroup left.
-			while ( this._overflowedItems.length && !this._areItemsOverflowing ) {
+			while ( this.groupedItems.length && !this._areItemsOverflowing ) {
 				this._ungroupFirstItem();
 			}
 
-			// If the ungrouping ended up with some item overflowing,
-			// put it back to the group toolbar (undo the last ungroup). We don't know whether
-			// an item will overflow or not until we ungroup it (that's a DOM/CSS thing) so this
-			// clean–up is vital.
+			// If the ungrouping ended up with some item wrapping to the next row,
+			// put it back to the group toolbar ("undo the last ungroup"). We don't know whether
+			// an item will wrap or not until we ungroup it (that's a DOM/CSS thing) so this
+			// clean–up is vital for the algorithm.
 			if ( this._areItemsOverflowing ) {
 				this._groupLastItem();
 			}
 		}
 
-		this._updateLock = false;
+		this._updateGroupedItemsLock = false;
 	}
 
 	/**
-	 * TODO
+	 * Returns `true` when any of toolbar {@link #items} visually overflows, for instance if the
+	 * toolbar is narrower than its members. `false` otherwise.
 	 *
-	 * @protected
-	 * @type {module:ui/viewcollection~ViewCollection}
-	 */
-	get _overflowedItems() {
-		return this.overflowedItemsDropdown.toolbarView.items;
-	}
-
-	/**
-	 * TODO
-	 *
-	 * @protected
-	 * @type {Boolean}
-	 */
-	get _hasOverflowedItemsDropdown() {
-		return this.overflowedItemsDropdown && this._components.has( this.overflowedItemsDropdown );
-	}
-
-	/**
-	 * Returns `true` when any of toolbar {@link #items} overflows visually.
-	 * `false` otherwise.
+	 * **Note**: Technically speaking, if not for the {@link #shouldGroupWhenFull}, the items would
+	 * wrap and break the toolbar into multiple rows. Overflowing is only possible when
+	 *  {@link #shouldGroupWhenFull} is `true`.
 	 *
 	 * @protected
 	 * @type {Boolean}
@@ -431,7 +476,7 @@ export default class ToolbarView extends View {
 	}
 
 	/**
-	 * TODO
+	 * Creates the {@link #itemsView} that hosts the members of the {@link #items} collection.
 	 *
 	 * @protected
 	 * @returns {module:ui/view~View}
@@ -446,10 +491,10 @@ export default class ToolbarView extends View {
 	}
 
 	/**
-	 * Creates the {@link #overflowedItemsDropdown} on demand. Used when the space in the toolbar
-	 * is scarce and some items start overflow and need grouping.
+	 * Creates the {@link #groupedItemsDropdown} that hosts the members of the {@link #groupedItems}
+	 * collection when there is not enough space in the toolbar to display all items in a single row.
 	 *
-	 * See {@link #shouldGroupWhenFull}.
+	 * **Note:** Invoked on demand. See {@link #shouldGroupWhenFull} to learn more.
 	 *
 	 * @protected
 	 * @returns {module:ui/dropdown/dropdownview~DropdownView}
@@ -457,34 +502,41 @@ export default class ToolbarView extends View {
 	_createOverflowedItemsDropdown() {
 		const t = this.t;
 		const locale = this.locale;
-		const overflowedItemsDropdown = createDropdown( locale );
+		const groupedItemsDropdown = createDropdown( locale );
 
-		overflowedItemsDropdown.class = 'ck-toolbar__grouped-dropdown';
-		addToolbarToDropdown( overflowedItemsDropdown, [] );
+		groupedItemsDropdown.class = 'ck-toolbar__grouped-dropdown';
+		addToolbarToDropdown( groupedItemsDropdown, [] );
 
-		overflowedItemsDropdown.buttonView.set( {
+		groupedItemsDropdown.buttonView.set( {
 			label: t( 'Show more items' ),
 			tooltip: true,
 			icon: verticalDotsIcon
 		} );
 
-		return overflowedItemsDropdown;
+		this.groupedItems = groupedItemsDropdown.toolbarView.items;
+
+		return groupedItemsDropdown;
 	}
 
 	/**
+	 * Handles forward keyboard navigation in the toolbar.
+	 *
+	 * Because the internal structure of the toolbar has 2 levels, this cannot be handled
+	 * by a simple {@link module:ui/focuscycler~FocusCycler} instance.
+	 *
 	 *	┌────────────────────────────── #_components ────────────────────────────────────────┐
 	 *	|                                                                                    |
 	 *	|    /────▶────\                  /───────▶───────▶───────\          /────▶─────\    |
 	 *	|    |         ▼                  ▲                       ▼          ▲          |    |
 	 *	|    |       ┌─|──── #items ──────|─┐             ┌───────|──────────|───────┐  |    |
-	 *	|    ▲       | \───▶──────────▶───/ |             | #overflowedItemsDropdown |  ▼    |
+	 *	|    ▲       | \───▶──────────▶───/ |             |   #groupedItemsDropdown  |  ▼    |
 	 *	|    |       └─────────────────────-┘             └──────────────────────────┘  |    |
 	 *	|    |                                                                          |    |
 	 *	|    └─────◀───────────◀────────────◀──────────────◀──────────────◀─────────────/    |
 	 *	|                                                                                    |
 	 *	+────────────────────────────────────────────────────────────────────────────────────┘
 	 */
-	_onKeyboardNext( keyEvtData, cancel ) {
+	_focusNext( keyEvtData, cancel ) {
 		if ( this.itemsView.focusTracker.isFocused ) {
 			if ( this._itemsFocusCycler.next === this._itemsFocusCycler.first ) {
 				this._componentsFocusCycler.focusNext();
@@ -501,22 +553,29 @@ export default class ToolbarView extends View {
 	}
 
 	/**
+	 * Handles backward keyboard navigation in the toolbar.
+	 *
+	 * Because the internal structure of the toolbar has 2 levels, this cannot be handled
+	 * by a simple {@link module:ui/focuscycler~FocusCycler} instance.
+	 *
 	 *	┌────────────────────────────── #_components ────────────────────────────────────────┐
 	 *	|                                                                                    |
 	 *	|    /────◀────\                  /───────◀───────◀───────\          /────◀─────\    |
 	 *	|    |         ▲                  ▼                       ▲          ▼          |    |
 	 *	|    |       ┌─|──── #items ──────|─┐             ┌───────|──────────|───────┐  |    |
-	 *	|    ▼       | \───◀──────────◀───/ |             | #overflowedItemsDropdown |  ▲    |
+	 *	|    ▼       | \───◀──────────◀───/ |             |   #groupedItemsDropdown  |  ▲    |
 	 *	|    |       └─────────────────────-┘             └──────────────────────────┘  |    |
 	 *	|    |                                                                          |    |
 	 *	|    └─────▶───────────▶────────────▶──────────────▶──────────────▶─────────────/    |
 	 *	|                                                                                    |
 	 *	+────────────────────────────────────────────────────────────────────────────────────┘
 	 */
-	_onKeyboardPrevious( keyEvtData, cancel ) {
+	_focusPrevious( keyEvtData, cancel ) {
 		if ( this.itemsView.focusTracker.isFocused ) {
 			if ( this._itemsFocusCycler.previous === this._itemsFocusCycler.last ) {
-				if ( this._hasOverflowedItemsDropdown ) {
+				const hasGroupedItemsDropdown = this.groupedItemsDropdown && this._components.has( this.groupedItemsDropdown );
+
+				if ( hasGroupedItemsDropdown ) {
 					this._componentsFocusCycler.focusLast();
 				} else {
 					this._itemsFocusCycler.focusPrevious();
@@ -538,15 +597,15 @@ export default class ToolbarView extends View {
 	}
 
 	/**
-	 * Enables the toolbar functionality that prevents its {@link #items} from overflow
-	 * when the space becomes scarce. Instead, the toolbar items are grouped under the
-	 * {@link #overflowedItemsDropdown dropdown} displayed at the end of the space, which offers its own
-	 * nested toolbar.
+	 * Enables the toolbar functionality that prevents its {@link #items} from overflowing (wrapping
+	 * to the next row) when the space becomes scarce. Instead, the toolbar items are moved to the
+	 * {@link #groupedItems} collection and displayed in a {@link #groupedItemsDropdown} at the end of
+	 * the space, which has its own nested toolbar.
 	 *
-	 * When called, the toolbar will automatically analyze the location of its children and "group"
+	 * When called, the toolbar will automatically analyze the location of its {@link #items} and "group"
 	 * them in the dropdown if necessary. It will also observe the browser window for size changes in
-	 * the future and respond to them by grouping more items or reverting already grouped back to the
-	 * main {@link #element}, depending on the visual space available.
+	 * the future and respond to them by grouping more items or reverting already grouped back, depending
+	 * on the visual space available.
 	 *
 	 * **Note:** Calling this method **before** the toolbar {@link #element} is in a DOM tree and visible (i.e.
 	 * not `display: none`) will cause lots of warnings in the console from the utilities analyzing
@@ -557,66 +616,90 @@ export default class ToolbarView extends View {
 			return;
 		}
 
-		let oldRect;
+		let previousWidth;
 
-		// TODO: stopObserving on destroy();
 		this._resizeObserver = getResizeObserver( ( [ entry ] ) => {
-			if ( !oldRect || oldRect.width !== entry.contentRect.width ) {
-				this.update();
+			if ( !previousWidth || previousWidth.width !== entry.contentRect.width ) {
+				this._updateGroupedItems();
 			}
 
-			oldRect = entry.contentRect.width;
-		} ).observe( this.element );
+			previousWidth = entry.contentRect.width;
+		} );
 
-		this.update();
+		this._resizeObserver.observe( this.element );
+
+		this._updateGroupedItems();
 	}
 
 	/**
-	 * When called it will remove the last {@link #_lastNonGroupedItem regular item} from {@link #items}
-	 * and move it to the {@link #overflowedItemsDropdown}. The opposite of {@link _ungroupFirstItem}.
+	 * The opposite of {@link #_ungroupFirstItem}.
+	 *
+	 * When called it will remove the last item from {@link #items} and move it to the
+	 * {@link #groupedItems} collection (from {@link #itemsView} to {@link #groupedItemsDropdown}).
 	 *
-	 * If the dropdown does not exist or does not belong to {@link #items} it is created and located at
-	 * the end of the collection.
+	 * If the {@link #groupedItemsDropdown} does not exist, it is created and added to {@link #_components}.
 	 *
 	 * @protected
 	 */
 	_groupLastItem() {
-		if ( !this.overflowedItemsDropdown ) {
-			this.overflowedItemsDropdown = this._createOverflowedItemsDropdown();
+		if ( !this.groupedItemsDropdown ) {
+			this.groupedItemsDropdown = this._createOverflowedItemsDropdown();
 		}
 
-		if ( !this._hasOverflowedItemsDropdown ) {
+		if ( !this._components.has( this.groupedItemsDropdown ) ) {
 			this._components.add( new ToolbarSeparatorView() );
-			this._components.add( this.overflowedItemsDropdown );
+			this._components.add( this.groupedItemsDropdown );
 		}
 
-		this._overflowedItems.add( this.items.remove( this.items.last ), 0 );
+		this.groupedItems.add( this.items.remove( this.items.last ), 0 );
 	}
 
 	/**
-	 * Moves the very first item from the toolbar belonging to {@link #overflowedItemsDropdown} back
-	 * to the {@link #items} collection.
+	 * The opposite of {@link #_groupLastItem}.
 	 *
-	 * In some way, it's the opposite of {@link #_groupLastItem}.
+	 * Moves the very first item from the toolbar belonging to {@link #groupedItems} back
+	 * to the {@link #items} collection (from {@link #groupedItemsDropdown} to {@link #itemsView}).
 	 *
 	 * @protected
 	 */
 	_ungroupFirstItem() {
-		this.items.add( this._overflowedItems.remove( this._overflowedItems.first ) );
+		this.items.add( this.groupedItems.remove( this.groupedItems.first ) );
 
-		if ( !this._overflowedItems.length ) {
-			this._components.remove( this.overflowedItemsDropdown );
+		if ( !this.groupedItems.length ) {
+			this._components.remove( this.groupedItemsDropdown );
 			this._components.remove( this._components.last );
 		}
 	}
 }
 
+/**
+ * An inner block of the {@link module:ui/toolbar/toolbarview~ToolbarView} hosting its
+ * {@link module:ui/toolbar/toolbarview~ToolbarView#items}.
+ *
+ * @private
+ * @extends module:ui/view~View
+ */
 class ToolbarItemsView extends View {
+	/**
+	 * @inheritDoc
+	 */
 	constructor( locale ) {
 		super( locale );
 
+		/**
+		 * Collection of the items (buttons, drop–downs, etc.).
+		 *
+		 * @readonly
+		 * @member {module:ui/viewcollection~ViewCollection}
+		 */
 		this.items = this.createCollection();
 
+		/**
+		 * Tracks information about DOM focus in the items view.
+		 *
+		 * @readonly
+		 * @member {module:utils/focustracker~FocusTracker}
+		 */
 		this.focusTracker = new FocusTracker();
 
 		/**
@@ -643,6 +726,9 @@ class ToolbarItemsView extends View {
 		} );
 	}
 
+	/**
+	 * @inheritDoc
+	 */
 	render() {
 		super.render();