zoukankan      html  css  js  c++  java
  • Electron简易编辑器实现:打开保存文件,自定义菜单,代码高亮提示等功能

    ipcmain.js

    var {Menu,shell,ipcMain,BrowserWindow,app} =require('electron');
    
    var template = [
        {
            label: '文件',
            submenu: [
                {
                    label: '新建',       
                    accelerator:"Ctrl+N",         
                    click: function(){
                        //主进程通知渲染进程操作文件
                        BrowserWindow.getFocusedWindow().webContents.send('action','new');
                        
                    }
    
                },
                {
                    label: '打开',
                    accelerator:"Ctrl+O", 
                    click: function(){
    
                         //主进程通知渲染进程操作文件
                         BrowserWindow.getFocusedWindow().webContents.send('action','open');
                        
    
                    }
                },
                
                {   
                    accelerator:"Ctrl+S", 
                    label: '保存',
                    click: function(){
                        BrowserWindow.getFocusedWindow().webContents.send('action','save');
    
                    }
                },
                {
                    type: 'separator'
                },          
             
                {
                    label: '打印',
                    accelerator:"Ctrl+P",
                    click: function(){
                        //打印功能通过 webContents  https://electronjs.org/docs/api/web-contents
    
                        BrowserWindow.getFocusedWindow().webContents.print();
    
                            
                    }
                },
                {
                    label: '退出',
                    accelerator:"Ctrl+Q",
                    click: function(){
                        
                        //要提示用户保存  未保存的文件
    
                        //主进程通知渲染进程执行退出操作
                        BrowserWindow.getFocusedWindow().webContents.send('action','exit');
    
                    }
                }
            ]
        },
        {
            label: '编辑',
            submenu: [
                
                {
                    label: '撤销',
                    role: 'undo'
                },
                {
                    label: '恢复',
                    role: 'redo'
                },
                {
                    type: 'separator'
                },
                {   label: '截切',
                    role: 'cut'
                },
                {
                    label: '复制',
                    role: 'copy'
                },
                {
                    label: '黏贴',
                    role: 'paste'
                },
              
                {
                    label: '删除',
                    role: 'delete'
                },
                {
                    label: '全选',
                    role: 'selectall'
                }
            ]
        },    
        {
            label: '视图',
            submenu: [
                {
                    label: '加载',
                    role: 'reload'
                },
               
                {
                    label: '缩小',
                    role: 'zoomin'
                },
                {   label: '放大',
                    role: 'zoomout'
                },
                {   label: '重置缩放',
                    role: 'resetzoom'
                },
                {
                    type: 'separator'
                },
                {
                    label: '全屏',
                    role: 'togglefullscreen'
                }
            ]
        },
        {
            label: '帮助',
            submenu: [
                {
                    label: '关于',
                    click() { 
                        
                        shell.openExternal('https://www.itying.com');
                    
                    }
                }
            ]
        }
    ];
    var m=Menu.buildFromTemplate(template);
    
    
    Menu.setApplicationMenu(m);
    
    
    
    //右键菜单
    
    
    const contextMenuTemplate=[
        {
            label: '撤销',
            role: 'undo'
        },
        {
            label: '恢复',
            role: 'redo'
        },
        {
            type: 'separator'
        },
        {   label: '截切',
            role: 'cut'
        },
        {
            label: '复制',
            role: 'copy'
        },
        {
            label: '黏贴',
            role: 'paste'
        },
        { type: 'separator' },  //分隔线
        { label: '全选',
            role: 'selectall' 
        }   //Select All菜单项
    ];
    
    var contextMenu=Menu.buildFromTemplate(contextMenuTemplate);
    
    
    // 监听右键事件
    ipcMain.on('contextMenu',function(){
    
        contextMenu.popup(BrowserWindow.getFocusedWindow())
    })
    
    
    
    //监听客户端的退出操作
    ipcMain.on('exit-app',()=>{
    
        app.quit();
    })

    ipcrender.js

    var {ipcRenderer,remote}=require('electron');
    var fs=require('fs');
    
    document.title='无标题'
    
    //获取文本框dom
    
    var textAreaDom=document.querySelector("#textArea");
    
    /*
    
    问题:
        1、新建 打开 保存的问题
    
        2、如果已经保存 第二次保存的时候不提示直接保存
    
        3、判断文件是否已经保存  改变软件左上角的内容
    
    */
    
    var isSave=true;   //判断文件是否保存
    
    var currentFile='';   //保存当前文件的路径
    
    
    //内容变化的时候 让isSave等于false
    textAreaDom.oninput=function(){
    
        if(isSave){document.title+=" *"} 
        
        isSave=false;
    }
    
    
    
    document.addEventListener('contextmenu',function(e){
    
        e.preventDefault();
    
    
        ipcRenderer.send('contextMenu');
    })
    
    
    //监听主进程的操作
    
    ipcRenderer.on('action',function(event,action){
    
        console.log(action);
    
        switch(action){
    
            case "new":
    
    
                //判断文件是否保存  如果没有保存提示   并保存
    
                askSaveDialog();
    
    
                textAreaDom.value='';
    
    
            break;
    
            case "open":
                //判断文件是否保存  如果没有保存提示   并保存
    
                askSaveDialog();
    
                //通过dialog打开文件
                var dir= remote.dialog.showOpenDialog({
    
                    properties:['openFile']
    
                });
    
                if(dir){
                    var fsData=fs.readFileSync(dir[0]);
                        //获取文件里面的东西
                    // textAreaDom.value=fsData;
    
    
                    editor.setValue(fsData.toString());   //注意传入的数据
    
                }
              break;
    
            case "save":
    
                saveCurrentDoc();
                
                break;
    
            case "exit":
    
                askSaveDialog();  //同步方法
                
                //通知主进程退出应用
    
                ipcRenderer.send('exit-app')
    
    
    
                break;
    
    
        }
    
    })
    
    
    //判断文件师傅保存并执行保存功能
    
    function askSaveDialog(){
    
        if(!isSave){
                
            var index=remote.dialog.showMessageBox({
    
                type:"question",
                message:'是否要保存此文件?',
                buttons:['Yes','No']
            })
    
            if(index==0){
    
                //执行保存操作
                saveCurrentDoc();
            }
    
        }
    
    }
    
    //执行保存的方法
    function saveCurrentDoc(){
        if(!currentFile){  //当前文件路径不存在 提示保存
    
            var dir=remote.dialog.showSaveDialog({
    
                defaultPath:'aaa.txt',
                filters: [
                
                    {name: 'All Files', extensions: ['*']}
                ]
    
            });
    
            if(dir){
    
                currentFile=dir;
                
                fs.writeFileSync(currentFile,editor.getValue());
                isSave=true;
                //改变软件的标题
                document.title=currentFile;
            }
    
        }else{
    
    
            // editor.getValue() 获取编辑器的值
    
            // fs.writeFileSync(currentFile,textAreaDom.value);
    
            fs.writeFileSync(currentFile,editor.getValue());
            isSave=true;
    
             //改变软件的标题
             document.title=currentFile;
    
        }
    
    }

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title></title>
    
        <link rel="stylesheet" href="./static/css/index.css">
      </head>
      <body>
      
    
        <textarea id="textArea"></textarea>
        
    
      </body>
    
    
    
      <link rel=stylesheet href="static/codemirror/doc/docs.css">
      <link rel="stylesheet" href="static/codemirror/lib/codemirror.css">
      <script src="static/codemirror/lib/codemirror.js"></script>
      <script src="static/codemirror/addon/selection/selection-pointer.js"></script>
      <script src="static/codemirror/mode/xml/xml.js"></script>
      <script src="static/codemirror/mode/javascript/javascript.js"></script>
      <script src="static/codemirror/mode/css/css.js"></script>
      <script src="static/codemirror/mode/vbscript/vbscript.js"></script>
      <script src="static/codemirror/mode/htmlmixed/htmlmixed.js"></script>
    
    
    
      <script>
          // Define an extended mixed-mode that understands vbscript and
          // leaves mustache/handlebars embedded templates in html mode
          var mixedMode = {
            name: "htmlmixed",
            scriptTypes: [{matches: //x-handlebars-template|/x-mustache/i,
                           mode: null},
                          {matches: /(text|application)/(x-)?vb(a|script)/i,
                           mode: "vbscript"}]
          };
          var editor = CodeMirror.fromTextArea(document.getElementById("textArea"), {
            mode: mixedMode,
            selectionPointer: true
          });
        </script>
      <style>
      
        .CodeMirror{
    
          height: 100%;
        }
      
      </style>
    
    
      <script src="./renderer/ipcRenderer.js"></script>
    </html>

    index.js

    import { app, BrowserWindow } from 'electron';
    
    
    // Handle creating/removing shortcuts on Windows when installing/uninstalling.
    if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
      app.quit();
    }
    
    // Keep a global reference of the window object, if you don't, the window will
    // be closed automatically when the JavaScript object is garbage collected.
    let mainWindow;
    
    const createWindow = () => {
      // Create the browser window.
      mainWindow = new BrowserWindow({
         800,
        height: 600,
        webPreferences: {
          nodeIntegration: true
        }
      });
    
      // and load the index.html of the app.
      mainWindow.loadURL(`file://${__dirname}/index.html`);
    
      // Open the DevTools.
      mainWindow.webContents.openDevTools();
    
      // Emitted when the window is closed.
      mainWindow.on('closed', () => {
        // Dereference the window object, usually you would store windows
        // in an array if your app supports multi windows, this is the time
        // when you should delete the corresponding element.
        mainWindow = null;
      });
    
    
      //引入icpMain
    
      require('./main/ipcMain.js');
    };
    
    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.on('ready', createWindow);
    
    // Quit when all windows are closed.
    app.on('window-all-closed', () => {
      // On OS X it is common for applications and their menu bar
      // to stay active until the user quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') {
        app.quit();
      }
    });
    
    app.on('activate', () => {
      // On OS X it's common to re-create a window in the app when the
      // dock icon is clicked and there are no other windows open.
      if (mainWindow === null) {
        createWindow();
      }
    });
    
    // In this file you can include the rest of your app's specific main process
    // code. You can also put them in separate files and import them here.

    备注:

    CodeMirror在线编辑器插件:
        github地址:https://github.com/codemirror/CodeMirror
        官网:http://codemirror.net/
        CodeMirror api:  http://codemirror.net/doc/manual.html#api
    使用CodeMirror:
        1.下载:
        2、看文档使用
            http://codemirror.net/mode/index.html
    注意:
        https://github.com/codemirror/CodeMirror   
        CodeMirror最新版本使用的是es6的语法,但是由于nodejs不支持 es6的import 所以我们的项目里面没法用最新的版本
        教程使用的是codemirror-5.2
            下载codemirror-5.2,然后看官方文档使用
        插件要设置和获取值:
            doc.setValue设置值
            doc.getValue  或获取值
           var editor = CodeMirror.fromTextArea(document.getElementById("textArea"), {
              mode: mixedMode,
              selectionPointer: true
           });
           editor.setValue()
           editor.getValue()
           
    codemirror-5.2修改codemirror.js的地方:
        17行左右:    this.CodeMirror = mod();   改为 window.CodeMirror = mod();
        8400行左右     return string.split(/
    ?|
    /);  改为      return string.toString().split(/
    ?|
    /);   或者可以不修改,但是传入数据必须是string
        fsData.toString()

    运行项目:

    npm start
  • 相关阅读:
    ubuntu删除django和安装django
    linux shell 统计文件单词出现次数
    linux shell $$、$!特殊符号
    linux安装zabbix需要php两个模块php-bcmach与php-mbstring
    linux 源码编译与卸载
    Job for dhcpd.service failed because the control process exited with error code. See "systemctl status dhcpd.service" and "journalctl -xe" for details.问题
    Linux中部署DNS分离解析技术
    NFS网络文件系统服务搭建
    Samba服务搭建
    Linux RAID磁盘阵列技术
  • 原文地址:https://www.cnblogs.com/loaderman/p/12152072.html
Copyright © 2011-2022 走看看