Skip to content

Commit c9d3b86

Browse files
dennisfranciseszkadev
authored andcommitted
browser: parts-preview: jsdialog based context menu
Signed-off-by: Dennis Francis <dennis.francis@collabora.com> Change-Id: I614947cc8a4aa97d2b5aab869f9b811d84309218
1 parent 1b878b2 commit c9d3b86

File tree

1 file changed

+183
-125
lines changed

1 file changed

+183
-125
lines changed

browser/src/control/Control.PartsPreview.js

Lines changed: 183 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* window.L.Control.PartsPreview
1313
*/
1414

15-
/* global _ app $ Hammer _UNO cool */
15+
/* global _ app $ Hammer _UNO cool JSDialog */
1616
window.L.Control.PartsPreview = window.L.Control.extend({
1717
options: {
1818
fetchThumbnail: true,
@@ -44,6 +44,7 @@ window.L.Control.PartsPreview = window.L.Control.extend({
4444
this._width = 0;
4545
this._height = 0;
4646
this.scrollTimer = null;
47+
this._menuPosEl = null;
4748

4849
document.body.addEventListener('click', (e) => {
4950
if (!e.partsFocusedApplied && this.partsFocused)
@@ -181,6 +182,16 @@ window.L.Control.PartsPreview = window.L.Control.extend({
181182
return !((x > nLeft && x < width - nRight) && (y > nTop && y < height - nBottom));
182183
},
183184

185+
_getMenuPosEl: function () {
186+
if (!this._menuPosEl) {
187+
this._menuPosEl = document.createElement('div');
188+
this._menuPosEl.id = 'slide-context-menu-pos';
189+
this._menuPosEl.style.position = 'absolute';
190+
this._container.appendChild(this._menuPosEl);
191+
}
192+
return this._menuPosEl;
193+
},
194+
184195
_createPreview: function (i, hashCode) {
185196
var frameClass = 'preview-frame ' + this.options.frameClass;
186197
var frame = window.L.DomUtil.create('div', frameClass, this._partsPreviewCont);
@@ -245,12 +256,9 @@ window.L.Control.PartsPreview = window.L.Control.extend({
245256
var that = this;
246257
window.L.DomEvent.on(frame, 'contextmenu', function(e) {
247258
var isMasterView = this._map['stateChangeHandler'].getItemValue('.uno:SlideMasterPage');
248-
var pcw = document.getElementById('presentation-controls-wrapper');
249-
var $trigger = $(pcw);
250-
if (isMasterView === 'true' || app.map.isReadOnlyMode()) {
251-
$trigger.contextMenu(false);
259+
if (isMasterView === 'true' || app.map.isReadOnlyMode())
252260
return;
253-
}
261+
e.preventDefault();
254262

255263
var nPos = undefined;
256264
if (this.isPaddingClick(frame, e, 'top'))
@@ -260,137 +268,187 @@ window.L.Control.PartsPreview = window.L.Control.extend({
260268
else if (this.isPaddingClick(frame, e, 'right') || this.isPaddingClick(frame, e, 'left'))
261269
nPos = that._findClickedPart(frame);
262270

263-
$trigger.contextMenu(true);
264271
if (!that._isSelected(e))
265272
that._setPart(e);
266-
$.contextMenu({
267-
selector: '#'+frame.id,
268-
className: 'cool-font',
269-
items: {
270-
paste: {
271-
name: app.IconUtil.createMenuItemLink(_('Paste'), 'Paste'),
272-
isHtmlName: true,
273-
callback: function(key, options) {
274-
if (nPos === undefined)
275-
nPos = that._findClickedPart(options.$trigger[0]);
276-
that._pasteSlide(nPos);
277-
},
278-
visible: function() {
279-
// Show paste if we have a local copied slide OR
280-
// the system clipboard API is available (may have content from another tab)
281-
return that.copiedSlide || window.L.Browser.clipboardApiAvailable;
282-
}
283-
},
284-
newslide: {
285-
name: app.IconUtil.createMenuItemLink( _UNO(that._map._docLayer._docType == 'presentation' ? '.uno:InsertSlide' : '.uno:InsertPage', 'presentation'), 'InsertPage'),
286-
isHtmlName: true,
287-
callback: function() { that._map.insertPage(nPos); }
288-
}
289-
},
290-
events: {
291-
hide: function() {
292-
img.focus();
293-
}
294-
}
273+
img.focus();
274+
275+
var entries = [];
276+
if (that.copiedSlide || window.L.Browser.clipboardApiAvailable) {
277+
entries.push({
278+
id: 'paste',
279+
type: 'comboboxentry',
280+
text: _('Paste'),
281+
img: 'Paste',
282+
pos: 0,
283+
});
284+
}
285+
entries.push({
286+
id: 'newslide',
287+
type: 'comboboxentry',
288+
text: _UNO(that._map._docLayer._docType == 'presentation' ? '.uno:InsertSlide' : '.uno:InsertPage', 'presentation'),
289+
img: 'InsertPage',
290+
pos: 0,
295291
});
292+
293+
var menuPosEl = that._getMenuPosEl();
294+
var rect = that._container.getBoundingClientRect();
295+
menuPosEl.style.left = (e.clientX - rect.left) + 'px';
296+
menuPosEl.style.top = (e.clientY - rect.top) + 'px';
297+
298+
var callback = function(objectType, eventType, object, data, entry) {
299+
if (eventType !== 'selected')
300+
return false;
301+
if (entry.id === 'paste') {
302+
if (nPos === undefined)
303+
nPos = that._findClickedPart(frame);
304+
that._pasteSlide(nPos);
305+
} else if (entry.id === 'newslide') {
306+
that._map.insertPage(nPos);
307+
}
308+
JSDialog.CloseAllDropdowns();
309+
return true;
310+
};
311+
312+
JSDialog.OpenDropdown(
313+
'slide-frame-menu',
314+
menuPosEl,
315+
entries,
316+
callback,
317+
'',
318+
false,
319+
);
296320
}, this);
297321

298322
window.L.DomEvent.on(img, 'contextmenu', function(e) {
323+
e.stopPropagation();
299324
var isMasterView = this._map['stateChangeHandler'].getItemValue('.uno:SlideMasterPage');
300-
var $trigger = $('#' + img.id);
301-
if (isMasterView === 'true' || app.map.isReadOnlyMode()) {
302-
$trigger.contextMenu(false);
325+
if (isMasterView === 'true' || app.map.isReadOnlyMode())
303326
return;
304-
}
305-
$trigger.contextMenu(true);
327+
e.preventDefault();
328+
306329
if (!that._isSelected(e))
307330
that._setPart(e);
331+
img.focus();
308332

309-
$.contextMenu({
310-
selector: '#' + img.id,
311-
className: 'cool-font',
312-
items: {
313-
copy: {
314-
name: app.IconUtil.createMenuItemLink(_('Copy'), 'Copy'),
315-
isHtmlName: true,
316-
callback: function() {
317-
that.copiedSlide = e;
318-
that._map._clip.clearSelection();
319-
that._map._clip.setTextSelectionType('slide');
320-
that._map._clip._execCopyCutPaste('copy', '.uno:CopySlide');
321-
},
322-
visible: function() {
323-
return !(app.impress.hasOverviewPage && that._map._docLayer._selectedPart === 0);
324-
}
325-
},
326-
paste: {
327-
name: app.IconUtil.createMenuItemLink(_('Paste'), 'Paste'),
328-
isHtmlName: true,
329-
callback: function() {
330-
that._pasteSlide();
331-
},
332-
},
333-
newslide: {
334-
name: app.IconUtil.createMenuItemLink(_UNO(that._map._docLayer._docType == 'presentation' ? '.uno:InsertSlide' : '.uno:InsertPage', 'presentation'), 'InsertPage'),
335-
isHtmlName: true,
336-
callback: function() { that._map.insertPage(); }
337-
},
338-
duplicateslide: {
339-
name: app.IconUtil.createMenuItemLink(_UNO(that._map._docLayer._docType == 'presentation' ? '.uno:DuplicateSlide' : '.uno:DuplicatePage', 'presentation'), 'DuplicatePage'),
340-
isHtmlName: true,
341-
callback: function() { that._map.duplicatePage(); }
342-
},
343-
delete: {
344-
name: app.IconUtil.createMenuItemLink(_UNO(that._map._docLayer._docType == 'presentation' ? '.uno:DeleteSlide' : '.uno:DeletePage', 'presentation'), 'DeletePage'),
345-
isHtmlName: true,
346-
callback: function() { app.dispatcher.dispatch('deletepage'); },
347-
visible: function() {
348-
return that._map._docLayer._parts > 1;
349-
}
350-
},
351-
slideproperties: {
352-
name: app.IconUtil.createMenuItemLink(_UNO(that._map._docLayer._docType == 'presentation' ? '.uno:SlideSetup' : '.uno:PageSetup', 'presentation'), 'PageSetup'),
353-
isHtmlName: true,
354-
callback: function() {
355-
app.socket.sendMessage('uno .uno:PageSetup');
356-
}
357-
},
358-
showslide: {
359-
name: app.IconUtil.createMenuItemLink(_UNO('.uno:ShowSlide', 'presentation'), 'ShowSlide'),
360-
isHtmlName: true,
361-
callback: function(key, options) {
362-
var part = that._findClickedPart(options.$trigger[0].parentNode);
363-
if (part !== null) {
364-
that._map.showSlide();
365-
}
366-
},
367-
visible: function(key, options) {
368-
var part = that._findClickedPart(options.$trigger[0].parentNode);
369-
return that._map._docLayer._docType === 'presentation' && app.impress.isSlideHidden(parseInt(part) - 1);
370-
}
371-
},
372-
hideslide: {
373-
name: app.IconUtil.createMenuItemLink(_UNO('.uno:HideSlide', 'presentation'), 'Hideslide'),
374-
isHtmlName: true,
375-
callback: function(key, options) {
376-
var part = that._findClickedPart(options.$trigger[0].parentNode);
377-
if (part !== null) {
378-
that._map.hideSlide();
379-
}
380-
},
381-
visible: function(key, options) {
382-
var part = that._findClickedPart(options.$trigger[0].parentNode);
383-
return that._map._docLayer._docType === 'presentation' && !app.impress.isSlideHidden(parseInt(part) - 1);
384-
}
385-
}
386-
},
387-
events: {
388-
hide: function() {
389-
// Restore focus to the element that opened the menu
390-
img.focus();
391-
}
392-
}
333+
var part = that._findClickedPart(img.parentNode);
334+
var partIndex = parseInt(part) - 1;
335+
var isPresentation = that._map._docLayer._docType === 'presentation';
336+
337+
var entries = [];
338+
if (!(app.impress.hasOverviewPage && that._map._docLayer._selectedPart === 0)) {
339+
entries.push({
340+
id: 'copy',
341+
type: 'comboboxentry',
342+
text: _('Copy'),
343+
img: 'Copy',
344+
pos: 0,
345+
});
346+
}
347+
entries.push({
348+
id: 'paste',
349+
type: 'comboboxentry',
350+
text: _('Paste'),
351+
img: 'Paste',
352+
pos: 0,
353+
});
354+
entries.push({
355+
id: 'newslide',
356+
type: 'comboboxentry',
357+
text: _UNO(isPresentation ? '.uno:InsertSlide' : '.uno:InsertPage', 'presentation'),
358+
img: 'InsertPage',
359+
pos: 0,
360+
});
361+
entries.push({
362+
id: 'duplicateslide',
363+
type: 'comboboxentry',
364+
text: _UNO(isPresentation ? '.uno:DuplicateSlide' : '.uno:DuplicatePage', 'presentation'),
365+
img: 'DuplicatePage',
366+
pos: 0,
367+
});
368+
if (that._map._docLayer._parts > 1) {
369+
entries.push({
370+
id: 'delete',
371+
type: 'comboboxentry',
372+
text: _UNO(isPresentation ? '.uno:DeleteSlide' : '.uno:DeletePage', 'presentation'),
373+
img: 'DeletePage',
374+
pos: 0,
375+
});
376+
}
377+
entries.push({
378+
id: 'slideproperties',
379+
type: 'comboboxentry',
380+
text: _UNO(isPresentation ? '.uno:SlideSetup' : '.uno:PageSetup', 'presentation'),
381+
img: 'PageSetup',
382+
pos: 0,
393383
});
384+
if (isPresentation && app.impress.isSlideHidden(partIndex)) {
385+
entries.push({
386+
id: 'showslide',
387+
type: 'comboboxentry',
388+
text: _UNO('.uno:ShowSlide', 'presentation'),
389+
img: 'ShowSlide',
390+
pos: 0,
391+
});
392+
}
393+
if (isPresentation && !app.impress.isSlideHidden(partIndex)) {
394+
entries.push({
395+
id: 'hideslide',
396+
type: 'comboboxentry',
397+
text: _UNO('.uno:HideSlide', 'presentation'),
398+
img: 'Hideslide',
399+
pos: 0,
400+
});
401+
}
402+
403+
var menuPosEl = that._getMenuPosEl();
404+
var rect = that._container.getBoundingClientRect();
405+
menuPosEl.style.left = (e.clientX - rect.left) + 'px';
406+
menuPosEl.style.top = (e.clientY - rect.top) + 'px';
407+
408+
var callback = function(objectType, eventType, object, data, entry) {
409+
if (eventType !== 'selected')
410+
return false;
411+
switch (entry.id) {
412+
case 'copy':
413+
that.copiedSlide = e;
414+
that._map._clip.clearSelection();
415+
that._map._clip.setTextSelectionType('slide');
416+
that._map._clip._execCopyCutPaste('copy', '.uno:CopySlide');
417+
break;
418+
case 'paste':
419+
that._pasteSlide();
420+
break;
421+
case 'newslide':
422+
that._map.insertPage();
423+
break;
424+
case 'duplicateslide':
425+
that._map.duplicatePage();
426+
break;
427+
case 'delete':
428+
app.dispatcher.dispatch('deletepage');
429+
break;
430+
case 'slideproperties':
431+
app.socket.sendMessage('uno .uno:PageSetup');
432+
break;
433+
case 'showslide':
434+
that._map.showSlide();
435+
break;
436+
case 'hideslide':
437+
that._map.hideSlide();
438+
break;
439+
}
440+
JSDialog.CloseAllDropdowns();
441+
return true;
442+
};
443+
444+
JSDialog.OpenDropdown(
445+
'slide-img-menu',
446+
menuPosEl,
447+
entries,
448+
callback,
449+
'',
450+
false,
451+
);
394452
}, this);
395453

396454
var imgSize = this._map.getPreview(i, i,

0 commit comments

Comments
 (0)