feat(core): 优化nav右侧菜单栏
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
goog.loadJs('common', () => {
|
||||
|
||||
goog.require('path');
|
||||
goog.require('layui');
|
||||
goog.require('hotkeys');
|
||||
goog.require('Mixly.Url');
|
||||
goog.require('Mixly.Config');
|
||||
goog.require('Mixly.Env');
|
||||
goog.require('Mixly.Msg');
|
||||
goog.require('Mixly.Drag');
|
||||
goog.require('Mixly.Nav');
|
||||
goog.require('Mixly.Menu');
|
||||
goog.require('Mixly.ContextMenu');
|
||||
goog.require('Mixly.Workspace');
|
||||
goog.require('Mixly.FooterBar');
|
||||
goog.require('Mixly.HTMLTemplate');
|
||||
@@ -27,6 +29,7 @@ goog.require('Mixly.Web.BU');
|
||||
goog.require('Mixly.Web.FS');
|
||||
goog.require('Mixly.Web.File');
|
||||
goog.require('Mixly.Web.Serial');
|
||||
goog.require('Mixly.WebCompiler.ArduShell');
|
||||
goog.require('Mixly.WebSocket.File');
|
||||
goog.require('Mixly.WebSocket.Serial');
|
||||
goog.require('Mixly.WebSocket.ArduShell');
|
||||
@@ -40,6 +43,8 @@ const {
|
||||
Msg,
|
||||
Drag,
|
||||
Nav,
|
||||
Menu,
|
||||
ContextMenu,
|
||||
Workspace,
|
||||
FooterBar,
|
||||
HTMLTemplate,
|
||||
@@ -49,6 +54,7 @@ const {
|
||||
EditorMix,
|
||||
Electron = {},
|
||||
Web = {},
|
||||
WebCompiler = {},
|
||||
WebSocket = {}
|
||||
} = Mixly;
|
||||
|
||||
@@ -70,18 +76,20 @@ const {
|
||||
FS,
|
||||
File,
|
||||
LibManager,
|
||||
ArduShell,
|
||||
BU,
|
||||
PythonShell,
|
||||
Serial
|
||||
} = currentObj;
|
||||
|
||||
let ArduShell = null;
|
||||
if (!goog.isElectron && Env.hasCompiler) {
|
||||
ArduShell = WebCompiler.ArduShell;
|
||||
} else {
|
||||
ArduShell = currentObj.ArduShell;
|
||||
}
|
||||
|
||||
const { BOARD, SELECTED_BOARD } = Config;
|
||||
|
||||
const { layer } = layui;
|
||||
|
||||
const electron = Mixly.require('electron');
|
||||
|
||||
|
||||
class App extends Component {
|
||||
static {
|
||||
@@ -116,7 +124,6 @@ class App extends Component {
|
||||
this.#footerbar_ = new FooterBar();
|
||||
this.#footerbar_.mountOn($content.find('.mixly-footerbar'));
|
||||
this.#addEventsListenerForNav_();
|
||||
this.#addEventsListenerForWorkspace_();
|
||||
this.#addObserver_();
|
||||
Mixly.mainStatusBarTabs = this.#workspace_.getStatusBarsManager();
|
||||
Serial.refreshPorts();
|
||||
@@ -433,211 +440,202 @@ class App extends Component {
|
||||
$a.addClass('codicon-layout-panel');
|
||||
});
|
||||
|
||||
const fileMenu = new Menu();
|
||||
const settingMenu = new Menu();
|
||||
|
||||
this.#nav_.register({
|
||||
id: 'file',
|
||||
displayText: Msg.Lang['nav.btn.file'],
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
displayText: `${Msg.Lang['nav.btn.file']}(F)`,
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 1
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-doc-new',
|
||||
id: ['file', 'new-file'],
|
||||
displayText: Msg.Lang['nav.btn.file.new'],
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
callback: () => File.new(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 1
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-doc',
|
||||
id: ['file', 'open-file'],
|
||||
displayText: Msg.Lang['nav.btn.file.open'],
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
callback: (elem) => File.open(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 2
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
id: ['file', 'hr'],
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 3
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-floppy',
|
||||
id: ['file', 'save-file'],
|
||||
displayText: Msg.Lang['nav.btn.file.save'],
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
callback: (elem) => File.save(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 4
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-save-as',
|
||||
id: ['file', 'save-as-file'],
|
||||
displayText: Msg.Lang['nav.btn.file.saveAs'],
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
callback: () => File.saveAs(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 5
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
id: ['file', 'hr'],
|
||||
preconditionFn: () => {
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 6
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-export',
|
||||
id: ['file', 'export-file'],
|
||||
displayText: Msg.Lang['nav.btn.file.exportAs'],
|
||||
preconditionFn: () => {
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
callback: (elem) => File.exportLib(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 7
|
||||
weight: 1,
|
||||
menu: fileMenu
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
id: 'setting',
|
||||
displayText: Msg.Lang['nav.btn.setting'],
|
||||
displayText: `${Msg.Lang['nav.btn.setting']}(S)`,
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 2,
|
||||
menu: settingMenu
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 0,
|
||||
id: 'new',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 1
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.file.new'], 'Ctrl+N'),
|
||||
callback: () => File.new()
|
||||
}
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-menu',
|
||||
id: ['setting', 'manage-libs'],
|
||||
displayText: Msg.Lang['nav.btn.setting.manageLibs'],
|
||||
hotkeys('ctrl+n', function(event) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
File.new();
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 1,
|
||||
id: 'open-file',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.file.open'], 'Ctrl+O'),
|
||||
callback: (key, opt) => File.open()
|
||||
}
|
||||
});
|
||||
|
||||
hotkeys('ctrl+o', function(event) {
|
||||
event.preventDefault();
|
||||
File.open();
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 2,
|
||||
id: 'sep1',
|
||||
data: '---------'
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 3,
|
||||
id: 'save',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.file.save'], 'Ctrl+S'),
|
||||
callback: () => File.save()
|
||||
}
|
||||
});
|
||||
|
||||
hotkeys('ctrl+s', function(event) {
|
||||
event.preventDefault();
|
||||
File.save();
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 4,
|
||||
id: 'save-as',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.file.saveAs'], 'Ctrl+Shift+S'),
|
||||
callback: () => File.saveAs()
|
||||
}
|
||||
});
|
||||
|
||||
hotkeys('ctrl+shift+s', function(event) {
|
||||
event.preventDefault();
|
||||
File.saveAs();
|
||||
});
|
||||
|
||||
fileMenu.add({
|
||||
weight: 5,
|
||||
id: 'sep2',
|
||||
preconditionFn: () => {
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
callback: () => LibManager.showManageDialog(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 1
|
||||
data: '---------'
|
||||
});
|
||||
|
||||
/*this.#nav_.register({
|
||||
icon: 'icon-upload-1',
|
||||
id: ['setting', 'firmware'],
|
||||
displayText: Msg.Lang['nav.btn.setting.firmware'],
|
||||
fileMenu.add({
|
||||
weight: 6,
|
||||
id: 'export',
|
||||
preconditionFn: () => {
|
||||
if (goog.isElectron) {
|
||||
return !!BOARD?.burn?.special;
|
||||
} else {
|
||||
return !!BOARD?.web?.burn?.special;
|
||||
}
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
callback: () => BU.burnWithSpecialBin(),
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 2
|
||||
});*/
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.file.exportAs'], 'Ctrl+E'),
|
||||
callback: () => File.exportLib()
|
||||
}
|
||||
});
|
||||
|
||||
this.#nav_.register({
|
||||
icon: 'icon-comment-1',
|
||||
id: ['setting', 'feedback'],
|
||||
displayText: Msg.Lang['nav.btn.setting.feedback'],
|
||||
if (goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary) {
|
||||
hotkeys('ctrl+e', function(event) {
|
||||
event.preventDefault();
|
||||
File.exportLib();
|
||||
});
|
||||
}
|
||||
|
||||
settingMenu.add({
|
||||
weight: 0,
|
||||
id: 'feedback',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
callback: (elem) => {
|
||||
const href = 'https://gitee.com/mixly2/mixly2.0_src/issues';
|
||||
Url.open(href);
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.setting.feedback'], 'Ctrl+Shift+F'),
|
||||
callback: () => {
|
||||
const href = 'https://gitee.com/bnu_mixly/mixly3/issues';
|
||||
Url.open(href);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
hotkeys('ctrl+shift+f', function(event) {
|
||||
const href = 'https://gitee.com/bnu_mixly/mixly3/issues';
|
||||
Url.open(href);
|
||||
});
|
||||
|
||||
settingMenu.add({
|
||||
weight: 1,
|
||||
id: 'wiki',
|
||||
preconditionFn: () => {
|
||||
return true;
|
||||
},
|
||||
scopeType: Nav.Scope.RIGHT,
|
||||
weight: 2
|
||||
});
|
||||
}
|
||||
|
||||
#addEventsListenerForWorkspace_() {
|
||||
const editorsManager = this.#workspace_.getEditorsManager();
|
||||
const editorTabs = editorsManager.getTabs();
|
||||
|
||||
editorTabs.bind('tabCheckDestroy', (event) => {
|
||||
const { tabEl } = event.detail;
|
||||
const id = $(tabEl).attr('data-tab-id');
|
||||
const editor = editorsManager.get(id);
|
||||
if (!editor) {
|
||||
return;
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem('文档', 'Ctrl+H'),
|
||||
callback: () => {
|
||||
const href = 'https://mixly.readthedocs.io/zh-cn/latest/contents.html';
|
||||
Url.open(href);
|
||||
}
|
||||
}
|
||||
if (editor.isDirty()) {
|
||||
layer.confirm(`是否保存对${path.basename(id)}的修改?`, {
|
||||
title: false,
|
||||
shade: LayerExt.SHADE_ALL,
|
||||
resize: false,
|
||||
btn: ['保存', '不保存', '取消'],
|
||||
closeBtn: 1,
|
||||
btn1: (index) => {
|
||||
const $tab = editor.getTab();
|
||||
if ($tab.attr('data-link-file') === 'true') {
|
||||
FS.writeFile($tab.attr('data-tab-id'), editor.getValue())
|
||||
.then(() => {
|
||||
editor.removeDirty();
|
||||
editorsManager.remove(id);
|
||||
layer.close(index);
|
||||
layer.msg('已保存文件');
|
||||
})
|
||||
.catch(Debug.error);
|
||||
} else {
|
||||
FS.showSaveFilePicker(id, $tab.attr('data-tab-type'))
|
||||
.then((filePath) => {
|
||||
if (!filePath) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
return FS.writeFile(filePath, editor.getValue());
|
||||
})
|
||||
.then((status) => {
|
||||
if (status) {
|
||||
return;
|
||||
}
|
||||
editor.removeDirty();
|
||||
editorsManager.remove(id);
|
||||
layer.close(index);
|
||||
layer.msg('已保存文件');
|
||||
})
|
||||
.catch(Debug.error);
|
||||
}
|
||||
},
|
||||
btn2: (index) => {
|
||||
editor.removeDirty();
|
||||
editorsManager.remove(id);
|
||||
layer.close(index);
|
||||
},
|
||||
btn3: (index) => {
|
||||
layer.close(index);
|
||||
},
|
||||
success: (layero) => {
|
||||
const { classList } = layero[0].childNodes[1].childNodes[0];
|
||||
classList.remove('layui-layer-close2');
|
||||
classList.add('layui-layer-close1');
|
||||
}
|
||||
});
|
||||
}
|
||||
return !editor.isDirty();
|
||||
});
|
||||
|
||||
hotkeys('ctrl+h', function(event) {
|
||||
const href = 'https://mixly.readthedocs.io/zh-cn/latest/contents.html';
|
||||
Url.open(href);
|
||||
});
|
||||
|
||||
settingMenu.add({
|
||||
weight: 2,
|
||||
id: 'sep1',
|
||||
preconditionFn: () => {
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
data: '---------'
|
||||
});
|
||||
|
||||
settingMenu.add({
|
||||
weight: 3,
|
||||
id: 'manage-libraries',
|
||||
preconditionFn: () => {
|
||||
return goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary;
|
||||
},
|
||||
data: {
|
||||
isHtmlName: true,
|
||||
name: ContextMenu.getItem(Msg.Lang['nav.btn.setting.manageLibs'], 'Ctrl+M'),
|
||||
callback: () => LibManager.showManageDialog()
|
||||
}
|
||||
});
|
||||
|
||||
if (goog.isElectron && BOARD?.nav?.setting?.thirdPartyLibrary) {
|
||||
hotkeys('ctrl+m', function(event) {
|
||||
LibManager.showManageDialog();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#addObserver_() {
|
||||
@@ -653,7 +651,7 @@ class App extends Component {
|
||||
if (goog.isElectron) {
|
||||
Loader.onbeforeunload();
|
||||
} else {
|
||||
let href = Env.srcDirPath + 'index.html?' + Url.jsonToUrl({ boardType: BOARD.boardType });
|
||||
let href = path.join(Env.srcDirPath, 'index.html') + '?' + Url.jsonToUrl({ boardType: BOARD.boardType });
|
||||
window.location.replace(href);
|
||||
}
|
||||
}
|
||||
|
||||
211
common/modules/mixly-modules/common/dropdown-menu-group.js
Normal file
211
common/modules/mixly-modules/common/dropdown-menu-group.js
Normal file
@@ -0,0 +1,211 @@
|
||||
goog.loadJs('common', () => {
|
||||
|
||||
goog.require('tippy');
|
||||
goog.require('Mixly.Menu');
|
||||
goog.require('Mixly.Registry');
|
||||
goog.require('Mixly.IdGenerator');
|
||||
goog.require('Mixly.ContextMenu');
|
||||
goog.require('Mixly.DropdownMenu');
|
||||
goog.provide('Mixly.DropdownMenuGroup');
|
||||
|
||||
const {
|
||||
Menu,
|
||||
Registry,
|
||||
IdGenerator,
|
||||
ContextMenu,
|
||||
DropdownMenu
|
||||
} = Mixly;
|
||||
|
||||
|
||||
class DropdownMenuGroup {
|
||||
#shown_ = false;
|
||||
#singleton_ = null;
|
||||
#menuItems_ = [];
|
||||
#ids_ = {};
|
||||
#instanceIds_ = {};
|
||||
#activeInstance_ = null;
|
||||
#hided_ = false;
|
||||
#trigged_ = false;
|
||||
#$instancePopper_ = null;
|
||||
#$instanceContent_ = null;
|
||||
#$content_ = null;
|
||||
constructor(elem) {
|
||||
this.#$content_ = $(elem);
|
||||
this.#$content_.css('z-index', 200);
|
||||
this.#singleton_ = tippy.createSingleton([], {
|
||||
interactive: true,
|
||||
maxWidth: 'none',
|
||||
offset: [0, 3],
|
||||
appendTo: document.body,
|
||||
arrow: false,
|
||||
placement: 'bottom-end',
|
||||
animation: 'shift-toward-extreme',
|
||||
hideOnClick: false,
|
||||
delay: [200, null],
|
||||
onShow: () => {
|
||||
if (this.#activeInstance_) {
|
||||
this.show(this.#activeInstance_.id);
|
||||
}
|
||||
this.#shown_ = true;
|
||||
},
|
||||
onTrigger: (_, event) => {
|
||||
const id = $(event.currentTarget).attr('data-id');
|
||||
if (this.#shown_) {
|
||||
if (this.#activeInstance_) {
|
||||
this.#trigged_ = true;
|
||||
this.hide(this.#activeInstance_.id);
|
||||
this.#activeInstance_ = null;
|
||||
}
|
||||
this.show(id);
|
||||
}
|
||||
this.#activeInstance_ = this.#instanceIds_[id].instance;
|
||||
},
|
||||
onHide: () => {
|
||||
if (this.#hided_) {
|
||||
this.#shown_ = false;
|
||||
}
|
||||
return this.#hided_;
|
||||
}
|
||||
});
|
||||
this.#$instancePopper_ = $(this.#singleton_.popper);
|
||||
this.#$instancePopper_.addClass('mixly-drapdown-menu');
|
||||
this.#$instanceContent_ = this.#$instancePopper_.children().children();
|
||||
}
|
||||
|
||||
add(item) {
|
||||
if (!item.id) {
|
||||
if (item.type) {
|
||||
item.id = item.type;
|
||||
} else {
|
||||
item.id = IdGenerator.generate();
|
||||
}
|
||||
}
|
||||
if (!item.weight) {
|
||||
item.weight = 0;
|
||||
}
|
||||
this.remove(item.id);
|
||||
item.$elem = $(`<button class="layui-btn layui-btn-xs layui-btn-primary mixly-nav">${item.displayText}</button>`);
|
||||
const instance = tippy(item.$elem[0]);
|
||||
item.$elem.attr('data-id', instance.id);
|
||||
item.instance = instance;
|
||||
const contextMenuId = IdGenerator.generate();
|
||||
const selector = `body > .mixly-dropdown-menus > div[m-id="${contextMenuId}"]`;
|
||||
const contextMenu = new ContextMenu(selector, {
|
||||
trigger: 'none',
|
||||
appendTo: this.#$instanceContent_,
|
||||
shadow: true,
|
||||
autoHide: false,
|
||||
async: false,
|
||||
zIndex: 150,
|
||||
position: (opt) => {
|
||||
opt.$menu.css('margin', 0);
|
||||
},
|
||||
events: {
|
||||
show: (opt) => {
|
||||
this.#hided_ = false;
|
||||
this.#singleton_.setProps({});
|
||||
},
|
||||
hide: (opt) => {
|
||||
if (this.trigged_) {
|
||||
this.trigged_ = false;
|
||||
return true;
|
||||
}
|
||||
this.#hided_ = true;
|
||||
this.#singleton_.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
item.contextMenu = contextMenu;
|
||||
contextMenu.register('menu', item.menu);
|
||||
contextMenu.bind('getMenu', () => 'menu');
|
||||
item.$menu = $(`<div m-id="${contextMenuId}"><div>`);
|
||||
DropdownMenu.$container.append(item.$menu);
|
||||
let i = 0;
|
||||
for (; i < this.#menuItems_.length; i++) {
|
||||
if (this.#menuItems_[i].weight <= item.weight) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i === this.#menuItems_.length) {
|
||||
if (this.#menuItems_.length) {
|
||||
this.#menuItems_[i - 1].$elem.after(item.$elem);
|
||||
} else {
|
||||
this.#$content_.append(item.$elem);
|
||||
}
|
||||
} else {
|
||||
this.#menuItems_[i].$elem.before(item.$elem);
|
||||
}
|
||||
this.#menuItems_.splice(i, 0, item);
|
||||
this.#ids_[item.id] = item;
|
||||
this.#instanceIds_[instance.id] = item;
|
||||
const instances = [];
|
||||
for (let menuItem of this.#menuItems_) {
|
||||
instances.push(menuItem.instance);
|
||||
}
|
||||
this.#singleton_.setInstances(instances);
|
||||
return item.id;
|
||||
}
|
||||
|
||||
getContextMenu(id) {
|
||||
if (!this.#ids_[id]) {
|
||||
return null;
|
||||
}
|
||||
return this.#ids_[id].contextMenu;
|
||||
}
|
||||
|
||||
remove(id) {
|
||||
let item = this.#ids_[id];
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
delete this.#ids_[id];
|
||||
const instanceId = item.instance.id;
|
||||
delete this.#instanceIds_[instanceId];
|
||||
for (let i in this.#menuItems_) {
|
||||
if (this.#menuItems_[i].id !== id) {
|
||||
continue;
|
||||
}
|
||||
this.#menuItems_.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
item.instance.destroy();
|
||||
item.contextMenu.dispose();
|
||||
item.$elem.remove();
|
||||
item.$menu.remove();
|
||||
item = null;
|
||||
}
|
||||
|
||||
show(instanceId) {
|
||||
const item = this.#instanceIds_[instanceId];
|
||||
item.$menu.contextMenu();
|
||||
}
|
||||
|
||||
hide(instanceId) {
|
||||
const item = this.#instanceIds_[instanceId];
|
||||
item.$menu.contextMenu('hide');
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
this.#$instanceContent_.remove();
|
||||
this.#$instanceContent_ = null;
|
||||
this.#$instancePopper_.remove();
|
||||
this.#$instancePopper_ = null;
|
||||
this.#$content_.empty();
|
||||
this.#$content_ = null;
|
||||
for (let id in this.#ids_) {
|
||||
this.remove(id);
|
||||
}
|
||||
this.#singleton_.destroy();
|
||||
this.#singleton_ = null;
|
||||
this.#menuItems_ = null;
|
||||
this.#ids_ = null;
|
||||
this.#instanceIds_ = null;
|
||||
this.#activeInstance_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
Mixly.DropdownMenuGroup = DropdownMenuGroup;
|
||||
|
||||
});
|
||||
@@ -7,6 +7,9 @@ goog.require('Mixly.XML');
|
||||
goog.require('Mixly.Msg');
|
||||
goog.require('Mixly.HTMLTemplate');
|
||||
goog.require('Mixly.Component');
|
||||
goog.require('Mixly.Menu');
|
||||
goog.require('Mixly.ContextMenu');
|
||||
goog.require('Mixly.DropdownMenuGroup');
|
||||
goog.provide('Mixly.Nav');
|
||||
|
||||
const {
|
||||
@@ -14,7 +17,10 @@ const {
|
||||
XML,
|
||||
Msg,
|
||||
HTMLTemplate,
|
||||
Component
|
||||
Component,
|
||||
Menu,
|
||||
ContextMenu,
|
||||
DropdownMenuGroup
|
||||
} = Mixly;
|
||||
|
||||
const { element } = layui;
|
||||
@@ -76,6 +82,15 @@ class Nav extends Component {
|
||||
new HTMLTemplate(goog.readFileSync(path.join(Env.templatePath, 'html/nav/port-selector-div.html')))
|
||||
);
|
||||
|
||||
/**
|
||||
* 下拉菜单遮罩
|
||||
* @type {String}
|
||||
*/
|
||||
HTMLTemplate.add(
|
||||
'html/nav/shadow.html',
|
||||
new HTMLTemplate(goog.readFileSync(path.join(Env.templatePath, 'html/nav/shadow.html')))
|
||||
);
|
||||
|
||||
Nav.Scope = {
|
||||
'LEFT': -1,
|
||||
'CENTER': 0,
|
||||
@@ -123,8 +138,9 @@ class Nav extends Component {
|
||||
#$editorBtnsContainer_ = null;
|
||||
#$boardSelect_ = null;
|
||||
#$portSelect_ = null;
|
||||
#$shadow_ = $('<div style="position:absolute;z-index:1000;width:100%;background:transparent;bottom:0px;top:var(--nav-height);"></div>');
|
||||
#$shadow_ = $(HTMLTemplate.get('html/nav/shadow.html').render());
|
||||
#btns_ = [];
|
||||
#rightDropdownMenuGroup_ = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -175,7 +191,9 @@ class Nav extends Component {
|
||||
this.#$shadow_.click(() => $merge.select2('close'));
|
||||
this.addEventsType(['changeBoard', 'changePort']);
|
||||
this.#addEventsListener_();
|
||||
this.#rightDropdownMenuGroup_ = new DropdownMenuGroup(this.#$rightMenuContainer_[0]);
|
||||
Nav.add(this);
|
||||
this.list = [];
|
||||
}
|
||||
|
||||
onMounted() {
|
||||
@@ -195,6 +213,22 @@ class Nav extends Component {
|
||||
return this.#$portSelect_;
|
||||
}
|
||||
|
||||
getBoardName() {
|
||||
return this.#$boardSelect_.find(':selected').text();
|
||||
}
|
||||
|
||||
getBoardKey() {
|
||||
return this.#$boardSelect_.val();
|
||||
}
|
||||
|
||||
getPortName() {
|
||||
return this.#$portSelect_.find(':selected').text();
|
||||
}
|
||||
|
||||
getPortKey() {
|
||||
return this.#$portSelect_.val();
|
||||
}
|
||||
|
||||
/**
|
||||
* @function 注册函数
|
||||
* @param config 选项
|
||||
@@ -237,24 +271,6 @@ class Nav extends Component {
|
||||
text: displayText
|
||||
}));
|
||||
break;
|
||||
case Nav.Scope.RIGHT:
|
||||
if (typeof id === 'string') {
|
||||
config.$btn = $(HTMLTemplate.get('html/nav/nav-item-container.html').render({
|
||||
mId: id,
|
||||
text: displayText
|
||||
}));
|
||||
} else {
|
||||
if (displayText) {
|
||||
config.$btn = $(HTMLTemplate.get('html/nav/nav-item.html').render({
|
||||
mId: id.join('-'),
|
||||
icon,
|
||||
text: displayText
|
||||
}));
|
||||
} else {
|
||||
config.$btn = $('<hr>');
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.#add_(config);
|
||||
return config;
|
||||
@@ -277,14 +293,9 @@ class Nav extends Component {
|
||||
this.#addCenterBtn_(config);
|
||||
break;
|
||||
case Nav.Scope.RIGHT:
|
||||
if (typeof id === 'string') {
|
||||
this.#addRightMenu_(config);
|
||||
} else {
|
||||
this.#addRightMenuItem_(config);
|
||||
}
|
||||
this.#addRightBtn_(config);
|
||||
break;
|
||||
}
|
||||
element.render('nav', 'nav-filter');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,10 +384,6 @@ class Nav extends Component {
|
||||
this.resize();
|
||||
}
|
||||
|
||||
#removeLeftBtn_(config) {
|
||||
|
||||
}
|
||||
|
||||
#addCenterBtn_(config) {
|
||||
const { id = '', weight = 0 } = config;
|
||||
let $btn = null;
|
||||
@@ -401,76 +408,15 @@ class Nav extends Component {
|
||||
this.resize();
|
||||
}
|
||||
|
||||
#removeCenterBtn_(config) {
|
||||
|
||||
}
|
||||
|
||||
#addRightMenu_(config) {
|
||||
const { id = '', weight = 0, preconditionFn } = config;
|
||||
#addRightBtn_(config) {
|
||||
const { preconditionFn } = config;
|
||||
if (!preconditionFn()) {
|
||||
return;
|
||||
}
|
||||
const $btns = this.#$rightMenuContainer_.children('li');
|
||||
let $btn = null;
|
||||
for (let i = 0; $btns[i]; i++) {
|
||||
const mId = $($btns[i]).attr('m-id');
|
||||
if (!this.#btns_[mId]) {
|
||||
continue;
|
||||
}
|
||||
if (weight < this.#btns_[mId].weight) {
|
||||
$btn = this.#btns_[mId].$btn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($btn) {
|
||||
$btn.before(config.$btn);
|
||||
} else {
|
||||
this.#$rightMenuContainer_.append(config.$btn);
|
||||
}
|
||||
config.width = this.#getElemWidth_(config.$btn);
|
||||
this.#btns_[id] = config;
|
||||
this.#rightDropdownMenuGroup_.add(config);
|
||||
this.resize();
|
||||
}
|
||||
|
||||
#removeRightMenu_(config) {
|
||||
|
||||
}
|
||||
|
||||
#addRightMenuItem_(config) {
|
||||
const { id = [], weight = 0, preconditionFn } = config;
|
||||
if (!preconditionFn()) {
|
||||
return;
|
||||
}
|
||||
const $li = this.#$rightMenuContainer_.children(`[m-id="${id[0]}"]`);
|
||||
let $btn = null;
|
||||
if (!$li.length) {
|
||||
return;
|
||||
}
|
||||
const $container_ = $li.find('.layui-nav-child');
|
||||
const $btns = $container_.find('dd');
|
||||
for (let i = 0; $btns[i]; i++) {
|
||||
const mId = $($btns[i]).attr('m-id');
|
||||
if (!this.#btns_[mId]) {
|
||||
continue;
|
||||
}
|
||||
if (weight < this.#btns_[mId].weight) {
|
||||
$btn = this.#btns_[mId].$btn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($btn) {
|
||||
$btn.before(config.$btn);
|
||||
} else {
|
||||
$container_.append(config.$btn);
|
||||
}
|
||||
config.width = this.#getElemWidth_(config.$btn);
|
||||
this.#btns_[id.join('-')] = config;
|
||||
}
|
||||
|
||||
#removeRightMenuItem_(config) {
|
||||
|
||||
}
|
||||
|
||||
resize() {
|
||||
super.resize();
|
||||
this.#$boardSelect_.select2('close');
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -19,7 +19,6 @@
|
||||
width: 100%;
|
||||
height: calc(100vh - var(--nav-height) - var(--footer-height));
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
@@ -29,7 +28,6 @@
|
||||
div[m-id="{{d.mId}}"] > .mixly-footerbar {
|
||||
width: 100%;
|
||||
height: var(--footer-height);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
html[data-bs-theme=dark] div[m-id="{{d.mId}}"] > .mixly-footerbar {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background: transparent;
|
||||
z-index: 100;
|
||||
z-index: 400;
|
||||
}
|
||||
</style>
|
||||
<div m-id="{{d.mId}}"></div>
|
||||
@@ -6,7 +6,7 @@
|
||||
height: var(--nav-height);
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
z-index: 100;
|
||||
z-index: 400;
|
||||
}
|
||||
</style>
|
||||
<div m-id="{{d.mId}}"></div>
|
||||
@@ -2,7 +2,4 @@
|
||||
<a style="white-space: nowrap;">
|
||||
{{d.text}}
|
||||
</a>
|
||||
<dl class="layui-nav-child layui-nav-child-r">
|
||||
<!-- 二级菜单 -->
|
||||
</dl>
|
||||
</li>
|
||||
@@ -63,7 +63,7 @@
|
||||
}
|
||||
|
||||
ul[m-id="{{d.mId}}"] button > a {
|
||||
color: rgba(255,255,255,.7);
|
||||
color: rgba(255, 255, 255, .7);
|
||||
-webkit-transition: all .3s;
|
||||
}
|
||||
|
||||
@@ -106,14 +106,25 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ul[m-id="{{d.mId}}"] .left-btn-container {
|
||||
ul[m-id="{{d.mId}}"] > div > .left-btn-container,
|
||||
ul[m-id="{{d.mId}}"] > .right-area > .right-menu-container {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
ul[m-id="{{d.mId}}"] .left-btn-container button {
|
||||
ul[m-id="{{d.mId}}"] > div > .left-btn-container > button[m-id="home-btn"] {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
ul[m-id="{{d.mId}}"] > .right-area > .right-menu-container {
|
||||
margin-left: 10px;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
ul[m-id="{{d.mId}}"] > div > .left-btn-container > button,
|
||||
ul[m-id="{{d.mId}}"] > .right-area > .right-menu-container > button {
|
||||
font-family: "Lato", "Noto Sans SC";
|
||||
height: var(--nav-left-btn-height);
|
||||
font-size: calc(var(--nav-left-btn-font-size) + 4px);
|
||||
font-size: 14px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
|
||||
11
common/templates/html/nav/shadow.html
Normal file
11
common/templates/html/nav/shadow.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<style>
|
||||
div[m-id="{{d.mId}}"] {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
bottom: 0px;
|
||||
top: var(--nav-height);
|
||||
}
|
||||
</style>
|
||||
<div m-id="{{d.mId}}"></div>
|
||||
112
main.js
112
main.js
@@ -102,12 +102,12 @@ function createWindow(filePath = null, indexUrl = null) {
|
||||
else
|
||||
win.loadFile('./src/index.html');
|
||||
|
||||
//打开或关闭开发者工具
|
||||
// 打开或关闭开发者工具
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+I', () => {
|
||||
win.webContents.toggleDevTools();
|
||||
});
|
||||
|
||||
//重载页面
|
||||
// 重载页面
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+R', () => {
|
||||
//win.reload();
|
||||
sendCommand({
|
||||
@@ -117,98 +117,22 @@ function createWindow(filePath = null, indexUrl = null) {
|
||||
}, win);
|
||||
});
|
||||
|
||||
//重载页面
|
||||
// 重载页面
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+R', () => {
|
||||
win.reload();
|
||||
});
|
||||
|
||||
//最小化窗口
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+M', () => {
|
||||
win.minimize();
|
||||
});
|
||||
|
||||
//关闭窗口
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+W', () => {
|
||||
win.close();
|
||||
});
|
||||
|
||||
//还原窗口
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+0', () => {
|
||||
win.webContents.setZoomFactor(1);
|
||||
});
|
||||
|
||||
//放大窗口
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+=', () => {
|
||||
let actualZoom = win.webContents.getZoomFactor();
|
||||
if (actualZoom == null) {
|
||||
actualZoom = 1;
|
||||
}
|
||||
if (actualZoom < 1.5) {
|
||||
win.webContents.setZoomFactor(actualZoom + 0.1);
|
||||
}
|
||||
});
|
||||
|
||||
//缩小窗口
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+-', () => {
|
||||
let actualZoom = win.webContents.getZoomFactor();
|
||||
if (actualZoom == null) {
|
||||
actualZoom = 1;
|
||||
}
|
||||
if (actualZoom > 0.5) {
|
||||
win.webContents.setZoomFactor(actualZoom - 0.1);
|
||||
}
|
||||
});
|
||||
|
||||
//重启
|
||||
// 重启
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Q', () => {
|
||||
app.relaunch();
|
||||
app.exit(0);
|
||||
});
|
||||
|
||||
//打开帮助页面
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+H', () => {
|
||||
var sendObj = {};
|
||||
sendObj.type = "help";
|
||||
var sendStr = JSON.stringify(sendObj);
|
||||
win.webContents.send('ping', sendStr);
|
||||
//win.webContents.executeJavaScript('alert("this is a test!");');
|
||||
});
|
||||
|
||||
//创建一个新页面
|
||||
// 创建一个新页面
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+N', () => {
|
||||
createWindow(null);
|
||||
});
|
||||
|
||||
//文件另存为
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+Shift+S', () => {
|
||||
const commandObj = {
|
||||
obj: 'Mixly.Electron.File',
|
||||
func: 'saveAs'
|
||||
}
|
||||
const commandStr = JSON.stringify(commandObj);
|
||||
win.webContents.send('command', commandStr);
|
||||
});
|
||||
|
||||
//保存文件
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+S', () => {
|
||||
const commandObj = {
|
||||
obj: 'Mixly.Electron.File',
|
||||
func: 'save'
|
||||
}
|
||||
const commandStr = JSON.stringify(commandObj);
|
||||
win.webContents.send('command', commandStr);
|
||||
});
|
||||
|
||||
//新建文件
|
||||
electronLocalshortcut.register(win, 'CmdOrCtrl+N', () => {
|
||||
const commandObj = {
|
||||
obj: 'Mixly.Electron.File',
|
||||
func: 'newFile'
|
||||
}
|
||||
const commandStr = JSON.stringify(commandObj);
|
||||
win.webContents.send('command', commandStr);
|
||||
});
|
||||
|
||||
win.once('ready-to-show', () => {
|
||||
win.maximize();
|
||||
win.show();
|
||||
@@ -225,32 +149,6 @@ function createWindow(filePath = null, indexUrl = null) {
|
||||
win.on('closed', function () {
|
||||
win = null;
|
||||
});
|
||||
|
||||
/*if (process.platform === 'win32') {
|
||||
getLibsJson(function (jsonData) {
|
||||
if (!jsonData?.version) return;
|
||||
cloudSoftwareJson = JSON.stringify(jsonData);
|
||||
//var updateSoftware = changeVersion(app.getVersion(), jsonData.version);
|
||||
var updateSoftware = (app.getVersion() != jsonData.version);
|
||||
if (updateSoftware) {
|
||||
var sendObj = {};
|
||||
sendObj.type = "update";
|
||||
sendObj.oldVersion = app.getVersion();
|
||||
sendObj.newVersion = jsonData.version;
|
||||
var sendStr = JSON.stringify(sendObj);
|
||||
setTimeout(function () {
|
||||
win.webContents.send('ping', sendStr);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('ping', (event, arg) => {
|
||||
if (arg == "update") {
|
||||
shell.openPath(nodePath.join(__dirname, '../../一键更新.bat'));
|
||||
}
|
||||
event.reply('ping', 'get');
|
||||
});
|
||||
}*/
|
||||
|
||||
win.on('unresponsive', async () => {
|
||||
const { response } = await dialog.showMessageBox({
|
||||
|
||||
Reference in New Issue
Block a user