Index: test/fluent/resources/js/home.js =================================================================== --- test/fluent/resources/js/home.js (revision 7121) +++ test/fluent/resources/js/home.js (working copy) @@ -20,7 +20,168 @@ new org.ametys.fluent.Group ( { + id:'boost', title: 'Boutons', + smallItems: + [ + new org.ametys.fluent.Group.Part + ({ + align: 'top', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ( + { + size: 'small', + + handler: function() { tinyMCE.activeEditor.execCommand('Bold'); }, + + iconSmall: 'resources/img/editpaste_16.gif', + text: 'Gras', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + } + ), + new org.ametys.fluent.controls.Button + ( + { + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + text: 'G', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + } + ), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + text: 'Saut de page', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }), + + new org.ametys.fluent.Group.Part + ({ + align: 'middle', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }), + + new org.ametys.fluent.Group.Part + ({ + align: 'top', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }), + new org.ametys.fluent.Group.Part + ({ + align: 'top', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }), + new org.ametys.fluent.Group.Part + ({ + align: 'top', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }), + new org.ametys.fluent.Group.Part + ({ + align: 'top', + layoutConfig: {columns: 1}, + items: + [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }), + new org.ametys.fluent.controls.Button + ({ + size: 'small', + + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ] + }) + ], items: [ new org.ametys.fluent.controls.Button @@ -187,6 +348,18 @@ ( { title: 'Test layout', + priority: 1, + smallItems: [ + new org.ametys.fluent.controls.Button + ({ + size: 'small', + colspan: 2, + + text: "Test de bouton long", + iconSmall: 'resources/img/editpaste_16.gif', + tooltip: org.ametys.fluent.Tooltip.create('Bouton Ametys1', 'resources/img/ametys.gif', 'Cliquez ici pour avoir accès aux fonctions générales de l\'application ou pour vous déconnecter.', 'Voir l\'aide pour plus de détails') + }) + ], items: [ new org.ametys.fluent.Group.Part Index: test/fluent/test.html =================================================================== --- test/fluent/test.html (revision 7119) +++ test/fluent/test.html (working copy) @@ -107,7 +107,7 @@ ribbon, { region: 'center', - html: '

Lorem ipsum

Lorem ipsum dolor sit amet consectetuer Quisque Phasellus Vestibulum gravida habitasse. Sed nunc turpis et et Sed enim ridiculus consectetuer nec semper. Ac feugiat at leo Phasellus Lorem orci Curabitur dictum id pulvinar. Show contextual tab 1 2 2bis 3 4 5 6 Quis semper felis Hide contextual tab 1 2 2bis 3 4 5 6 Nullam laoreet tincidunt ullamcorper tellus eu tincidunt sodales. Ac semper Cum quis et morbi tincidunt.

', + html: '

Lorem ipsum

Small Medium Large Is visibleipsum dolor sit amet consectetuer Quisque Phasellus Vestibulum gravida habitasse. Sed nunc turpis et et Sed enim ridiculus consectetuer nec semper. Ac feugiat at leo Phasellus Lorem orci Curabitur dictum id pulvinar. Show contextual tab 1 2 2bis 3 4 5 6 Quis semper felis Hide contextual tab 1 2 2bis 3 4 5 6 Nullam laoreet tincidunt ullamcorper tellus eu tincidunt sodales. Ac semper Cum quis et morbi tincidunt.

', border: false } ] Index: main/workspace-cms/resources/fluent/js/org/ametys/fluent/Group.js =================================================================== --- main/workspace-cms/resources/fluent/js/org/ametys/fluent/Group.js (revision 7121) +++ main/workspace-cms/resources/fluent/js/org/ametys/fluent/Group.js (working copy) @@ -27,6 +27,62 @@ */ org.ametys.fluent.Group = function(config) { + if (config.smallItems) + { + this.smallContainer = new Ext.Container({ + items: config.smallItems, + hidden: true, + layout: 'table' + }); + } + + this.mediumContainer = new Ext.Container({ + items: config.items, + hidden: true, + layout: 'table' + }); + + if (config.largeItems) + { + this.largeContainer = new Ext.Container({ + items: config.largeItems, + hidden: true, + layout: 'table' + }); + } + + if (this.largeContainer) + { + this.scale = "large"; + this.largeContainer.show(); + } + else if (this.mediumContainer) + { + this.scale = "medium"; + this.mediumContainer.show(); + } + else if (this.smallContainer) + { + this.scale = "small"; + this.smallContainer.show(); + } + else + { + throw "Group has no items in any scale"; + } + + + config.items = []; + if (this.smallContainer) + { + config.items.push(this.smallContainer); + } + config.items.push(this.mediumContainer); + if (this.largeContainer) + { + config.items.push(this.largeContainer); + } + org.ametys.fluent.Group.superclass.constructor.call(this, config); this.on('render', this._onRenderModify, this); @@ -62,6 +118,33 @@ } ); +org.ametys.fluent.Group.prototype.getScale = function() +{ + return this.scale; +} + +org.ametys.fluent.Group.prototype.supportScale = function(newSize) +{ + return this[newSize + "Container"] != null; +} + +org.ametys.fluent.Group.prototype.setScale = function(newSize) +{ + if (newSize == this.scale || !this.supportScale(newSize)) + { + return; + } + + this[this.scale + "Container"].hide(); + this.scale = newSize; + this[this.scale + "Container"].show(); +} + +org.ametys.fluent.Group.prototype.canBeVisible = function() +{ + return this.el ? this.el.getTop() < 60 : true; +} + /** * private * Listener on layout to adapt title width Index: main/workspace-cms/resources/fluent/js/org/ametys/fluent/controls/Button.js =================================================================== --- main/workspace-cms/resources/fluent/js/org/ametys/fluent/controls/Button.js (revision 7121) +++ main/workspace-cms/resources/fluent/js/org/ametys/fluent/controls/Button.js (working copy) @@ -67,24 +67,6 @@ /** * @private - * Override toggle to work before render - * FIXME To remove when using last SVN build (should be corrected - to test) - */ -org.ametys.fluent.controls.Button.prototype.toggle = function(state, suppressEvent) -{ - var state = state === undefined ? !this.pressed : !!state; - if (!this.rendered) - { - this.pressed = state; - } - else - { - org.ametys.fluent.controls.Button.superclass.toggle.call(this, state, suppressEvent); - } -} - -/** - * @private * Listener on render to reset the text (during creation a template is applied and setText is not called) */ org.ametys.fluent.controls.Button.prototype._onRenderSetTextAndClass = function() @@ -224,16 +206,6 @@ org.ametys.fluent.controls.Button.prototype.onClick = function(e, t){ e.preventDefault(); - // dismiss tooltip - // FIXME remove this block if using last extjs svn built : should be corrected (to test) - var tooltip = Ext.QuickTips.getQuickTip(); - tooltip.clearTimer('show'); - if(tooltip.autoHide !== false) - { - tooltip.delayHide(); - } - // end of fix me - if(!this.disabled) { if(this.split && this.isClickOnArrow(e) || !this.split && this.menu && !this.menu.isVisible() && !this.ignoreNextClick) Index: main/workspace-cms/resources/fluent/js/org/ametys/fluent/RibbonPanel.js =================================================================== --- main/workspace-cms/resources/fluent/js/org/ametys/fluent/RibbonPanel.js (revision 7119) +++ main/workspace-cms/resources/fluent/js/org/ametys/fluent/RibbonPanel.js (working copy) @@ -31,7 +31,8 @@ this._lastContextualTabHidden = null; this._actionPerfomed = false; this._contextualGroups = {}; - + this._scaleGrid = {}; + config.itemTpl = new Ext.Template ( '
  • ', @@ -138,6 +139,7 @@ Ext.getDoc().on("click", this._onAnyMouseDown, this); Ext.getDoc().on("contextmenu", this._onAnyMouseDown, this); this.on('afterlayout', this._onLayoutChanged, this); + this.on('resize', this._onResize, this); if (this.menu && this.menu.icon) { @@ -154,6 +156,8 @@ org.ametys.fluent.RibbonPanel.prototype._onTabChanged = function() { this.activeTab.doLayout(); + + this._checkSize(); } /** * Set the title in the ribbon. The title is prefixed by the application title {@see org.ametys.fluent.RibbonPanel.applicationTitle} @@ -256,6 +260,168 @@ /** * @private Listener when layout is made up */ +org.ametys.fluent.RibbonPanel.prototype._onResize = function() +{ + this._checkSize(); +} + +org.ametys.fluent.RibbonPanel.prototype._buildScalesGrid = function(index) +{ + var scaleGrid = this._scaleGrid; + scaleGrid[index] = []; + + var tab = this.items.get(index); + + // compute the priority between groups + var priority = []; + tab.items.each(function (e, i) + { + priority.push({index: i, priority: e.priority ? e.priority : 0}); + }); + function compare(e1, e2) + { + return (e1.priority != e2.priority) ? e1.priority < e2.priority : e2.index < e1.index; + } + priority.sort(compare); + + // fill the matrix + function fill(first, second, fullspeed) + { + for (var cursor = fullspeed ? 1 : 0; cursor <= priority.length; cursor++) + { + var line = []; + for (var i = 0; i < priority.length; i++) { line.push("X"); } + + for (var i = 0; i < priority.length - cursor; i++) + { + line[priority[i].index] = first; + } + for (var i = 0; i < cursor; i++) + { + line[priority[priority.length - cursor + i].index] =second; + } + + scaleGrid[index].matrix.push({resize: line}); + } + } + + scaleGrid[index].matrix = []; + scaleGrid[index].current = 0; + + fill("large", "medium", false); + fill("medium", "small", true); + + // change unexisting combo & remove duplicates + for (var i = scaleGrid[index].matrix.length - 1; i >= 0 ; i--) + { + var grid = scaleGrid[index].matrix[i]; + for (var j = 0; j < grid.resize.length; j++) + { + if (!tab.items.get(j).supportScale(grid.resize[j])) + { + grid.resize[j] = "medium"; + } + } + + if (i + 1 < scaleGrid[index].matrix.length) + { + var areTheSame = true; + + var grid = scaleGrid[index].matrix[i]; + var grid2 = scaleGrid[index].matrix[i + 1]; + for (var j = 0; j < grid.resize.length; j++) + { + if (grid.resize[j] != grid2.resize[j]) + { + areTheSame = false; + break; + } + } + + if (areTheSame) + { + scaleGrid[index].matrix.remove(grid2); + } + } + } +} + +org.ametys.fluent.RibbonPanel.prototype._checkSize = function() +{ + if (this.getActiveTab()) + { + var doesNotFit = false; + this.getActiveTab().items.each(function (e) + { + if (e.canBeVisible && !e.canBeVisible()) + { + doesNotFit = true; + } + }); + + var index = this.items.indexOf(this.getActiveTab()); + if (this._scaleGrid[index] == null) + { + this._buildScalesGrid(index); + } + + var grid = this._scaleGrid[index]; + + if (doesNotFit) + { + if (!grid.matrix[grid.current].doesNotFitIn || grid.matrix[grid.current].doesNotFitIn < this.getActiveTab().getWidth()) + { + grid.matrix[grid.current].doesNotFitIn = this.getActiveTab().getWidth(); + } + + if (grid.current + 1 < grid.matrix.length) + { + grid.current++; + + for (var i = 0; i < grid.matrix[grid.current].resize.length; i++) + { + this.getActiveTab().items.get(i).setScale(grid.matrix[grid.current].resize[i]); + } + + // may need to go under ! + this._checkSize(); + } + else + { + // does not fit in the window, but already at the min size + return; + } + } + else + { + if (!grid.matrix[grid.current].fitIn || grid.matrix[grid.current].fitIn > this.getActiveTab().getWidth()) + { + grid.matrix[grid.current].fitIn = this.getActiveTab().getWidth(); + } + + // Can we grow ? + if (grid.current > 0) + { + if (!grid.matrix[grid.current - 1].doesNotFitIn || this.getActiveTab().getWidth() > grid.matrix[grid.current - 1].doesNotFitIn) + { + // have a try + grid.current--; + + for (var i = 0; i < grid.matrix[grid.current].resize.length; i++) + { + this.getActiveTab().items.get(i).setScale(grid.matrix[grid.current].resize[i]); + } + + this._checkSize(); + } + } + } + } +} + +/** + * @private Listener when layout is made up + */ org.ametys.fluent.RibbonPanel.prototype._onLayoutChanged = function() { this.body.setHeight(org.ametys.fluent.RibbonPanel.BODY_HEIGHT);