|
Packit Service |
ed5168 |
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
const { Atk, Clutter, Shell, St } = imports.gi;
|
|
Packit Service |
ed5168 |
const Signals = imports.signals;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
const Dialog = imports.ui.dialog;
|
|
Packit Service |
ed5168 |
const Layout = imports.ui.layout;
|
|
Packit Service |
ed5168 |
const Lightbox = imports.ui.lightbox;
|
|
Packit Service |
ed5168 |
const Main = imports.ui.main;
|
|
Packit Service |
ed5168 |
const Params = imports.misc.params;
|
|
Packit Service |
ed5168 |
const Tweener = imports.ui.tweener;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
var OPEN_AND_CLOSE_TIME = 0.1;
|
|
Packit Service |
ed5168 |
var FADE_OUT_DIALOG_TIME = 1.0;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
var State = {
|
|
Packit Service |
ed5168 |
OPENED: 0,
|
|
Packit Service |
ed5168 |
CLOSED: 1,
|
|
Packit Service |
ed5168 |
OPENING: 2,
|
|
Packit Service |
ed5168 |
CLOSING: 3,
|
|
Packit Service |
ed5168 |
FADED_OUT: 4
|
|
Packit Service |
ed5168 |
};
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
var ModalDialog = class {
|
|
Packit Service |
ed5168 |
constructor(params) {
|
|
Packit Service |
ed5168 |
params = Params.parse(params, { shellReactive: false,
|
|
Packit Service |
ed5168 |
styleClass: null,
|
|
Packit Service |
ed5168 |
actionMode: Shell.ActionMode.SYSTEM_MODAL,
|
|
Packit Service |
ed5168 |
shouldFadeIn: true,
|
|
Packit Service |
ed5168 |
shouldFadeOut: true,
|
|
Packit Service |
ed5168 |
destroyOnClose: true });
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.state = State.CLOSED;
|
|
Packit Service |
ed5168 |
this._hasModal = false;
|
|
Packit Service |
ed5168 |
this._actionMode = params.actionMode;
|
|
Packit Service |
ed5168 |
this._shellReactive = params.shellReactive;
|
|
Packit Service |
ed5168 |
this._shouldFadeIn = params.shouldFadeIn;
|
|
Packit Service |
ed5168 |
this._shouldFadeOut = params.shouldFadeOut;
|
|
Packit Service |
ed5168 |
this._destroyOnClose = params.destroyOnClose;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._group = new St.Widget({ visible: false,
|
|
Packit Service |
ed5168 |
x: 0,
|
|
Packit Service |
ed5168 |
y: 0,
|
|
Packit Service |
ed5168 |
accessible_role: Atk.Role.DIALOG });
|
|
Packit Service |
ed5168 |
Main.layoutManager.modalDialogGroup.add_actor(this._group);
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
let constraint = new Clutter.BindConstraint({ source: global.stage,
|
|
Packit Service |
ed5168 |
coordinate: Clutter.BindCoordinate.ALL });
|
|
Packit Service |
ed5168 |
this._group.add_constraint(constraint);
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._group.connect('destroy', this._onGroupDestroy.bind(this));
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
|
|
Packit Service |
ed5168 |
this._backgroundBin = new St.Bin({ child: this.backgroundStack,
|
|
Packit Service |
ed5168 |
x_fill: true, y_fill: true });
|
|
Packit Service |
ed5168 |
this._monitorConstraint = new Layout.MonitorConstraint();
|
|
Packit Service |
ed5168 |
this._backgroundBin.add_constraint(this._monitorConstraint);
|
|
Packit Service |
ed5168 |
this._group.add_actor(this._backgroundBin);
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.dialogLayout = new Dialog.Dialog(this.backgroundStack, params.styleClass);
|
|
Packit Service |
ed5168 |
this.contentLayout = this.dialogLayout.contentLayout;
|
|
Packit Service |
ed5168 |
this.buttonLayout = this.dialogLayout.buttonLayout;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (!this._shellReactive) {
|
|
Packit Service |
ed5168 |
this._lightbox = new Lightbox.Lightbox(this._group,
|
|
Packit Service |
ed5168 |
{ inhibitEvents: true,
|
|
Packit Service |
ed5168 |
radialEffect: true });
|
|
Packit Service |
ed5168 |
this._lightbox.highlight(this._backgroundBin);
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._eventBlocker = new Clutter.Actor({ reactive: true });
|
|
Packit Service |
ed5168 |
this.backgroundStack.add_actor(this._eventBlocker);
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
global.focus_manager.add_group(this.dialogLayout);
|
|
Packit Service |
ed5168 |
this._initialKeyFocus = null;
|
|
Packit Service |
ed5168 |
this._initialKeyFocusDestroyId = 0;
|
|
Packit Service |
ed5168 |
this._savedKeyFocus = null;
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
destroy() {
|
|
Packit Service |
ed5168 |
this._group.destroy();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
clearButtons() {
|
|
Packit Service |
ed5168 |
this.dialogLayout.clearButtons();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
setButtons(buttons) {
|
|
Packit Service |
ed5168 |
this.clearButtons();
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
for (let buttonInfo of buttons)
|
|
Packit Service |
ed5168 |
this.addButton(buttonInfo);
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
addButton(buttonInfo) {
|
|
Packit Service |
ed5168 |
return this.dialogLayout.addButton(buttonInfo);
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
_onGroupDestroy() {
|
|
Packit Service |
ed5168 |
this.emit('destroy');
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
_fadeOpen(onPrimary) {
|
|
Packit Service |
ed5168 |
if (onPrimary)
|
|
Packit Service |
ed5168 |
this._monitorConstraint.primary = true;
|
|
Packit Service |
ed5168 |
else
|
|
Packit Service |
ed5168 |
this._monitorConstraint.index = global.display.get_current_monitor();
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.state = State.OPENING;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.dialogLayout.opacity = 255;
|
|
Packit Service |
ed5168 |
if (this._lightbox)
|
|
Packit Service |
ed5168 |
this._lightbox.show();
|
|
Packit Service |
ed5168 |
this._group.opacity = 0;
|
|
Packit Service |
ed5168 |
this._group.show();
|
|
Packit Service |
ed5168 |
Tweener.addTween(this._group,
|
|
Packit Service |
ed5168 |
{ opacity: 255,
|
|
Packit Service |
ed5168 |
time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
|
|
Packit Service |
ed5168 |
transition: 'easeOutQuad',
|
|
Packit Service |
ed5168 |
onComplete: () => {
|
|
Packit Service |
ed5168 |
this.state = State.OPENED;
|
|
Packit Service |
ed5168 |
this.emit('opened');
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
});
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
setInitialKeyFocus(actor) {
|
|
Packit Service |
ed5168 |
if (this._initialKeyFocusDestroyId)
|
|
Packit Service |
ed5168 |
this._initialKeyFocus.disconnect(this._initialKeyFocusDestroyId);
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._initialKeyFocus = actor;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._initialKeyFocusDestroyId = actor.connect('destroy', () => {
|
|
Packit Service |
ed5168 |
this._initialKeyFocus = null;
|
|
Packit Service |
ed5168 |
this._initialKeyFocusDestroyId = 0;
|
|
Packit Service |
ed5168 |
});
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
open(timestamp, onPrimary) {
|
|
Packit Service |
ed5168 |
if (this.state == State.OPENED || this.state == State.OPENING)
|
|
Packit Service |
ed5168 |
return true;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (!this.pushModal(timestamp))
|
|
Packit Service |
ed5168 |
return false;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._fadeOpen(onPrimary);
|
|
Packit Service |
ed5168 |
return true;
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
_closeComplete() {
|
|
Packit Service |
ed5168 |
this.state = State.CLOSED;
|
|
Packit Service |
ed5168 |
this._group.hide();
|
|
Packit Service |
ed5168 |
this.emit('closed');
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (this._destroyOnClose)
|
|
Packit Service |
ed5168 |
this.destroy();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
close(timestamp) {
|
|
Packit Service |
ed5168 |
if (this.state == State.CLOSED || this.state == State.CLOSING)
|
|
Packit Service |
ed5168 |
return;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.state = State.CLOSING;
|
|
Packit Service |
ed5168 |
this.popModal(timestamp);
|
|
Packit Service |
ed5168 |
this._savedKeyFocus = null;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (this._shouldFadeOut)
|
|
Packit Service |
ed5168 |
Tweener.addTween(this._group,
|
|
Packit Service |
ed5168 |
{ opacity: 0,
|
|
Packit Service |
ed5168 |
time: OPEN_AND_CLOSE_TIME,
|
|
Packit Service |
ed5168 |
transition: 'easeOutQuad',
|
|
Packit Service |
ed5168 |
onComplete: this._closeComplete.bind(this)
|
|
Packit Service |
ed5168 |
})
|
|
Packit Service |
ed5168 |
else
|
|
Packit Service |
ed5168 |
this._closeComplete();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
// Drop modal status without closing the dialog; this makes the
|
|
Packit Service |
ed5168 |
// dialog insensitive as well, so it needs to be followed shortly
|
|
Packit Service |
ed5168 |
// by either a close() or a pushModal()
|
|
Packit Service |
ed5168 |
popModal(timestamp) {
|
|
Packit Service |
ed5168 |
if (!this._hasModal)
|
|
Packit Service |
ed5168 |
return;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
let focus = global.stage.key_focus;
|
|
Packit Service |
ed5168 |
if (focus && this._group.contains(focus))
|
|
Packit Service |
ed5168 |
this._savedKeyFocus = focus;
|
|
Packit Service |
ed5168 |
else
|
|
Packit Service |
ed5168 |
this._savedKeyFocus = null;
|
|
Packit Service |
ed5168 |
Main.popModal(this._group, timestamp);
|
|
Packit Service |
ed5168 |
this._hasModal = false;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (!this._shellReactive)
|
|
Packit Service |
ed5168 |
this._eventBlocker.raise_top();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
pushModal(timestamp) {
|
|
Packit Service |
ed5168 |
if (this._hasModal)
|
|
Packit Service |
ed5168 |
return true;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
let params = { actionMode: this._actionMode };
|
|
Packit Service |
ed5168 |
if (timestamp)
|
|
Packit Service |
ed5168 |
params['timestamp'] = timestamp;
|
|
Packit Service |
ed5168 |
if (!Main.pushModal(this._group, params))
|
|
Packit Service |
ed5168 |
return false;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this._hasModal = true;
|
|
Packit Service |
ed5168 |
if (this._savedKeyFocus) {
|
|
Packit Service |
ed5168 |
this._savedKeyFocus.grab_key_focus();
|
|
Packit Service |
ed5168 |
this._savedKeyFocus = null;
|
|
Packit Service |
ed5168 |
} else {
|
|
Packit Service |
ed5168 |
let focus = this._initialKeyFocus || this.dialogLayout.initialKeyFocus;
|
|
Packit Service |
ed5168 |
focus.grab_key_focus();
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (!this._shellReactive)
|
|
Packit Service |
ed5168 |
this._eventBlocker.lower_bottom();
|
|
Packit Service |
ed5168 |
return true;
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
// This method is like close, but fades the dialog out much slower,
|
|
Packit Service |
ed5168 |
// and leaves the lightbox in place. Once in the faded out state,
|
|
Packit Service |
ed5168 |
// the dialog can be brought back by an open call, or the lightbox
|
|
Packit Service |
ed5168 |
// can be dismissed by a close call.
|
|
Packit Service |
ed5168 |
//
|
|
Packit Service |
ed5168 |
// The main point of this method is to give some indication to the user
|
|
Packit Service |
ed5168 |
// that the dialog reponse has been acknowledged but will take a few
|
|
Packit Service |
ed5168 |
// moments before being processed.
|
|
Packit Service |
ed5168 |
// e.g., if a user clicked "Log Out" then the dialog should go away
|
|
Packit Service |
ed5168 |
// imediately, but the lightbox should remain until the logout is
|
|
Packit Service |
ed5168 |
// complete.
|
|
Packit Service |
ed5168 |
_fadeOutDialog(timestamp) {
|
|
Packit Service |
ed5168 |
if (this.state == State.CLOSED || this.state == State.CLOSING)
|
|
Packit Service |
ed5168 |
return;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
if (this.state == State.FADED_OUT)
|
|
Packit Service |
ed5168 |
return;
|
|
Packit Service |
ed5168 |
|
|
Packit Service |
ed5168 |
this.popModal(timestamp);
|
|
Packit Service |
ed5168 |
Tweener.addTween(this.dialogLayout,
|
|
Packit Service |
ed5168 |
{ opacity: 0,
|
|
Packit Service |
ed5168 |
time: FADE_OUT_DIALOG_TIME,
|
|
Packit Service |
ed5168 |
transition: 'easeOutQuad',
|
|
Packit Service |
ed5168 |
onComplete: () => {
|
|
Packit Service |
ed5168 |
this.state = State.FADED_OUT;
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
});
|
|
Packit Service |
ed5168 |
}
|
|
Packit Service |
ed5168 |
};
|
|
Packit Service |
ed5168 |
Signals.addSignalMethods(ModalDialog.prototype);
|