Trevor Parscal has uploaded a new change for review.
https://gerrit.wikimedia.org/r/78412
Change subject: [WIP] Toolbar API
......................................................................
[WIP] Toolbar API
Objectives:
* Make it possible to add items to toolbars without having to have all toolbars
know about the items in advance
* Make it possible to specialize an existing tool and have it be used instead
of the base implementation
Approach:
* Tools are named using a path-style category/id/ext system, making them
selectable, the latter component being used to differentiate extended tools
from their base classes, but is ignored during selection
* Toolbars have ToolGroups, which include or exclude tools by category or
category/id, and order them by promoting and demoting selections of tools by
category or category/id
Future:
* Add a way to place available but not yet placed tools in an "overflow" group
* Add a mode to ToolGroup to make the tools a multi-column drop-down style list
with labels so tools with less obvious icons are easier to identify - and
probably use this as the overflow group
Change-Id: I7625f861435a99ce3d7a2b1ece9731aaab1776f8
---
M modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
M modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js
M modules/ve-mw/ui/dialogs/ve.ui.MWReferenceDialog.js
M modules/ve-mw/ui/styles/ve.ui.Tool.css
M modules/ve-mw/ui/tools/buttons/ve.ui.MWLinkButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWMathButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceListButtonTool.js
M modules/ve-mw/ui/tools/buttons/ve.ui.MWTransclusionButtonTool.js
M modules/ve-mw/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js
M modules/ve/init/sa/ve.init.sa.Target.js
M modules/ve/init/ve.init.Target.js
M modules/ve/ui/styles/ve.ui.Tool.css
M modules/ve/ui/tools/buttons/ve.ui.BoldButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.BulletButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.ClearButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.CodeButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.IndentButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.ItalicButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.LanguageButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.LinkButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.NumberButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.OutdentButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js
M modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js
M modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js
M modules/ve/ui/tools/ve.ui.DropdownTool.js
M modules/ve/ui/ve.ui.Context.js
M modules/ve/ui/ve.ui.Tool.js
M modules/ve/ui/ve.ui.ToolFactory.js
M modules/ve/ui/ve.ui.ToolGroup.js
M modules/ve/ui/ve.ui.Toolbar.js
34 files changed, 370 insertions(+), 181 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/12/78412/1
diff --git a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
index 5856153..f0fd700 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
@@ -167,18 +167,6 @@
}
};
-ve.init.mw.ViewPageTarget.static.toolbarTools = [
- { 'items': [ 'undo', 'redo' ] },
- { 'items': [ 'mwFormat' ] },
- { 'items': [ 'bold', 'italic', 'mwLink', 'language', 'code', 'clear' ]
},
- { 'items': [ 'number', 'bullet', 'outdent', 'indent' ] },
- { 'items': [ 'mwMediaInsert', 'mwReference', 'mwReferenceList',
'mwTransclusion', 'mwMath' ] }
-];
-
-ve.init.mw.ViewPageTarget.static.surfaceCommands = [
- 'bold', 'italic', 'mwLink', 'undo', 'redo', 'indent', 'outdent', 'clear'
-];
-
// TODO: Accessibility tooltips and logical tab order for prevButton and
closeButton.
ve.init.mw.ViewPageTarget.saveDialogTemplate = '\
<div class="ve-init-mw-viewPageTarget-saveDialog-head">\
@@ -1887,7 +1875,7 @@
ve.init.mw.ViewPageTarget.prototype.setUpToolbar = function () {
this.toolbar = new ve.ui.SurfaceToolbar( this.surface, { 'shadow':
true, 'actions': true } );
this.toolbar.connect( this, { 'position': 'onToolbarPosition' } );
- this.toolbar.setup( this.constructor.static.toolbarTools );
+ this.toolbar.setup( this.constructor.static.toolbarGroups );
this.surface.addCommands( this.constructor.static.surfaceCommands );
if ( !this.isMobileDevice ) {
this.toolbar.enableFloatable();
diff --git a/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js
b/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js
index 5f275aa..9873ccd 100644
--- a/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js
+++ b/modules/ve-mw/ui/dialogs/ve.ui.MWMediaEditDialog.js
@@ -33,16 +33,6 @@
ve.ui.MWMediaEditDialog.static.icon = 'picture';
-ve.ui.MWMediaEditDialog.static.toolbarTools = [
- { 'items': ['undo', 'redo'] },
- { 'items': ['bold', 'italic', 'mwLink', 'clear'] },
- { 'items': ['mwReference', 'mwTransclusion', 'mwMath'] }
-];
-
-ve.ui.MWMediaEditDialog.static.surfaceCommands = [
- 'bold', 'italic', 'mwLink', 'undo', 'redo', 'clear'
-];
-
/* Methods */
/** */
@@ -98,8 +88,8 @@
new ve.dm.ElementLinearData( doc.getStore(), data ),
{
'$$': this.frame.$$,
- 'tools': this.constructor.static.toolbarTools,
- 'commands': this.constructor.static.surfaceCommands
+ 'tools': ve.init.mw.Target.static.toolbarGroups,
+ 'commands': ve.init.mw.Target.static.surfaceCommands
}
);
diff --git a/modules/ve-mw/ui/dialogs/ve.ui.MWReferenceDialog.js
b/modules/ve-mw/ui/dialogs/ve.ui.MWReferenceDialog.js
index 9e12c40..93a7363 100644
--- a/modules/ve-mw/ui/dialogs/ve.ui.MWReferenceDialog.js
+++ b/modules/ve-mw/ui/dialogs/ve.ui.MWReferenceDialog.js
@@ -33,15 +33,6 @@
ve.ui.MWReferenceDialog.static.icon = 'reference';
-ve.ui.MWReferenceDialog.static.toolbarTools = [
- { 'items': ['undo', 'redo'] },
- { 'items': ['bold', 'italic', 'mwLink', 'clear', 'mwMediaInsert',
'mwTransclusion'] }
-];
-
-ve.ui.MWReferenceDialog.static.surfaceCommands = [
- 'bold', 'italic', 'mwLink', 'undo', 'redo', 'clear'
-];
-
/* Methods */
/**
@@ -303,8 +294,8 @@
new ve.dm.ElementLinearData( doc.getStore(), data ),
{
'$$': this.frame.$$,
- 'tools': this.constructor.static.toolbarTools,
- 'commands': this.constructor.static.surfaceCommands
+ 'tools': ve.init.mw.Target.static.toolbarGroups,
+ 'commands': ve.init.mw.Target.static.surfaceCommands
}
);
diff --git a/modules/ve-mw/ui/styles/ve.ui.Tool.css
b/modules/ve-mw/ui/styles/ve.ui.Tool.css
index 5c40410..5481102 100644
--- a/modules/ve-mw/ui/styles/ve.ui.Tool.css
+++ b/modules/ve-mw/ui/styles/ve.ui.Tool.css
@@ -5,6 +5,6 @@
* @license The MIT License (MIT); see LICENSE.txt
*/
-.ve-ui-dropdownTool-mwFormat ul {
+.ve-ui-mwFormatDropdownTool ul {
font-size: 80%;
}
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWLinkButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWLinkButtonTool.js
index 613b8ca..8264a28 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWLinkButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWLinkButtonTool.js
@@ -25,7 +25,7 @@
/* Static Members */
-ve.ui.MWLinkButtonTool.static.name = 'mwLink';
+ve.ui.MWLinkButtonTool.static.name = 'meta/link/mw';
ve.ui.MWLinkButtonTool.static.inspector = 'mwLink';
@@ -35,10 +35,10 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwLink', ve.ui.MWLinkButtonTool );
+ve.ui.toolFactory.register( 'meta/link/mw', ve.ui.MWLinkButtonTool );
-ve.ui.commandRegistry.register( 'mwLink', 'inspector', 'open', 'mwLink' );
+ve.ui.commandRegistry.register( 'meta/link/mw', 'inspector', 'open', 'mwLink'
);
ve.ui.triggerRegistry.register(
- 'mwLink', { 'mac': new ve.ui.Trigger( 'cmd+k' ), 'pc': new
ve.ui.Trigger( 'ctrl+k' ) }
+ 'meta/link/mw', { 'mac': new ve.ui.Trigger( 'cmd+k' ), 'pc': new
ve.ui.Trigger( 'ctrl+k' ) }
);
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMathButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMathButtonTool.js
index c97e212..c4ae5e0 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMathButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMathButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.MWMathButtonTool.static.name = 'mwMath';
+ve.ui.MWMathButtonTool.static.name = 'object/math/mw';
ve.ui.MWMathButtonTool.static.icon = 'math';
@@ -37,4 +37,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwMath', ve.ui.MWMathButtonTool );
+ve.ui.toolFactory.register( 'object/math/mw', ve.ui.MWMathButtonTool );
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js
index 2e1fa5e..e4802c8 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaEditButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.MWMediaEditButtonTool.static.name = 'mwMediaEdit';
+ve.ui.MWMediaEditButtonTool.static.name = 'object/mediaEdit/mw';
ve.ui.MWMediaEditButtonTool.static.icon = 'picture';
@@ -35,6 +35,8 @@
ve.ui.MWMediaEditButtonTool.static.modelClasses = [ ve.dm.MWBlockImageNode ];
+ve.ui.MWMediaEditButtonTool.static.autoAdd = false;
+
/* Registration */
-ve.ui.toolFactory.register( 'mwMediaEdit', ve.ui.MWMediaEditButtonTool );
+ve.ui.toolFactory.register( 'object/mediaEdit/mw', ve.ui.MWMediaEditButtonTool
);
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js
index c569fb6..d5a86f7 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWMediaInsertButtonTool.js
@@ -26,7 +26,7 @@
/* Static Properties */
-ve.ui.MWMediaInsertButtonTool.static.name = 'mwMediaInsert';
+ve.ui.MWMediaInsertButtonTool.static.name = 'object/mediaInsert/mw';
ve.ui.MWMediaInsertButtonTool.static.icon = 'picture';
@@ -36,4 +36,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwMediaInsert', ve.ui.MWMediaInsertButtonTool );
+ve.ui.toolFactory.register( 'object/mediaInsert/mw',
ve.ui.MWMediaInsertButtonTool );
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceButtonTool.js
index 837b326..b07bbfd 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceButtonTool.js
@@ -26,7 +26,7 @@
/* Static Properties */
-ve.ui.MWReferenceButtonTool.static.name = 'mwReference';
+ve.ui.MWReferenceButtonTool.static.name = 'object/reference/mw';
ve.ui.MWReferenceButtonTool.static.icon = 'reference';
@@ -38,4 +38,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwReference', ve.ui.MWReferenceButtonTool );
+ve.ui.toolFactory.register( 'object/reference/mw', ve.ui.MWReferenceButtonTool
);
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceListButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceListButtonTool.js
index afe940e..6fbcd36 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceListButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWReferenceListButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.MWReferenceListButtonTool.static.name = 'mwReferenceList';
+ve.ui.MWReferenceListButtonTool.static.name = 'object/referenceList/mw';
ve.ui.MWReferenceListButtonTool.static.icon = 'references';
@@ -37,4 +37,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwReferenceList', ve.ui.MWReferenceListButtonTool
);
+ve.ui.toolFactory.register( 'object/referenceList/mw',
ve.ui.MWReferenceListButtonTool );
diff --git a/modules/ve-mw/ui/tools/buttons/ve.ui.MWTransclusionButtonTool.js
b/modules/ve-mw/ui/tools/buttons/ve.ui.MWTransclusionButtonTool.js
index f8d3757..8b88888 100644
--- a/modules/ve-mw/ui/tools/buttons/ve.ui.MWTransclusionButtonTool.js
+++ b/modules/ve-mw/ui/tools/buttons/ve.ui.MWTransclusionButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.MWTransclusionButtonTool.static.name = 'mwTransclusion';
+ve.ui.MWTransclusionButtonTool.static.name = 'object/transclusion/mw';
ve.ui.MWTransclusionButtonTool.static.icon = 'template';
@@ -37,4 +37,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'mwTransclusion', ve.ui.MWTransclusionButtonTool );
+ve.ui.toolFactory.register( 'object/transclusion/mw',
ve.ui.MWTransclusionButtonTool );
diff --git a/modules/ve-mw/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js
b/modules/ve-mw/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js
index 504212e..86751c5 100644
--- a/modules/ve-mw/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js
+++ b/modules/ve-mw/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js
@@ -16,6 +16,9 @@
ve.ui.MWFormatDropdownTool = function VeUiMwFormatDropdownTool( toolbar,
config ) {
// Parent constructor
ve.ui.FormatDropdownTool.call( this, toolbar, config );
+
+ // Initialize
+ this.$.addClass( 've-ui-mwFormatDropdownTool' );
};
/* Inheritance */
@@ -24,9 +27,7 @@
/* Static Properties */
-ve.ui.MWFormatDropdownTool.static.name = 'mwFormat';
-
-ve.ui.MWFormatDropdownTool.static.cssName = 'format
ve-ui-dropdownTool-mwFormat';
+ve.ui.MWFormatDropdownTool.static.name = 'format/convert/mw';
ve.ui.MWFormatDropdownTool.static.items[1].data.type = 'mwHeading';
ve.ui.MWFormatDropdownTool.static.items[1].label =
'visualeditor-formatdropdown-format-mw-heading1';
@@ -42,9 +43,11 @@
ve.ui.MWFormatDropdownTool.static.items[6].label =
'visualeditor-formatdropdown-format-mw-heading6';
ve.ui.MWFormatDropdownTool.static.items[7].data.type = 'mwPreformatted';
-// Move the H1 (item 1 in the list) to the end (7) so as to make it less
prominent and tempting to users
-ve.ui.MWFormatDropdownTool.static.items.splice( 7, 0,
ve.ui.MWFormatDropdownTool.static.items.splice( 1, 1 )[0] );
+// Move H1 (index 0) to the end (index 7) so as to make it less prominent and
tempting to users
+ve.ui.MWFormatDropdownTool.static.items.splice(
+ 7, 0, ve.ui.MWFormatDropdownTool.static.items.splice( 1, 1 )[0]
+);
/* Registration */
-ve.ui.toolFactory.register( 'mwFormat', ve.ui.MWFormatDropdownTool );
+ve.ui.toolFactory.register( 'format/convert/mw', ve.ui.MWFormatDropdownTool );
diff --git a/modules/ve/init/sa/ve.init.sa.Target.js
b/modules/ve/init/sa/ve.init.sa.Target.js
index ca4b965..c697dfb 100644
--- a/modules/ve/init/sa/ve.init.sa.Target.js
+++ b/modules/ve/init/sa/ve.init.sa.Target.js
@@ -30,7 +30,7 @@
// Initialization
this.toolbar.$.addClass( 've-init-sa-target-toolbar' );
- this.toolbar.setup( this.constructor.static.toolbarTools );
+ this.toolbar.setup( this.constructor.static.toolbarGroups );
this.toolbar.enableFloatable();
this.$.append( this.toolbar.$, this.surface.$ );
diff --git a/modules/ve/init/ve.init.Target.js
b/modules/ve/init/ve.init.Target.js
index 54db1d6..3459fb7 100644
--- a/modules/ve/init/ve.init.Target.js
+++ b/modules/ve/init/ve.init.Target.js
@@ -29,20 +29,46 @@
/* Static Properties */
-ve.init.Target.static.toolbarTools = [
- { 'items': ['undo', 'redo'] },
- { 'items': ['format'] },
- { 'items': ['bold', 'italic', 'link', 'code', 'language', 'clear'] },
- { 'items': ['number', 'bullet', 'outdent', 'indent'] }
+ve.init.Target.static.toolbarGroups = [
+ {
+ 'include': [ 'history' ],
+ 'promote': [
+ 'history/undo',
+ 'history/redo'
+ ]
+ },
+ {
+ 'include': [ 'format' ],
+ 'promote': [ 'format/convert' ]
+ },
+ {
+ 'include': [ 'textStyle', 'meta', 'utility/clear' ],
+ 'promote': [
+ 'textStyle/bold',
+ 'textStyle/italic',
+ 'meta/link'
+ ],
+ 'demote': [ 'utility/clear' ]
+ },
+ {
+ 'include': [ 'structure' ],
+ 'promote': [
+ 'structure/number',
+ 'structure/bullet',
+ 'structure/outdent',
+ 'structure/indent'
+ ]
+ },
+ { 'include': [ 'object' ] }
];
ve.init.Target.static.surfaceCommands = [
- 'bold',
- 'italic',
- 'link',
- //'language',
- 'undo',
- 'redo',
- 'indent',
- 'outdent'
+ 'history/undo',
+ 'history/redo',
+ 'textStyle/bold',
+ 'textStyle/italic',
+ 'meta/link',
+ 'utility/clear',
+ 'structure/indent',
+ 'structure/outdent'
];
diff --git a/modules/ve/ui/styles/ve.ui.Tool.css
b/modules/ve/ui/styles/ve.ui.Tool.css
index ac83650..61c1f6a 100644
--- a/modules/ve/ui/styles/ve.ui.Tool.css
+++ b/modules/ve/ui/styles/ve.ui.Tool.css
@@ -32,6 +32,11 @@
vertical-align: middle;
border-radius: 0.25em;
border: solid 1px transparent;
+ -webkit-transition: border-color 300ms;
+ -moz-transition: border-color 300ms;
+ -ms-transition: border-color 300ms;
+ -o-transition: border-color 300ms;
+ transition: border-color 300ms;
}
.ve-ui-toolGroup:hover {
@@ -148,45 +153,45 @@
/* ve.ui.FormatDropdownTool */
-.ve-ui-dropdownTool-format {
+.ve-ui-formatDropdownTool {
width: 8em;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="paragraph"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="paragraph"]
.ve-ui-labeledElement-label {
font-weight: normal;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-1"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-1"]
.ve-ui-labeledElement-label {
font-size: 188%;
font-weight: normal;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-2"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-2"]
.ve-ui-labeledElement-label {
font-size: 150%;
font-weight: normal;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-3"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-3"]
.ve-ui-labeledElement-label {
font-size: 132%;
font-weight: bold;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-4"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-4"]
.ve-ui-labeledElement-label {
font-size: 116%;
font-weight: bold;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-5"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-5"]
.ve-ui-labeledElement-label {
font-size: 100%;
font-weight: bold;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="heading-6"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="heading-6"]
.ve-ui-labeledElement-label {
font-size: 80%;
font-weight: bold;
}
-.ve-ui-dropdownTool-format .ve-ui-optionWidget[rel="preformatted"]
.ve-ui-labeledElement-label {
+.ve-ui-formatDropdownTool .ve-ui-optionWidget[rel="preformatted"]
.ve-ui-labeledElement-label {
font-family: monospace, "Courier New";
}
diff --git a/modules/ve/ui/tools/buttons/ve.ui.BoldButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.BoldButtonTool.js
index cd6b950..0ef6570 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.BoldButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.BoldButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.BoldButtonTool.static.name = 'bold';
+ve.ui.BoldButtonTool.static.name = 'textStyle/bold';
ve.ui.BoldButtonTool.static.icon = {
'default': 'bold-a',
@@ -61,10 +61,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'bold', ve.ui.BoldButtonTool );
+ve.ui.toolFactory.register( 'textStyle/bold', ve.ui.BoldButtonTool );
-ve.ui.commandRegistry.register( 'bold', 'annotation', 'toggle',
'textStyle/bold' );
+ve.ui.commandRegistry.register( 'textStyle/bold', 'annotation', 'toggle',
'textStyle/bold' );
ve.ui.triggerRegistry.register(
- 'bold', { 'mac': new ve.ui.Trigger( 'cmd+b' ), 'pc': new ve.ui.Trigger(
'ctrl+b' ) }
+ 'textStyle/bold',
+ { 'mac': new ve.ui.Trigger( 'cmd+b' ), 'pc': new ve.ui.Trigger(
'ctrl+b' ) }
);
diff --git a/modules/ve/ui/tools/buttons/ve.ui.BulletButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.BulletButtonTool.js
index ea20ec1..07ca8d8 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.BulletButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.BulletButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.BulletButtonTool.static.name = 'bullet';
+ve.ui.BulletButtonTool.static.name = 'structure/bullet';
ve.ui.BulletButtonTool.static.icon = 'bullet-list';
@@ -35,4 +35,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'bullet', ve.ui.BulletButtonTool );
+ve.ui.toolFactory.register( 'structure/bullet', ve.ui.BulletButtonTool );
diff --git a/modules/ve/ui/tools/buttons/ve.ui.ClearButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.ClearButtonTool.js
index 763c3ff..451a4ff 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.ClearButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.ClearButtonTool.js
@@ -28,7 +28,7 @@
/* Static Properties */
-ve.ui.ClearButtonTool.static.name = 'clear';
+ve.ui.ClearButtonTool.static.name = 'utility/clear';
ve.ui.ClearButtonTool.static.icon = 'clear';
@@ -59,10 +59,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'clear', ve.ui.ClearButtonTool );
+ve.ui.toolFactory.register( 'utility/clear', ve.ui.ClearButtonTool );
-ve.ui.commandRegistry.register( 'clear', 'annotation', 'clearAll' );
+ve.ui.commandRegistry.register( 'utility/clear', 'annotation', 'clearAll' );
ve.ui.triggerRegistry.register(
- 'clear', { 'mac': new ve.ui.Trigger( 'cmd+\\' ), 'pc': new
ve.ui.Trigger( 'ctrl+\\' ) }
+ 'utility/clear',
+ { 'mac': new ve.ui.Trigger( 'cmd+\\' ), 'pc': new ve.ui.Trigger(
'ctrl+\\' ) }
);
diff --git a/modules/ve/ui/tools/buttons/ve.ui.CodeButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.CodeButtonTool.js
index ca462cc..a8a8eef 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.CodeButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.CodeButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.CodeButtonTool.static.name = 'code';
+ve.ui.CodeButtonTool.static.name = 'textStyle/code';
ve.ui.CodeButtonTool.static.icon = 'code';
@@ -35,6 +35,6 @@
/* Registration */
-ve.ui.toolFactory.register( 'code', ve.ui.CodeButtonTool );
+ve.ui.toolFactory.register( 'textStyle/code', ve.ui.CodeButtonTool );
-ve.ui.commandRegistry.register( 'code', 'annotation', 'toggle',
'textStyle/code' );
+ve.ui.commandRegistry.register( 'textStyle/code', 'annotation', 'toggle',
'textStyle/code' );
diff --git a/modules/ve/ui/tools/buttons/ve.ui.IndentButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.IndentButtonTool.js
index 43018ea..1c35dd6 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.IndentButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.IndentButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.IndentButtonTool.static.name = 'indent';
+ve.ui.IndentButtonTool.static.name = 'structure/indent';
ve.ui.IndentButtonTool.static.icon = 'indent-list';
@@ -35,8 +35,8 @@
/* Registration */
-ve.ui.toolFactory.register( 'indent', ve.ui.IndentButtonTool );
+ve.ui.toolFactory.register( 'structure/indent', ve.ui.IndentButtonTool );
-ve.ui.commandRegistry.register( 'indent', 'indentation', 'increase' );
+ve.ui.commandRegistry.register( 'structure/indent', 'indentation', 'increase'
);
-ve.ui.triggerRegistry.register( 'indent', new ve.ui.Trigger( 'tab' ) );
+ve.ui.triggerRegistry.register( 'structure/indent', new ve.ui.Trigger( 'tab' )
);
diff --git a/modules/ve/ui/tools/buttons/ve.ui.ItalicButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.ItalicButtonTool.js
index adcc886..1b016ed 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.ItalicButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.ItalicButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.ItalicButtonTool.static.name = 'italic';
+ve.ui.ItalicButtonTool.static.name = 'textStyle/italic';
ve.ui.ItalicButtonTool.static.icon = {
'default': 'italic-a',
@@ -61,12 +61,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'italic', ve.ui.ItalicButtonTool );
+ve.ui.toolFactory.register( 'textStyle/italic', ve.ui.ItalicButtonTool );
-ve.ui.commandRegistry.register(
- 'italic', 'annotation', 'toggle', 'textStyle/italic'
-);
+ve.ui.commandRegistry.register( 'textStyle/italic', 'annotation', 'toggle',
'textStyle/italic' );
ve.ui.triggerRegistry.register(
- 'italic', { 'mac': new ve.ui.Trigger( 'cmd+i' ), 'pc': new
ve.ui.Trigger( 'ctrl+i' ) }
+ 'textStyle/italic',
+ { 'mac': new ve.ui.Trigger( 'cmd+i' ), 'pc': new ve.ui.Trigger(
'ctrl+i' ) }
);
diff --git a/modules/ve/ui/tools/buttons/ve.ui.LanguageButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.LanguageButtonTool.js
index b9397ff..53861eb 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.LanguageButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.LanguageButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.LanguageButtonTool.static.name = 'language';
+ve.ui.LanguageButtonTool.static.name = 'meta/language';
ve.ui.LanguageButtonTool.static.icon = 'language';
@@ -37,6 +37,6 @@
/* Registration */
-ve.ui.toolFactory.register( 'language', ve.ui.LanguageButtonTool );
+ve.ui.toolFactory.register( 'meta/language', ve.ui.LanguageButtonTool );
-ve.ui.commandRegistry.register( 'language', 'inspector', 'open', 'language' );
\ No newline at end of file
+ve.ui.commandRegistry.register( 'meta/language', 'inspector', 'open',
'language' );
\ No newline at end of file
diff --git a/modules/ve/ui/tools/buttons/ve.ui.LinkButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.LinkButtonTool.js
index 4aa17d9..4f8af59 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.LinkButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.LinkButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.LinkButtonTool.static.name = 'link';
+ve.ui.LinkButtonTool.static.name = 'meta/link';
ve.ui.LinkButtonTool.static.icon = 'link';
@@ -37,10 +37,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'link', ve.ui.LinkButtonTool );
+ve.ui.toolFactory.register( 'meta/link', ve.ui.LinkButtonTool );
-ve.ui.commandRegistry.register( 'link', 'inspector', 'open', 'link' );
+ve.ui.commandRegistry.register( 'meta/link', 'inspector', 'open', 'link' );
ve.ui.triggerRegistry.register(
- 'link', { 'mac': new ve.ui.Trigger( 'cmd+k' ), 'pc': new ve.ui.Trigger(
'ctrl+k' ) }
+ 'meta/link',
+ { 'mac': new ve.ui.Trigger( 'cmd+k' ), 'pc': new ve.ui.Trigger(
'ctrl+k' ) }
);
diff --git a/modules/ve/ui/tools/buttons/ve.ui.NumberButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.NumberButtonTool.js
index 9d49af2..9ec2d98 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.NumberButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.NumberButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.NumberButtonTool.static.name = 'number';
+ve.ui.NumberButtonTool.static.name = 'structure/number';
ve.ui.NumberButtonTool.static.icon = 'number-list';
@@ -35,4 +35,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'number', ve.ui.NumberButtonTool );
+ve.ui.toolFactory.register( 'structure/number', ve.ui.NumberButtonTool );
diff --git a/modules/ve/ui/tools/buttons/ve.ui.OutdentButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.OutdentButtonTool.js
index b8b093e..ac13547 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.OutdentButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.OutdentButtonTool.js
@@ -25,7 +25,7 @@
/* Static Properties */
-ve.ui.OutdentButtonTool.static.name = 'outdent';
+ve.ui.OutdentButtonTool.static.name = 'structure/outdent';
ve.ui.OutdentButtonTool.static.icon = 'outdent-list';
@@ -35,9 +35,9 @@
/* Registration */
-ve.ui.toolFactory.register( 'outdent', ve.ui.OutdentButtonTool );
+ve.ui.toolFactory.register( 'structure/outdent', ve.ui.OutdentButtonTool );
// TODO: Consistency between outdent and unindent.
-ve.ui.commandRegistry.register( 'outdent', 'indentation', 'decrease' );
+ve.ui.commandRegistry.register( 'structure/outdent', 'indentation', 'decrease'
);
-ve.ui.triggerRegistry.register( 'outdent', new ve.ui.Trigger( 'shift+tab' ) );
+ve.ui.triggerRegistry.register( 'structure/outdent', new ve.ui.Trigger(
'shift+tab' ) );
diff --git a/modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js
index 8cee7ed..10941fd 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js
@@ -31,7 +31,7 @@
/* Static Properties */
-ve.ui.RedoButtonTool.static.name = 'redo';
+ve.ui.RedoButtonTool.static.name = 'history/redo';
ve.ui.RedoButtonTool.static.icon = 'redo';
@@ -62,13 +62,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'redo', ve.ui.RedoButtonTool );
+ve.ui.toolFactory.register( 'history/redo', ve.ui.RedoButtonTool );
-ve.ui.commandRegistry.register(
- 'redo', 'history', 'redo'
-);
+ve.ui.commandRegistry.register( 'history/redo', 'history', 'redo' );
ve.ui.triggerRegistry.register(
- 'redo', { 'mac': new ve.ui.Trigger( 'cmd+shift+z' ), 'pc': new
ve.ui.Trigger( 'ctrl+shift+z' ) }
+ 'history/redo',
+ { 'mac': new ve.ui.Trigger( 'cmd+shift+z' ), 'pc': new ve.ui.Trigger(
'ctrl+shift+z' ) }
);
-
diff --git a/modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js
b/modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js
index 21cb027..5865eae 100644
--- a/modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js
+++ b/modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js
@@ -31,7 +31,7 @@
/* Static Properties */
-ve.ui.UndoButtonTool.static.name = 'undo';
+ve.ui.UndoButtonTool.static.name = 'history/undo';
ve.ui.UndoButtonTool.static.icon = 'undo';
@@ -62,13 +62,11 @@
/* Registration */
-ve.ui.toolFactory.register( 'undo', ve.ui.UndoButtonTool );
+ve.ui.toolFactory.register( 'history/undo', ve.ui.UndoButtonTool );
-ve.ui.commandRegistry.register(
- 'undo', 'history', 'undo'
-);
+ve.ui.commandRegistry.register( 'history/undo', 'history', 'undo' );
ve.ui.triggerRegistry.register(
- 'undo', { 'mac': new ve.ui.Trigger( 'cmd+z' ), 'pc': new ve.ui.Trigger(
'ctrl+z' ) }
+ 'history/undo',
+ { 'mac': new ve.ui.Trigger( 'cmd+z' ), 'pc': new ve.ui.Trigger(
'ctrl+z' ) }
);
-
diff --git a/modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js
b/modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js
index fae97e8..1ba1342 100644
--- a/modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js
+++ b/modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js
@@ -22,6 +22,7 @@
ve.ui.DropdownTool.call( this, toolbar, config );
// Initialization
+ this.$.addClass( 've-ui-formatDropdownTool' );
for ( i = 0, len = items.length; i < len; i++ ) {
item = items[i];
items[i] = new ve.ui.MenuItemWidget(
@@ -37,7 +38,7 @@
/* Static Properties */
-ve.ui.FormatDropdownTool.static.name = 'format';
+ve.ui.FormatDropdownTool.static.name = 'format/convert';
ve.ui.FormatDropdownTool.static.titleMessage =
'visualeditor-formatdropdown-title';
@@ -174,4 +175,4 @@
/* Registration */
-ve.ui.toolFactory.register( 'format', ve.ui.FormatDropdownTool );
+ve.ui.toolFactory.register( 'format/convert', ve.ui.FormatDropdownTool );
diff --git a/modules/ve/ui/tools/ve.ui.DropdownTool.js
b/modules/ve/ui/tools/ve.ui.DropdownTool.js
index 89e3377..47e5deb 100644
--- a/modules/ve/ui/tools/ve.ui.DropdownTool.js
+++ b/modules/ve/ui/tools/ve.ui.DropdownTool.js
@@ -36,10 +36,7 @@
// Initialization
this.$
.append( this.$icon, this.$label, this.menu.$ )
- .addClass(
- 've-ui-dropdownTool ve-ui-dropdownTool-' +
- ( this.constructor.static.cssName ||
this.constructor.static.name )
- );
+ .addClass( 've-ui-dropdownTool' );
if ( this.constructor.static.titleMessage ) {
this.$.attr( 'title', ve.msg(
this.constructor.static.titleMessage ) );
}
diff --git a/modules/ve/ui/ve.ui.Context.js b/modules/ve/ui/ve.ui.Context.js
index bfb96f8..5e6e454 100644
--- a/modules/ve/ui/ve.ui.Context.js
+++ b/modules/ve/ui/ve.ui.Context.js
@@ -222,7 +222,7 @@
this.toolbar.destroy();
}
this.toolbar = new ve.ui.SurfaceToolbar( this.surface );
- this.toolbar.setup( [ { 'items' : tools } ] );
+ this.toolbar.setup( [ { 'include' : tools } ] );
this.$menu.append( this.toolbar.$ );
this.show();
this.toolbar.initialize();
diff --git a/modules/ve/ui/ve.ui.Tool.js b/modules/ve/ui/ve.ui.Tool.js
index 5ae3ab5..3ac601d 100644
--- a/modules/ve/ui/ve.ui.Tool.js
+++ b/modules/ve/ui/ve.ui.Tool.js
@@ -48,17 +48,6 @@
ve.ui.Tool.static.name = '';
/**
- * CSS class name, rendered as ve-ui-dropdownTool-cssName
- *
- * If this is left as null, static.name is used instead.
- *
- * @abstract
- * @static
- * @property {string}
- */
-ve.ui.Tool.static.cssName = null;
-
-/**
* Message key for tool title.
*
* @abstract
@@ -66,6 +55,14 @@
* @property {string}
*/
ve.ui.Tool.static.titleMessage = null;
+
+/**
+ * Tool should be automatically added to toolbars.
+ *
+ * @static
+ * @property {boolean}
+ */
+ve.ui.Tool.static.autoAdd = true;
/**
* Check if this tool can be used on a model.
@@ -116,7 +113,6 @@
* Combines trigger i18n with tooltip message if trigger exists.
* Otherwise defaults to titleMessage value.
*
- * @abstract
* @method
* @chainable
*/
@@ -131,3 +127,14 @@
this.$.attr( 'title', labelText );
return this;
};
+
+/**
+ * Destory tool.
+ *
+ * @method
+ */
+ve.ui.Tool.prototype.destroy = function () {
+ this.toolbar.disconnect( this );
+ ve.ui.triggerRegistry.disconnect( this );
+ this.$.remove();
+};
diff --git a/modules/ve/ui/ve.ui.ToolFactory.js
b/modules/ve/ui/ve.ui.ToolFactory.js
index dba608b..cd9e747 100644
--- a/modules/ve/ui/ve.ui.ToolFactory.js
+++ b/modules/ve/ui/ve.ui.ToolFactory.js
@@ -15,6 +15,9 @@
ve.ui.ToolFactory = function VeUiToolFactory() {
// Parent constructor
ve.Factory.call( this );
+
+ // Properties
+ this.tools = {};
};
/* Inheritance */
@@ -24,6 +27,110 @@
/* Methods */
/**
+ * @inheritdoc
+ */
+ve.ui.ToolFactory.prototype.register = function ( name, constructor ) {
+ var parts = name.split( '/' ),
+ baseName = parts.slice( 0, 2 ).join( '/' );
+
+ if (
+ // First entry
+ !this.tools[baseName] ||
+ // Overriding entry
+ constructor.prototype instanceof
this.registry[this.tools[baseName].name]
+ ) {
+ this.tools[baseName] = {
+ 'name': name,
+ 'type': parts[0],
+ 'id': parts[1],
+ 'ext': parts[2]
+ };
+ }
+
+ ve.Factory.prototype.register.call( this, name, constructor );
+};
+
+ve.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote,
demote ) {
+ var i, len, tool, parts, baseName,
+ tools = {},
+ promoted = [],
+ demoted = [],
+ auto = [];
+
+ // Collect included tools
+ for ( i = 0, len = include.length; i < len; i++ ) {
+ parts = include[i].split( '/' );
+ for ( baseName in this.tools ) {
+ tool = this.tools[baseName];
+ if (
+ // Types match
+ parts[0] === tool.type &&
+ // Either no ID was specified and tool can be
automatically added or IDs matche
+ ( ( !parts[1] &&
this.registry[tool.name].static.autoAdd ) || parts[1] === tool.id )
+ ) {
+ tools[baseName] = tool;
+ }
+
+ }
+ }
+
+ // Remove excluded tools
+ for ( i = 0, len = exclude.length; i < len; i++ ) {
+ parts = exclude[i].split( '/' );
+ for ( baseName in tools ) {
+ tool = tools[baseName];
+ if (
+ // Types match
+ parts[0] === tool.type &&
+ // Either no ID was specified or IDs match
+ ( !parts[1] || parts[1] === tool.id )
+ ) {
+ delete tools[baseName];
+ }
+ }
+ }
+
+ // Promotion
+ for ( i = 0, len = promote.length; i < len; i++ ) {
+ parts = promote[i].split( '/' );
+ for ( baseName in tools ) {
+ tool = tools[baseName];
+ if (
+ // Types match
+ parts[0] === tool.type &&
+ // Either no ID was specified or IDs match
+ ( !parts[1] || parts[1] === tool.id )
+ ) {
+ promoted.push( tool.name );
+ delete tools[baseName];
+ }
+ }
+ }
+
+ for ( i = 0, len = demote.length; i < len; i++ ) {
+ parts = demote[i].split( '/' );
+ for ( baseName in tools ) {
+ tool = tools[baseName];
+ if (
+ // Types match
+ parts[0] === tool.type &&
+ // Either no ID was specified or IDs match
+ ( !parts[1] || parts[1] === tool.id )
+ ) {
+ demoted.push( tool.name );
+ delete tools[baseName];
+ }
+ }
+ }
+
+ for ( baseName in tools ) {
+ auto.push( tools[baseName].name );
+ }
+
+ return promoted.concat( auto.sort() ).concat( demoted );
+};
+
+/**
* Get a list of tools from a set of annotations.
*
* The most specific tool will be chosen based on inheritance - mostly. The
order of being added
diff --git a/modules/ve/ui/ve.ui.ToolGroup.js b/modules/ve/ui/ve.ui.ToolGroup.js
index 707887a..7835031 100644
--- a/modules/ve/ui/ve.ui.ToolGroup.js
+++ b/modules/ve/ui/ve.ui.ToolGroup.js
@@ -13,11 +13,22 @@
* @extends ve.ui.Widget
* @mixins ve.ui.GroupElement
*
+ * Patterns can be either:
+ * - All tools in a category: 'category'
+ * - A specific tool: 'category/name'
+ *
* @constructor
* @param {ve.ui.Toolbar} toolbar
* @param {Object} [config] Config options
+ * @param {string[]} [include=[]] Patterns of tools to automatically include
+ * @param {string[]} [exclude=[]] Patterns of tools to automatically exclude
+ * @param {string[]} [promote=[]] Patterns of tools to promote to the beginning
+ * @param {string[]} [demote=[]] Patterns of tools to demote to the end
*/
ve.ui.ToolGroup = function VeUiToolGroup( toolbar, config ) {
+ // Configuration initialization
+ config = config || {};
+
// Parent constructor
ve.ui.Widget.call( this, config );
@@ -26,12 +37,19 @@
// Properties
this.toolbar = toolbar;
+ this.tools = {};
+ this.include = config.include || [];
+ this.exclude = config.exclude || [];
+ this.promote = config.promote || [];
+ this.demote = config.demote || [];
// Events
this.$.on( { 'mousedown': false } );
+ ve.ui.toolFactory.connect( this, { 'register': 'ontoolFactoryRegister'
} );
// Initialization
this.$.addClass( 've-ui-toolGroup' );
+ this.populateTools();
};
/* Inheritance */
@@ -39,3 +57,60 @@
ve.inheritClass( ve.ui.ToolGroup, ve.ui.Widget );
ve.mixinClass( ve.ui.ToolGroup, ve.ui.GroupElement );
+
+/* Methods */
+
+/**
+ * Handle tool registry register events.
+ *
+ * If a tool is registered after the group is created, this handler will
ensure the tool is included
+ * as if it were present at the time of the group being created.
+ *
+ * @param {string} name Symbolic name of tool
+ */
+ve.ui.ToolGroup.prototype.ontoolFactoryRegister = function () {
+ this.populateTools();
+};
+
+ve.ui.ToolGroup.prototype.populateTools = function () {
+ var i, len, name, tool,
+ names = {},
+ tools = [],
+ list = ve.ui.toolFactory.getTools(
+ this.include, this.exclude, this.promote, this.demote
+ );
+
+ // Build a list of needed tools
+ for ( i = 0, len = list.length; i < len; i++ ) {
+ name = list[i];
+ tool = this.tools[name];
+ if ( !tool ) {
+ // Auto-initialize tools on
+ tool = ve.ui.toolFactory.create( name, this.toolbar );
+ this.tools[name] = tool;
+ }
+ tools.push( tool );
+ names[name] = true;
+ }
+ // Remove tools that are no longer needed
+ for ( name in this.tools ) {
+ if ( !names[name] ) {
+ this.tools[name].destroy();
+ this.removeItem( this.tools[name] );
+ delete this.tools[name];
+ }
+ }
+ // Re-add tools (moving existing ones to new locations)
+ this.addItems( tools );
+};
+
+ve.ui.ToolGroup.prototype.destroy = function () {
+ var name;
+
+ this.clearItems();
+ ve.ui.toolFactory.disconnect( this );
+ for ( name in this.tools ) {
+ this.tools[name].destroy();
+ }
+ this.$.remove();
+};
diff --git a/modules/ve/ui/ve.ui.Toolbar.js b/modules/ve/ui/ve.ui.Toolbar.js
index 9b7be98..98cfd6b 100644
--- a/modules/ve/ui/ve.ui.Toolbar.js
+++ b/modules/ve/ui/ve.ui.Toolbar.js
@@ -11,6 +11,7 @@
* @class
* @extends ve.Element
* @mixins ve.EventEmitter
+ * @mixins ve.ui.GroupElement
*
* @constructor
* @param {Object} [config] Config options
@@ -26,21 +27,22 @@
// Mixin constructors
ve.EventEmitter.call( this );
+ ve.ui.GroupElement.call( this, this.$$( '<div>' ) );
// Properties
+ this.groups = [];
this.$bar = this.$$( '<div>' );
- this.$tools = this.$$( '<div>' );
this.$actions = this.$$( '<div>' );
this.initialized = false;
// Events
this.$
- .add( this.$bar ).add( this.$tools ).add( this.$actions )
+ .add( this.$bar ).add( this.$group ).add( this.$actions )
.on( 'mousedown', false );
// Initialization
- this.$tools.addClass( 've-ui-toolbar-tools' );
- this.$bar.addClass( 've-ui-toolbar-bar' ).append( this.$tools );
+ this.$group.addClass( 've-ui-toolbar-tools' );
+ this.$bar.addClass( 've-ui-toolbar-bar' ).append( this.$group );
if ( options.actions ) {
this.$actions.addClass( 've-ui-toolbar-actions' );
this.$bar.append( this.$actions );
@@ -57,34 +59,9 @@
ve.inheritClass( ve.ui.Toolbar, ve.Element );
ve.mixinClass( ve.ui.Toolbar, ve.EventEmitter );
+ve.mixinClass( ve.ui.Toolbar, ve.ui.GroupElement );
/* Methods */
-
-/**
- * Initialize all tools and groups.
- *
- * @method
- * @param {Object[]} config List of tool group configurations
- */
-ve.ui.Toolbar.prototype.setup = function ( config ) {
- var i, j, group, tools;
-
- for ( i = 0; i < config.length; i++ ) {
- tools = config[i].items;
- group = new ve.ui.ToolGroup( this, { '$$': this.$$ } );
-
- // Add tools
- for ( j = 0; j < tools.length; j++ ) {
- try {
- tools[j] = ve.ui.toolFactory.create( tools[j],
this );
- } catch( e ) {}
- }
- group.addItems( tools );
-
- // Append group
- this.$tools.append( group.$ );
- }
-};
/**
* Sets up handles and preloads required information for the toolbar to work.
@@ -95,10 +72,32 @@
};
/**
+ * Setup toolbar.
+ *
+ * @method
+ * @param {Object[]} groups List of tool group configurations
+ */
+ve.ui.Toolbar.prototype.setup = function ( groups ) {
+ var i, len,
+ items = [];
+
+ for ( i = 0, len = groups.length; i < len; i++ ) {
+ items.push( new ve.ui.ToolGroup( this, ve.extendObject( { '$$':
this.$$ }, groups[i] ) ) );
+ }
+ this.addItems( items );
+};
+
+/**
* Destroys toolbar, removing event handlers and DOM elements.
*
* Call this whenever you are done using a toolbar.
*/
ve.ui.Toolbar.prototype.destroy = function () {
+ var i, len;
+
+ this.clearItems();
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[i].destroy();
+ }
this.$.remove();
};
--
To view, visit https://gerrit.wikimedia.org/r/78412
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7625f861435a99ce3d7a2b1ece9731aaab1776f8
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits