From 6de61ccf779ec23002ab14d72e484460201162ca Mon Sep 17 00:00:00 2001 From: Adam Wight Date: Wed, 22 Jun 2022 13:59:22 +0200 Subject: [PATCH] Fork OutlineControlsWidget Bug: T311223 Change-Id: Id2f9fc89c607c8001e8b150add1ffbcaa318993a --- extension.json | 4 +- ...ve.ui.MWTwoPaneTransclusionDialogLayout.js | 4 +- ....ui.MWTwoPaneTransclusionDialogLayout.less | 2 +- ...i.MWTransclusionOutlineControlsWidget.less | 28 ++++ ....ui.MWTransclusionOutlineControlsWidget.js | 148 ++++++++++++++++++ 5 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 modules/ve-mw/ui/styles/widgets/ve.ui.MWTransclusionOutlineControlsWidget.less create mode 100644 modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineControlsWidget.js diff --git a/extension.json b/extension.json index 2e3810bb1f..d9f90bc753 100644 --- a/extension.json +++ b/extension.json @@ -2137,6 +2137,7 @@ "modules/ve-mw/ui/tools/ve.ui.MWTransclusionDialogTool.js", "modules/ve-mw/ui/contextitems/ve.ui.MWTransclusionContextItem.js", "modules/ve-mw/ui/contextitems/ve.ui.MWDefinedTransclusionContextItem.js", + "modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineControlsWidget.js", "modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineParameterWidget.js", "modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineButtonWidget.js", "modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlinePartWidget.js", @@ -2153,7 +2154,8 @@ "modules/ve-mw/ui/styles/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.less", "modules/ve-mw/ui/styles/pages/ve.ui.MWTransclusionContentPage.css", "modules/ve-mw/ui/styles/pages/ve.ui.MWParameterPage.css", - "modules/ve-mw/ui/styles/pages/ve.ui.MWTemplatePage.css" + "modules/ve-mw/ui/styles/pages/ve.ui.MWTemplatePage.css", + "modules/ve-mw/ui/styles/widgets/ve.ui.MWTransclusionOutlineControlsWidget.less" ], "skinStyles": { "default": [ diff --git a/modules/ve-mw/ui/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.js b/modules/ve-mw/ui/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.js index 9a181b9043..6012750c29 100644 --- a/modules/ve-mw/ui/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.js +++ b/modules/ve-mw/ui/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.js @@ -47,7 +47,7 @@ ve.ui.MWTwoPaneTransclusionDialogLayout = function VeUiMWTwoPaneTransclusionDial this.setMenuPanel( this.outlinePanel ); this.outlineVisible = true; if ( this.editable ) { - this.outlineControlsWidget = new OO.ui.OutlineControlsWidget( + this.outlineControlsWidget = new ve.ui.MWTransclusionOutlineControlsWidget( this.outlineSelectWidget ); } @@ -300,7 +300,7 @@ ve.ui.MWTwoPaneTransclusionDialogLayout.prototype.getOutline = function () { * * If the outline is not editable, the method will return `null`. * - * @return {OO.ui.OutlineControlsWidget|null} The outline controls widget. + * @return {ve.ui.MWTransclusionOutlineControlsWidget|null} The outline controls widget. */ ve.ui.MWTwoPaneTransclusionDialogLayout.prototype.getOutlineControls = function () { return this.outlineControlsWidget; diff --git a/modules/ve-mw/ui/styles/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.less b/modules/ve-mw/ui/styles/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.less index 155e5a038f..0cdefb5596 100644 --- a/modules/ve-mw/ui/styles/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.less +++ b/modules/ve-mw/ui/styles/layouts/ve.ui.MWTwoPaneTransclusionDialogLayout.less @@ -20,7 +20,7 @@ } &-outlinePanel { - .oo-ui-outlineControlsWidget { + .ve-ui-mwTransclusionOutlineControlsWidget { position: absolute; bottom: 0; left: 0; diff --git a/modules/ve-mw/ui/styles/widgets/ve.ui.MWTransclusionOutlineControlsWidget.less b/modules/ve-mw/ui/styles/widgets/ve.ui.MWTransclusionOutlineControlsWidget.less new file mode 100644 index 0000000000..3ae9729cc4 --- /dev/null +++ b/modules/ve-mw/ui/styles/widgets/ve.ui.MWTransclusionOutlineControlsWidget.less @@ -0,0 +1,28 @@ +.ve-ui-mwTransclusionOutlineControlsWidget { + @size-base: 32px; + background-color: #fff; // @background-color-base; aka @wmui-color-base100; + &-items, + &-movers { + float: left; + box-sizing: border-box; + + > .oo-ui-buttonWidget { + height: @size-base; + width: @size-base; + // There's a lot of weird specific margins with weird specific selectors + margin: 0 !important; /* stylelint-disable-line declaration-no-important */ + } + } + + &-items { + float: left; + + .oo-ui-buttonWidget { + float: left; + } + } + + &-movers { + float: right; + } +} diff --git a/modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineControlsWidget.js b/modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineControlsWidget.js new file mode 100644 index 0000000000..05d7f8da8e --- /dev/null +++ b/modules/ve-mw/ui/widgets/ve.ui.MWTransclusionOutlineControlsWidget.js @@ -0,0 +1,148 @@ +/** + * OutlineControlsWidget is a set of controls for an + * {@link OO.ui.OutlineSelectWidget outline select widget}. + * Controls include moving items up and down, removing items, and adding different kinds of items. + * + * **Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}.** + * + * @class + * @extends OO.ui.Widget + * @mixins OO.ui.mixin.GroupElement + * + * @constructor + * @param {OO.ui.OutlineSelectWidget} outline Outline to control + * @param {Object} [config] Configuration options + * @cfg {Object} [abilities] List of abilties + * @cfg {boolean} [abilities.move=true] Allow moving movable items + * @cfg {boolean} [abilities.remove=true] Allow removing removable items + */ +ve.ui.MWTransclusionOutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) { + // Allow passing positional parameters inside the config object + if ( OO.isPlainObject( outline ) && config === undefined ) { + config = outline; + outline = config.outline; + } + + // Configuration initialization + config = config || {}; + + // Parent constructor + ve.ui.MWTransclusionOutlineControlsWidget.super.call( this, config ); + + // Mixin constructors + OO.ui.mixin.GroupElement.call( this, config ); + + // Properties + this.outline = outline; + this.$movers = $( '
' ); + this.upButton = new OO.ui.ButtonWidget( { + framed: false, + icon: 'upTriangle', + title: OO.ui.msg( 'ooui-outline-control-move-up' ) + } ); + this.downButton = new OO.ui.ButtonWidget( { + framed: false, + icon: 'downTriangle', + title: OO.ui.msg( 'ooui-outline-control-move-down' ) + } ); + this.removeButton = new OO.ui.ButtonWidget( { + framed: false, + icon: 'trash', + title: OO.ui.msg( 'ooui-outline-control-remove' ) + } ); + this.abilities = { move: true, remove: true }; + + // Events + outline.connect( this, { + select: 'onOutlineChange', + add: 'onOutlineChange', + remove: 'onOutlineChange' + } ); + this.upButton.connect( this, { + click: [ 'emit', 'move', -1 ] + } ); + this.downButton.connect( this, { + click: [ 'emit', 'move', 1 ] + } ); + this.removeButton.connect( this, { + click: [ 'emit', 'remove' ] + } ); + + // Initialization + this.$element.addClass( 've-ui-mwTransclusionOutlineControlsWidget' ); + this.$group.addClass( 've-ui-mwTransclusionOutlineControlsWidget-items' ); + this.$movers + .addClass( 've-ui-mwTransclusionOutlineControlsWidget-movers' ) + .append( this.upButton.$element, this.downButton.$element, this.removeButton.$element ); + this.$element.append( this.$icon, this.$group, this.$movers ); + this.setAbilities( config.abilities || {} ); +}; + +/* Setup */ + +OO.inheritClass( ve.ui.MWTransclusionOutlineControlsWidget, OO.ui.Widget ); +OO.mixinClass( ve.ui.MWTransclusionOutlineControlsWidget, OO.ui.mixin.GroupElement ); + +/* Events */ + +/** + * @event move + * @param {number} places Number of places to move + */ + +/** + * @event remove + */ + +/* Methods */ + +/** + * Set abilities. + * + * @param {Object} abilities List of abilties + * @param {boolean} [abilities.move] Allow moving movable items + * @param {boolean} [abilities.remove] Allow removing removable items + */ +ve.ui.MWTransclusionOutlineControlsWidget.prototype.setAbilities = function ( abilities ) { + for ( var ability in this.abilities ) { + if ( abilities[ ability ] !== undefined ) { + this.abilities[ ability ] = !!abilities[ ability ]; + } + } + + this.onOutlineChange(); +}; + +/** + * Handle outline change events. + * + * @private + */ +ve.ui.MWTransclusionOutlineControlsWidget.prototype.onOutlineChange = function () { + var items = this.outline.getItems(), + selectedItem = this.outline.findSelectedItem(), + movable = this.abilities.move && selectedItem && selectedItem.isMovable(), + removable = this.abilities.remove && selectedItem && selectedItem.isRemovable(); + + var firstMovable, lastMovable; + if ( movable ) { + var i = -1; + var len = items.length; + while ( ++i < len ) { + if ( items[ i ].isMovable() ) { + firstMovable = items[ i ]; + break; + } + } + i = len; + while ( i-- ) { + if ( items[ i ].isMovable() ) { + lastMovable = items[ i ]; + break; + } + } + } + this.upButton.setDisabled( !movable || selectedItem === firstMovable ); + this.downButton.setDisabled( !movable || selectedItem === lastMovable ); + this.removeButton.setDisabled( !removable ); +};