microsoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemail
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
924 lines
30 KiB
924 lines
30 KiB
/** |
|
* A specialized panel intended for use as an application window. Windows are floated, {@link #resizable}, and |
|
* {@link #cfg-draggable} by default. Windows can be {@link #maximizable maximized} to fill the viewport, restored to |
|
* their prior size, and can be {@link #method-minimize}d. |
|
* |
|
* Windows can also be linked to a {@link Ext.ZIndexManager} or managed by the {@link Ext.WindowManager} to provide |
|
* grouping, activation, to front, to back and other application-specific behavior. |
|
* |
|
* By default, Windows will be rendered to document.body. To {@link #constrain} a Window to another element specify |
|
* {@link Ext.Component#renderTo renderTo}. |
|
* |
|
* **As with all {@link Ext.container.Container Container}s, it is important to consider how you want the Window to size |
|
* and arrange any child Components. Choose an appropriate {@link #layout} configuration which lays out child Components |
|
* in the required manner.** |
|
* |
|
* @example |
|
* Ext.create('Ext.window.Window', { |
|
* title: 'Hello', |
|
* height: 200, |
|
* width: 400, |
|
* layout: 'fit', |
|
* items: { // Let's put an empty grid in just to illustrate fit layout |
|
* xtype: 'grid', |
|
* border: false, |
|
* columns: [{header: 'World'}], // One header just for show. There's no data, |
|
* store: Ext.create('Ext.data.ArrayStore', {}) // A dummy empty data store |
|
* } |
|
* }).show(); |
|
*/ |
|
Ext.define('Ext.window.Window', { |
|
extend: 'Ext.panel.Panel', |
|
|
|
alternateClassName: 'Ext.Window', |
|
|
|
requires: ['Ext.util.ComponentDragger', 'Ext.util.Region'], |
|
|
|
alias: 'widget.window', |
|
|
|
/** |
|
* @cfg {Number} x |
|
* The X position of the left edge of the window on initial showing. Defaults to centering the Window within the |
|
* width of the Window's container {@link Ext.dom.Element Element} (The Element that the Window is rendered to). |
|
*/ |
|
|
|
/** |
|
* @cfg {Number} y |
|
* The Y position of the top edge of the window on initial showing. Defaults to centering the Window within the |
|
* height of the Window's container {@link Ext.dom.Element Element} (The Element that the Window is rendered to). |
|
*/ |
|
|
|
/** |
|
* @cfg {String/Ext.dom.Element} [animateTarget=null] |
|
* Id or element from which the window should animate while opening. |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean/Function} ghost |
|
* Set to false to disable the ghost panel during dragging the window. |
|
* Do note that you should not set this to true, by default it is a function. |
|
*/ |
|
|
|
/** |
|
* @cfg {String/Number/Ext.Component} defaultFocus |
|
* Specifies a Component to receive focus when this Window is focused. |
|
* |
|
* If a String is provided, the Component will be resolved using the {@link #down} method which uses {@link Ext.ComponentQuery}. |
|
* If the string begins with an alphanumeric value, it will first attempt to find the Component based on the {@link Ext.Component#id} or {@link Ext.Component#itemId}. |
|
* If a matching component is not found via id, then an attempt to do a query to find a matching component. |
|
* |
|
* An example of finding the Component with an id/itemId: |
|
* |
|
* Ext.create('Ext.window.Window', { |
|
* autoShow : true, |
|
* width : 300, |
|
* title : 'Login', |
|
* defaultFocus : 'username', |
|
* items : [ |
|
* { |
|
* xtype : 'textfield', |
|
* fieldLabel : 'Username', |
|
* itemId : 'username', |
|
* name : 'username' |
|
* }, |
|
* { |
|
* xtype : 'textfield', |
|
* inputType : 'password', |
|
* fieldLabel : 'Password', |
|
* itemId : 'password', |
|
* name : 'password' |
|
* } |
|
* ] |
|
* }); |
|
* |
|
* If a Number is provided, this will resolve an {@link Ext.button.Button} at that index. This is very useful if |
|
* the window has buttons in the {@link #buttons} config and you want to provide default focus to one of them. |
|
* |
|
* An example of this would be: |
|
* |
|
* Ext.create('Ext.window.Window', { |
|
* autoShow : true, |
|
* width : 300, |
|
* title : 'Login', |
|
* defaultFocus : 1, |
|
* items : [ |
|
* { |
|
* xtype : 'textfield', |
|
* fieldLabel : 'Username', |
|
* name : 'username' |
|
* }, |
|
* { |
|
* xtype : 'textfield', |
|
* inputType : 'password', |
|
* fieldLabel : 'Password', |
|
* name : 'password' |
|
* } |
|
* ], |
|
* buttons : [ |
|
* { |
|
* text : 'Cancel' |
|
* }, |
|
* { |
|
* text : 'Login' |
|
* } |
|
* ] |
|
* }); |
|
* |
|
* In summary, defaultFocus may be one of: |
|
* |
|
* - The index of a footer Button. |
|
* - The id or {@link Ext.Component#itemId} of a descendant Component. |
|
* - A {@link Ext.ComponentQuery query} to find a {@link Ext.Component}. |
|
* - A descendant {@link Ext.Component}. |
|
*/ |
|
|
|
/** |
|
* @cfg {Function} onEsc |
|
* Allows override of the built-in processing for the escape key. Default action is to close the Window (performing |
|
* whatever action is specified in {@link #closeAction}. To prevent the Window closing when the escape key is |
|
* pressed, specify this as {@link Ext#emptyFn Ext.emptyFn}. |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean} [collapsed=false] |
|
* True to render the window collapsed, false to render it expanded. Note that if {@link #expandOnShow} |
|
* is true (the default) it will override the `collapsed` config and the window will always be |
|
* expanded when shown. |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean} [maximized=false] |
|
* True to initially display the window in a maximized state. |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean} [hideShadowOnDeactivate=false] |
|
* True to hide this Window's shadow when another floating item in the same z-index stack is activated. |
|
*/ |
|
|
|
/** |
|
* @cfg {String} [baseCls='x-window'] |
|
* The base CSS class to apply to this panel's element. |
|
*/ |
|
baseCls: Ext.baseCSSPrefix + 'window', |
|
|
|
/** |
|
* @cfg {Boolean/Object} resizable |
|
* Specify as `true` to allow user resizing at each edge and corner of the window, false to disable resizing. |
|
* |
|
* This may also be specified as a config object to Ext.resizer.Resizer |
|
*/ |
|
resizable: true, |
|
|
|
/** |
|
* @cfg {Boolean} draggable |
|
* True to allow the window to be dragged by the header bar, false to disable dragging. Note that |
|
* by default the window will be centered in the viewport, so if dragging is disabled the window may need to be |
|
* positioned programmatically after render (e.g., `myWindow.setPosition(100, 100);`). |
|
*/ |
|
draggable: true, |
|
|
|
/** |
|
* @override |
|
* @cfg {Boolean} constrain |
|
* True to constrain the window within its containing element, false to allow it to fall outside of its containing |
|
* element. By default the window will be rendered to `document.body`. To render and constrain the window within |
|
* another element specify {@link #renderTo}. Optionally the header only can be constrained |
|
* using {@link #constrainHeader}. |
|
*/ |
|
constrain: false, |
|
|
|
/** |
|
* @override |
|
* @cfg {Boolean} constrainHeader |
|
* True to constrain the window header within its containing element (allowing the window body to fall outside of |
|
* its containing element) or false to allow the header to fall outside its containing element. |
|
* Optionally the entire window can be constrained using {@link #constrain}. |
|
*/ |
|
constrainHeader: false, |
|
|
|
/** |
|
* @cfg simpleDrag |
|
* @hide |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean} plain |
|
* True to render the window body with a transparent background so that it will blend into the framing elements, |
|
* false to add a lighter background color to visually highlight the body element and separate it more distinctly |
|
* from the surrounding frame. |
|
*/ |
|
plain: false, |
|
|
|
/** |
|
* @cfg {Boolean} minimizable |
|
* True to display the 'minimize' tool button and allow the user to minimize the window, false to hide the button |
|
* and disallow minimizing the window. Note that this button provides no implementation -- the |
|
* behavior of minimizing a window is implementation-specific, so the minimize event must be handled and a custom |
|
* minimize behavior implemented for this option to be useful. |
|
*/ |
|
minimizable: false, |
|
|
|
/** |
|
* @cfg {Boolean} maximizable |
|
* True to display the 'maximize' tool button and allow the user to maximize the window, false to hide the button |
|
* and disallow maximizing the window. Note that when a window is maximized, the tool button |
|
* will automatically change to a 'restore' button with the appropriate behavior already built-in that will restore |
|
* the window to its previous size. |
|
*/ |
|
maximizable: false, |
|
|
|
// inherit docs |
|
minHeight: 50, |
|
|
|
// inherit docs |
|
minWidth: 50, |
|
|
|
/** |
|
* @cfg {Boolean} expandOnShow |
|
* True to always expand the window when it is displayed, false to keep it in its current state (which may be |
|
* {@link #collapsed}) when displayed. |
|
*/ |
|
expandOnShow: true, |
|
|
|
// inherited docs, same default |
|
collapsible: false, |
|
|
|
/** |
|
* @cfg {Boolean} closable |
|
* True to display the 'close' tool button and allow the user to close the window, false to hide the button and |
|
* disallow closing the window. |
|
* |
|
* By default, when close is requested by either clicking the close button in the header or pressing ESC when the |
|
* Window has focus, the {@link #method-close} method will be called. This will _{@link Ext.Component#method-destroy destroy}_ the |
|
* Window and its content meaning that it may not be reused. |
|
* |
|
* To make closing a Window _hide_ the Window so that it may be reused, set {@link #closeAction} to 'hide'. |
|
*/ |
|
closable: true, |
|
|
|
/** |
|
* @cfg {Boolean} monitorResize |
|
* `true` to listen to the viewport resize event and perform any layout updating if necessary. |
|
* This is useful if using sizes as percentages for the window. |
|
*/ |
|
|
|
/** |
|
* @cfg {Boolean} hidden |
|
* Render this Window hidden. If `true`, the {@link #method-hide} method will be called internally. |
|
*/ |
|
hidden: true, |
|
|
|
/** |
|
* @cfg {Boolean} |
|
* @inheritdoc |
|
* Windows render to the body on first show. |
|
*/ |
|
autoRender: true, |
|
|
|
/** |
|
* @cfg {String} |
|
* @inheritdoc |
|
* Windows hide using offsets in order to preserve the scroll positions of their descendants. You may review |
|
* other configuration options here: {@link Ext.Component#hideMode}. |
|
*/ |
|
hideMode: 'offsets', |
|
|
|
// Windows are always floating. |
|
floating: true, |
|
|
|
itemCls: Ext.baseCSSPrefix + 'window-item', |
|
|
|
overlapHeader: true, |
|
|
|
ignoreHeaderBorderManagement: true, |
|
|
|
// Flag to Renderable to always look up the framing styles for this Component |
|
alwaysFramed: true, |
|
|
|
// Buffer this so we don't recreate the same object |
|
isRootCfg: { |
|
isRoot: true |
|
}, |
|
|
|
/** |
|
* @property {Boolean} isWindow |
|
* `true` in this class to identify an object as an instantiated Window, or subclass thereof. |
|
*/ |
|
isWindow: true, |
|
|
|
ariaRole: 'dialog', |
|
|
|
/** |
|
* @event activate |
|
* Fires after the window has been visually activated via {@link #setActive}. |
|
* @param {Ext.window.Window} this |
|
*/ |
|
|
|
/** |
|
* @event deactivate |
|
* Fires after the window has been visually deactivated via {@link #setActive}. |
|
* @param {Ext.window.Window} this |
|
*/ |
|
|
|
/** |
|
* @event resize |
|
* Fires after the window has been resized. |
|
* @param {Ext.window.Window} this |
|
* @param {Number} width The window's new width |
|
* @param {Number} height The window's new height |
|
*/ |
|
|
|
/** |
|
* @event maximize |
|
* Fires after the window has been maximized. |
|
* @param {Ext.window.Window} this |
|
*/ |
|
|
|
/** |
|
* @event minimize |
|
* Fires after the window has been minimized. |
|
* @param {Ext.window.Window} this |
|
*/ |
|
|
|
/** |
|
* @event restore |
|
* Fires after the window has been restored to its original size after being maximized. |
|
* @param {Ext.window.Window} this |
|
*/ |
|
|
|
// @private |
|
initComponent: function() { |
|
var me = this; |
|
// Explicitly set frame to false, since alwaysFramed is |
|
// true, we only want to lookup framing in a specific instance |
|
me.frame = false; |
|
me.callParent(); |
|
|
|
if (me.plain) { |
|
me.addClsWithUI('plain'); |
|
} |
|
|
|
me.addStateEvents(['maximize', 'restore', 'resize', 'dragend']); |
|
}, |
|
|
|
getElConfig: function () { |
|
var me = this, |
|
elConfig; |
|
|
|
elConfig = me.callParent(); |
|
elConfig.tabIndex = -1; |
|
return elConfig; |
|
}, |
|
|
|
/** |
|
* @protected |
|
* Returns the focus holder element associated with this Window. |
|
* By default, this is the Window's element; this can be overridden |
|
* by setting {@link #defaultFocus} property. |
|
* |
|
* @return {Ext.dom.Element/Ext.Component} the focus holding element or Component. |
|
*/ |
|
getFocusEl: function() { |
|
var me = this; |
|
|
|
// If the legacy FocusManager is enabled, then we must not focus |
|
// the defaultFocus child. We must focus the Window instead, to |
|
// let FocusManager do its thing. |
|
return Ext.enableFocusManager ? me.el : (me.getDefaultFocus() || me.el); |
|
}, |
|
|
|
// State Management |
|
|
|
// @private |
|
getState: function() { |
|
var me = this, |
|
state = me.callParent() || {}, |
|
maximized = !!me.maximized, |
|
ghostBox = me.ghostBox, |
|
pos; |
|
|
|
|
|
state.maximized = maximized; |
|
if (maximized) { |
|
pos = me.restorePos; |
|
} else if (ghostBox) { |
|
// If we're animating a show, it will be from offscreen, so |
|
// grab the position from the final box |
|
pos = [ghostBox.x, ghostBox.y]; |
|
} else { |
|
pos = me.getPosition(); |
|
} |
|
Ext.apply(state, { |
|
size: maximized ? me.restoreSize : me.getSize(), |
|
pos: pos |
|
}); |
|
return state; |
|
}, |
|
|
|
applyState: function(state){ |
|
var me = this; |
|
|
|
if (state) { |
|
me.maximized = state.maximized; |
|
if (me.maximized) { |
|
me.hasSavedRestore = true; |
|
me.restoreSize = state.size; |
|
me.restorePos = state.pos; |
|
} else { |
|
Ext.apply(me, { |
|
width: state.size.width, |
|
height: state.size.height, |
|
x: state.pos[0], |
|
y: state.pos[1] |
|
}); |
|
} |
|
} |
|
}, |
|
|
|
// @private |
|
onRender: function(ct, position) { |
|
var me = this; |
|
|
|
me.callParent(arguments); |
|
|
|
// Single clicking a header will focus the defaultFocus child |
|
if (me.header) { |
|
me.header.on({ |
|
scope: me, |
|
click: me.onHeaderClick |
|
}); |
|
} |
|
|
|
// Double clicking a header will toggleMaximize |
|
if (me.maximizable) { |
|
me.header.on({ |
|
scope: me, |
|
dblclick: me.toggleMaximize |
|
}); |
|
} |
|
}, |
|
|
|
// @private |
|
afterRender: function() { |
|
var me = this, |
|
header = me.header, |
|
keyMap; |
|
|
|
// Initialize |
|
if (me.maximized) { |
|
me.maximized = false; |
|
me.maximize(); |
|
if (header) { |
|
header.removeCls(header.indicateDragCls); |
|
} |
|
} |
|
|
|
me.callParent(); |
|
|
|
if (me.closable) { |
|
keyMap = me.getKeyMap(); |
|
keyMap.on(27, me.onEsc, me); |
|
} else { |
|
keyMap = me.keyMap; |
|
} |
|
if (keyMap && me.hidden) { |
|
keyMap.disable(); |
|
} |
|
}, |
|
|
|
// @private |
|
onEsc: function(k, e) { |
|
// hide the dependency from Cmd |
|
var mgr = Ext['FocusManager']; // jshint ignore:line |
|
|
|
// Only process ESC if the FocusManager is not doing it |
|
if (!Ext.enableFocusManager || mgr.focusedCmp === this) { |
|
e.stopEvent(); |
|
this.close(); |
|
} |
|
}, |
|
|
|
// @private |
|
beforeDestroy: function() { |
|
var me = this; |
|
if (me.rendered) { |
|
Ext.un('resize', me.onWindowResize, me); |
|
delete me.animateTarget; |
|
me.hide(); |
|
Ext.destroy( |
|
me.keyMap |
|
); |
|
} |
|
me.callParent(); |
|
}, |
|
|
|
/** |
|
* @private |
|
* Contribute class-specific tools to the header. |
|
* |
|
* Called by Panel's initTools at initialization time. |
|
* |
|
* Implementations should jst add new tool config objects to `this.tools` |
|
*/ |
|
addTools: function() { |
|
var me = this, |
|
tools = []; |
|
|
|
// Call Panel's addTools |
|
me.callParent(); |
|
|
|
if (me.minimizable) { |
|
tools.push({ |
|
type: 'minimize', |
|
handler: 'minimize', |
|
scope: me |
|
}); |
|
} |
|
if (me.maximizable) { |
|
tools.push({ |
|
type: me.maximized ? 'restore' : 'maximize', |
|
handler: 'toggleMaximize', |
|
scope: me |
|
}); |
|
} |
|
|
|
if (tools.length) { |
|
me.addTool(tools); |
|
} |
|
}, |
|
|
|
onShow: function() { |
|
var me = this; |
|
|
|
me.callParent(arguments); |
|
if (me.expandOnShow) { |
|
me.expand(false); |
|
} |
|
me.syncMonitorWindowResize(); |
|
|
|
if (me.keyMap) { |
|
me.keyMap.enable(); |
|
} |
|
}, |
|
|
|
// @private |
|
doClose: function() { |
|
var me = this; |
|
|
|
// Being called as callback after going through the hide call below |
|
if (me.hidden) { |
|
me.fireEvent('close', me); |
|
if (me.closeAction === 'destroy') { |
|
me.destroy(); |
|
} |
|
} else { |
|
// close after hiding |
|
me.hide(me.animateTarget, me.doClose, me); |
|
} |
|
}, |
|
|
|
// @private |
|
afterHide: function() { |
|
var me = this; |
|
|
|
// No longer subscribe to resizing now that we're hidden |
|
me.syncMonitorWindowResize(); |
|
|
|
// Turn off keyboard handling once window is hidden |
|
if (me.keyMap) { |
|
me.keyMap.disable(); |
|
} |
|
|
|
// Perform superclass's afterHide tasks. |
|
me.callParent(arguments); |
|
}, |
|
|
|
// @private |
|
onWindowResize: function() { |
|
var me = this, |
|
sizeModel; |
|
|
|
// This is called on a timer. Window may have been destroyed in the interval. |
|
if (!me.isDestroyed) { |
|
if (me.maximized) { |
|
me.fitContainer(); |
|
} else { |
|
sizeModel = me.getSizeModel(); |
|
if (sizeModel.width.natural || sizeModel.height.natural) { |
|
me.updateLayout(); |
|
} |
|
me.doConstrain(); |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* Placeholder method for minimizing the window. By default, this method simply fires the {@link #event-minimize} event |
|
* since the behavior of minimizing a window is application-specific. To implement custom minimize behavior, either |
|
* the minimize event can be handled or this method can be overridden. |
|
* @return {Ext.window.Window} this |
|
*/ |
|
minimize: function() { |
|
this.fireEvent('minimize', this); |
|
return this; |
|
}, |
|
|
|
resumeHeaderLayout: function(changed) { |
|
this.header.resumeLayouts(changed ? this.isRootCfg : null); |
|
}, |
|
|
|
afterCollapse: function() { |
|
var me = this, |
|
header = me.header, |
|
tools = me.tools; |
|
|
|
if (header && me.maximizable) { |
|
header.suspendLayouts(); |
|
tools.maximize.hide(); |
|
this.resumeHeaderLayout(true); |
|
} |
|
if (me.resizer) { |
|
me.resizer.disable(); |
|
} |
|
me.callParent(arguments); |
|
}, |
|
|
|
afterExpand: function() { |
|
var me = this, |
|
header = me.header, |
|
tools = me.tools, |
|
changed; |
|
|
|
|
|
if (header) { |
|
header.suspendLayouts(); |
|
if (me.maximizable) { |
|
tools.maximize.show(); |
|
changed = true; |
|
} |
|
this.resumeHeaderLayout(changed); |
|
} |
|
if (me.resizer) { |
|
me.resizer.enable(); |
|
} |
|
me.callParent(arguments); |
|
}, |
|
|
|
/** |
|
* Fits the window within its current container and automatically replaces the {@link #maximizable 'maximize' tool |
|
* button} with the 'restore' tool button. Also see {@link #toggleMaximize}. |
|
* @param {Boolean} [animate=false] Pass `true` to animate this Window to full size. |
|
* @return {Ext.window.Window} this |
|
*/ |
|
maximize: function(animate) { |
|
var me = this, |
|
header = me.header, |
|
tools = me.tools, |
|
width = me.width, |
|
height = me.height, |
|
restore, changed; |
|
|
|
if (!me.maximized) { |
|
me.expand(false); |
|
if (!me.hasSavedRestore) { |
|
restore = me.restoreSize = { |
|
width: width ? width : null, |
|
height: height ? height : null |
|
}; |
|
|
|
me.restorePos = me.getPosition(); |
|
} |
|
|
|
// Manipulate visibility of header tools if there is a header |
|
if (header) { |
|
header.suspendLayouts(); |
|
if (tools.maximize) { |
|
tools.maximize.setType('restore'); |
|
} |
|
if (me.collapseTool) { |
|
me.collapseTool.hide(); |
|
changed = true; |
|
} |
|
me.resumeHeaderLayout(changed); |
|
} |
|
|
|
me.el.disableShadow(); |
|
|
|
if (me.dd) { |
|
me.dd.disable(); |
|
if (header) { |
|
header.removeCls(header.indicateDragCls); |
|
} |
|
} |
|
if (me.resizer) { |
|
me.resizer.disable(); |
|
} |
|
|
|
me.el.addCls(Ext.baseCSSPrefix + 'window-maximized'); |
|
me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct'); |
|
|
|
me.syncMonitorWindowResize(); |
|
me.fitContainer(animate = (animate || !!me.animateTarget) ? { |
|
callback: function() { |
|
me.maximized = true; |
|
me.fireEvent('maximize', me); |
|
} |
|
} : null); |
|
if (!animate) { |
|
me.maximized = true; |
|
me.fireEvent('maximize', me); |
|
} |
|
} |
|
return me; |
|
}, |
|
|
|
/** |
|
* Restores a {@link #maximizable maximized} window back to its original size and position prior to being maximized |
|
* and also replaces the 'restore' tool button with the 'maximize' tool button. Also see {@link #toggleMaximize}. |
|
* @param {Boolean} [animate=false] Pass `true` to animate the restore. |
|
* @return {Ext.window.Window} this |
|
*/ |
|
restore: function(animate) { |
|
var me = this, |
|
tools = me.tools, |
|
header = me.header, |
|
newBox = me.restoreSize, |
|
changed; |
|
|
|
if (me.maximized) { |
|
me.hasSavedRestore = null; |
|
me.removeCls(Ext.baseCSSPrefix + 'window-maximized'); |
|
|
|
// Manipulate visibility of header tools if there is a header |
|
if (header) { |
|
header.suspendLayouts(); |
|
if (tools.maximize) { |
|
tools.maximize.setType('maximize'); |
|
} |
|
if (me.collapseTool) { |
|
me.collapseTool.show(); |
|
changed = true; |
|
} |
|
me.resumeHeaderLayout(changed); |
|
} |
|
|
|
// Restore the position/sizing |
|
newBox.x = me.restorePos[0]; |
|
newBox.y = me.restorePos[1]; |
|
me.setBox(newBox, animate = (animate || !!me.animateTarget) ? { |
|
callback: function() { |
|
me.el.enableShadow(null, true); |
|
me.maximized = false; |
|
me.fireEvent('restore', me); |
|
} |
|
} : null); |
|
|
|
// Unset old position/sizing |
|
me.restorePos = me.restoreSize = null; |
|
|
|
// Allow users to drag and drop again |
|
if (me.dd) { |
|
me.dd.enable(); |
|
if (header) { |
|
header.addCls(header.indicateDragCls); |
|
} |
|
} |
|
|
|
if (me.resizer) { |
|
me.resizer.enable(); |
|
} |
|
|
|
me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct'); |
|
|
|
me.syncMonitorWindowResize(); |
|
|
|
if (!animate) { |
|
me.el.enableShadow(null, true); |
|
me.maximized = false; |
|
me.fireEvent('restore', me); |
|
} |
|
} |
|
return me; |
|
}, |
|
|
|
/** |
|
* Synchronizes the presence of our listener for window resize events. This method |
|
* should be called whenever this status might change. |
|
* @private |
|
*/ |
|
syncMonitorWindowResize: function () { |
|
var me = this, |
|
currentlyMonitoring = me._monitoringResize, |
|
// all the states where we should be listening to window resize: |
|
yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized, |
|
// all the states where we veto this: |
|
veto = me.hidden || me.destroying || me.isDestroyed; |
|
|
|
if (yes && !veto) { |
|
// we should be listening... |
|
if (!currentlyMonitoring) { |
|
// but we aren't, so set it up. |
|
// Delay so that we jump over any Viewport resize activity |
|
Ext.on('resize', me.onWindowResize, me, {buffer: 1}); |
|
me._monitoringResize = true; |
|
} |
|
} else if (currentlyMonitoring) { |
|
// we should not be listening, but we are, so tear it down |
|
Ext.un('resize', me.onWindowResize, me); |
|
me._monitoringResize = false; |
|
} |
|
}, |
|
|
|
/** |
|
* A shortcut method for toggling between {@link #method-maximize} and {@link #method-restore} based on the current maximized |
|
* state of the window. |
|
* @return {Ext.window.Window} this |
|
*/ |
|
toggleMaximize: function() { |
|
return this[this.maximized ? 'restore': 'maximize'](); |
|
}, |
|
|
|
createGhost: function() { |
|
var ghost = this.callParent(arguments); |
|
ghost.xtype = 'window'; |
|
return ghost; |
|
}, |
|
|
|
/** |
|
* Gets the configured default focus item. If a {@link #defaultFocus} is set, it will |
|
* receive focus when the Window's `focus` method is called, otherwise the |
|
* Window itself will receive focus. |
|
*/ |
|
getDefaultFocus: function() { |
|
var me = this, |
|
result, |
|
defaultComp = me.defaultButton || me.defaultFocus, |
|
selector; |
|
|
|
if (defaultComp !== undefined) { |
|
// Number is index of Button |
|
if (Ext.isNumber(defaultComp)) { |
|
result = me.query('button')[defaultComp]; |
|
} |
|
// String is ID or CQ selector |
|
else if (Ext.isString(defaultComp)) { |
|
selector = defaultComp; |
|
|
|
// Try id/itemId match if selector begins with alphanumeric |
|
// and is not compound xtype/id selector with # in the middle |
|
// (https://sencha.jira.com/browse/EXTJS-14925) |
|
if (Ext.validIdRe.test(selector)) { |
|
result = me.down(Ext.makeIdSelector(selector)); |
|
} |
|
// If not found, use as selector |
|
if (!result) { |
|
result = me.down(selector); |
|
} |
|
} |
|
// Otherwise, if it's got a focus method, use it |
|
else if (defaultComp.focus) { |
|
result = defaultComp; |
|
} |
|
} |
|
|
|
return result; |
|
}, |
|
|
|
privates: { |
|
// Override. Windows are always simple draggable, they do not use Ext.Panel.DDs |
|
// The dd property in a Window is always a ComponentDragger |
|
initDraggable: function() { |
|
/** |
|
* @property {Ext.util.ComponentDragger} dd |
|
* If this Window is configured {@link #cfg-draggable}, this property will contain an instance of |
|
* {@link Ext.util.ComponentDragger} (A subclass of {@link Ext.dd.DragTracker DragTracker}) which handles dragging |
|
* the Window's DOM Element, and constraining according to the {@link #constrain} and {@link #constrainHeader} . |
|
* |
|
* This has implementations of `onBeforeStart`, `onDrag` and `onEnd` which perform the dragging action. If |
|
* extra logic is needed at these points, use {@link Ext.Function#createInterceptor createInterceptor} or |
|
* {@link Ext.Function#createSequence createSequence} to augment the existing implementations. |
|
*/ |
|
this.initSimpleDraggable(); |
|
}, |
|
|
|
onHeaderClick: function(header, e) { |
|
var delegate; |
|
|
|
if (header.el.contains(e.getTarget())) { |
|
delegate = this.getDefaultFocus(); |
|
|
|
if (delegate) { |
|
delegate.focus(); |
|
} |
|
} |
|
}, |
|
|
|
initResizable: function(){ |
|
this.callParent(arguments); |
|
if (this.maximized) { |
|
this.resizer.disable(); |
|
} |
|
} |
|
} |
|
});
|
|
|