#70 New menu

Open Tony Lian TonyLianLong Pseudo commit used to compare (b221b11...4cfdb87)
Missing base report.

Unable to compare commits because the base of the pull request did not upload a coverage report.

Changes found in between b221b11...4cfdb87 (pseudo...base) which prevent comparing this pull request.

Showing 2 of 36 files from the diff.
Newly tracked file
src/vega.jl changed.
Other files ignored by Codecov
appveyor.yml was deleted.
test/runtests.jl has changed.
docs/Project.toml has changed.
Project.toml has changed.
README.md has changed.
.gitignore has changed.
.travis.yml was deleted.

@@ -2,10 +2,15 @@
Loading
2 2
3 3
export electrondisplay
4 4
5 -
using Electron, Base64, Markdown
5 +
using Electron, Base64, Markdown, JSON
6 6
7 7
import IteratorInterfaceExtensions, TableTraits, TableShowUtils
8 8
9 +
using FilePaths
10 +
11 +
asset(url...) = replace(normpath(joinpath(@__DIR__, "..", "assets", url...)), "\\" => "/")
12 +
react_html_url = join(@__PATH__, "..", "assets", "plotgallery", "index.html")
13 +
9 14
Base.@kwdef mutable struct ElectronDisplayConfig
10 15
    showable = electron_showable
11 16
    single_window::Bool = false
@@ -70,15 +75,182 @@
Loading
70 75
71 76
const _window = Ref{Window}()
72 77
78 +
function initialize_window(w)
79 +
    run(w.app, """
80 +
    const { app, Menu, webContents } = require('electron')
81 +
    const isMac = process.platform === 'darwin'
82 +
83 +
    const template = [
84 +
      // { role: 'appMenu' }
85 +
      ...(isMac ? [{
86 +
        label: app.name,
87 +
        submenu: [
88 +
          // { role: 'about' },
89 +
          // { type: 'separator' },
90 +
          // { role: 'services' },
91 +
          // { type: 'separator' },
92 +
          { role: 'hide' },
93 +
          { role: 'hideothers' },
94 +
          { role: 'unhide' },
95 +
          { type: 'separator' },
96 +
          { role: 'quit' }
97 +
        ]
98 +
      }] : []),
99 +
      // { role: 'fileMenu' }
100 +
      {
101 +
        label: 'File',
102 +
        submenu: [
103 +
          isMac ? { role: 'close' } : { role: 'quit' }
104 +
        ]
105 +
      },
106 +
      // { role: 'editMenu' }
107 +
      {
108 +
        label: 'Edit',
109 +
        submenu: [
110 +
          // { role: 'undo' },
111 +
          // { role: 'redo' },
112 +
          // { type: 'separator' },
113 +
          // { role: 'cut' },
114 +
          { role: 'copy' },
115 +
          // { role: 'paste' },
116 +
          {
117 +
            label: 'Delete',
118 +
            click: async () => {
119 +
              // Delete
120 +
              let currentWebContents = webContents.getFocusedWebContents();
121 +
              if (currentWebContents) {
122 +
                currentWebContents.executeJavaScript(`if (window.deleteCurrentPlot) {
123 +
                  window.deleteCurrentPlot();
124 +
                }`);
125 +
              }
126 +
            }
127 +
          },
128 +
          ...(isMac ? [
129 +
            // { role: 'pasteAndMatchStyle' },
130 +
            // { role: 'delete' },
131 +
            // { role: 'selectAll' },
132 +
            { type: 'separator' },
133 +
            {
134 +
              label: 'Speech',
135 +
              submenu: [
136 +
                { role: 'startspeaking' },
137 +
                { role: 'stopspeaking' }
138 +
              ]
139 +
            }
140 +
          ] : [
141 +
            // { role: 'delete' },
142 +
            // { type: 'separator' },
143 +
            // { role: 'selectAll' }
144 +
          ])
145 +
        ]
146 +
      },
147 +
      // { role: 'viewMenu' }
148 +
      {
149 +
        label: 'View',
150 +
        submenu: [
151 +
          // { role: 'reload' },
152 +
          // { role: 'forcereload' },
153 +
          // { role: 'toggledevtools' },
154 +
          // { type: 'separator' },
155 +
          // { role: 'resetzoom' },
156 +
          {
157 +
            label: 'Zoom Reset (For Static Images)',
158 +
            click: async () => {
159 +
              let currentWebContents = webContents.getFocusedWebContents();
160 +
              if (currentWebContents) {
161 +
                currentWebContents.executeJavaScript(`window.zoomReset()`);
162 +
              }
163 +
            }
164 +
          },
165 +
          // { role: 'zoomin' },
166 +
          {
167 +
            label: 'Zoom In (For Static Images)',
168 +
            click: async () => {
169 +
              // Delete
170 +
              let currentWebContents = webContents.getFocusedWebContents();
171 +
              if (currentWebContents) {
172 +
                currentWebContents.executeJavaScript(`window.zoomIn()`);
173 +
              }
174 +
            }
175 +
          },
176 +
          // { role: 'zoomout' },
177 +
          {
178 +
            label: 'Zoom Out (For Static Images)',
179 +
            click: async () => {
180 +
              // Delete
181 +
              let currentWebContents = webContents.getFocusedWebContents();
182 +
              if (currentWebContents) {
183 +
                currentWebContents.executeJavaScript(`window.zoomOut()`);
184 +
              }
185 +
            }
186 +
          },
187 +
          // { type: 'separator' },
188 +
          { role: 'togglefullscreen' }
189 +
        ]
190 +
      },
191 +
      // { role: 'windowMenu' }
192 +
      ...(isMac ? [{
193 +
        label: 'Window',
194 +
        submenu: [
195 +
          { role: 'minimize' },
196 +
          { role: 'zoom' },
197 +
          { type: 'separator' },
198 +
          { role: 'front' },
199 +
          { type: 'separator' },
200 +
          // { role: 'window' },
201 +
          { role: 'close' },
202 +
        ]
203 +
      }] : []),
204 +
      {
205 +
        role: 'help',
206 +
        submenu: [
207 +
          {
208 +
            label: 'Learn More About ElectronDisplay',
209 +
            click: async () => {
210 +
              const { shell } = require('electron')
211 +
              await shell.openExternal('https://github.com/queryverse/ElectronDisplay.jl')
212 +
            }
213 +
          }
214 +
        ]
215 +
      }
216 +
    ]
217 +
    
218 +
    const menu = Menu.buildFromTemplate(template)
219 +
    Menu.setApplicationMenu(menu)
220 +
    """)
221 +
end
222 +
73 223
function _getglobalwindow()
74 224
    if !(isdefined(_window, 1) && _window[].exists)
75 225
        _window[] = Electron.Window(
76 226
            URI("about:blank"),
77 227
            options=Dict("webPreferences" => Dict("webSecurity" => false)))
228 +
        initialize_window(_window[])
78 229
    end
79 230
    return _window[]
80 231
end
81 232
233 +
const _plot_window = Ref{Window}()
234 +
235 +
function _getglobalplotwindow()
236 +
    if !(isdefined(_plot_window, 1) && _plot_window[].exists)
237 +
        _plot_window[] = Electron.Window(
238 +
            URI(react_html_url),
239 +
            options=Dict("webPreferences" => Dict("webSecurity" => false)))
240 +
        initialize_window(_plot_window[])
241 +
    end
242 +
    return _plot_window[]
243 +
end
244 +
245 +
function displayplot(d::ElectronDisplayType, type::String, data; options::Dict=Dict{String,Any}())
246 +
    w = _getglobalplotwindow()
247 +
    run(w, "addPlot({type: '$(type)', data: $(JSON.json(data))})")
248 +
249 +
    showfun = get(options, "show", d.config.focus) ? "show" : "showInactive"
250 +
    run(w.app, "BrowserWindow.fromId($(w.id)).$showfun()")
251 +
    return w
252 +
end
253 +
82 254
function displayhtml(d::ElectronDisplayType, payload; options::Dict=Dict{String,Any}())
83 255
    if d.config.single_window
84 256
        w = _getglobalwindow()
@@ -153,61 +325,26 @@
Loading
153 325
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("image/png")}, x)
154 326
    img = stringmime(MIME("image/png"), x)
155 327
156 -
    payload = string("<img src=\"data:image/png;base64,", img, "\"/>")
328 +
    imgdata = "data:image/png;base64, $(img)"
157 329
158 -
    displayhtml(d, payload)
330 +
    displayplot(d, "image", imgdata)
159 331
end
160 332
161 333
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("image/png")}) = true
162 334
163 335
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("image/svg+xml")}, x)
164 -
    payload = stringmime(MIME("image/svg+xml"), x)
336 +
    img = stringmime(MIME("image/svg+xml"), x)
337 +
    imgdata = "data:image/svg+xml;base64, $(base64encode(img))"
165 338
166 -
    displayhtml(d, payload)
339 +
    displayplot(d, "image", imgdata)
167 340
end
168 341
169 342
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("image/svg+xml")}) = true
170 343
171 -
asset(url...) = replace(normpath(joinpath(@__DIR__, "..", "assets", url...)), "\\" => "/")
172 -
173 344
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.plotly.v1+json")}, x)
174 345
    payload = stringmime(MIME("application/vnd.plotly.v1+json"), x)
175 346
176 -
    html_page = """
177 -
    <html>
178 -
179 -
    <head>
180 -
        <script src="file:///$(asset("plotly", "plotly-latest.min.js"))"></script>
181 -
    </head>
182 -
    <body>
183 -
    </body>
184 -
185 -
    <script type="text/javascript">
186 -
        gd = (function() {
187 -
            var WIDTH_IN_PERCENT_OF_PARENT = 100
188 -
            var HEIGHT_IN_PERCENT_OF_PARENT = 100;
189 -
            var gd = Plotly.d3.select('body')
190 -
                .append('div').attr("id", "plotdiv")
191 -
                .style({
192 -
                    width: WIDTH_IN_PERCENT_OF_PARENT + '%',
193 -
                    'margin-left': (100 - WIDTH_IN_PERCENT_OF_PARENT) / 2 + '%',
194 -
                    height: HEIGHT_IN_PERCENT_OF_PARENT + 'vh',
195 -
                    'margin-top': (100 - HEIGHT_IN_PERCENT_OF_PARENT) / 2 + 'vh'
196 -
                })
197 -
                .node();
198 -
            var spec = $payload
199 -
            Plotly.newPlot(gd, spec.data, spec.layout);
200 -
            window.onresize = function() {
201 -
                Plotly.Plots.resize(gd);
202 -
                };
203 -
            return gd;
204 -
        })();
205 -
    </script>
206 -
207 -
    </html>
208 -
    """
209 -
210 -
    displayhtml(d, html_page, options=Dict("webPreferences" => Dict("webSecurity" => false)))
347 +
    displayplot(d, "plotly", payload)
211 348
end
212 349
213 350
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.plotly.v1+json")}) = true
@@ -269,7 +406,9 @@
Loading
269 406
270 407
function Base.display(d::ElectronDisplayType, x)
271 408
    showable = d.config.showable
272 -
    if showable("application/vnd.vegalite.v3+json", x)
409 +
    if showable("application/vnd.vegalite.v4+json", x)
410 +
        display(d,MIME("application/vnd.vegalite.v4+json"), x)
411 +
    elseif showable("application/vnd.vegalite.v3+json", x)
273 412
        display(d,MIME("application/vnd.vegalite.v3+json"), x)
274 413
    elseif showable("application/vnd.vegalite.v2+json", x)
275 414
        display(d,MIME("application/vnd.vegalite.v2+json"), x)

@@ -1,5 +1,6 @@
Loading
1 1
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vegalite.v2+json")}) = true
2 2
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vegalite.v3+json")}) = true
3 +
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vegalite.v4+json")}) = true
3 4
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v3+json")}) = true
4 5
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v4+json")}) = true
5 6
Base.displayable(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v5+json")}) = true
@@ -20,89 +21,14 @@
Loading
20 21
    payload = stringmime(MIME("application/vnd.vegalite.v$major_version_vegalite+json"), x)
21 22
    ans = _maybe_fallback_to(MIME"image/png"(), d, x, payload)
22 23
    ans === nothing || return ans
23 -
24 -
    html_page = """
25 -
    <html>
26 -
27 -
    <head>
28 -
        <script src="file:///$(asset("vega-$major_version_vega", "vega.min.js"))"></script>
29 -
        <script src="file:///$(asset("vega-lite-$major_version_vegalite", "vega-lite.min.js"))"></script>
30 -
        <script src="file:///$(asset("vega-embed", "vega-embed.min.js"))"></script>
31 -
    </head>
32 -
    <body>
33 -
      <div id="plotdiv"></div>
34 -
    </body>
35 -
36 -
    <style media="screen">
37 -
      .vega-actions a {
38 -
        margin-right: 10px;
39 -
        font-family: sans-serif;
40 -
        font-size: x-small;
41 -
        font-style: italic;
42 -
      }
43 -
    </style>
44 -
45 -
    <script type="text/javascript">
46 -
47 -
      var opt = {
48 -
        mode: "vega-lite",
49 -
        actions: false
50 -
      }
51 -
52 -
      var spec = $payload
53 -
54 -
      vegaEmbed('#plotdiv', spec, opt);
55 -
56 -
    </script>
57 -
58 -
    </html>
59 -
    """
60 -
61 -
    displayhtml(d, html_page, options=Dict("webPreferences" => Dict("webSecurity" => false)))
24 +
    displayplot(d, "vega-lite", JSON.JSONText(payload), options=Dict("webPreferences" => Dict("webSecurity" => false)))
62 25
end
63 26
64 27
function _display_vega(d, major_version, x)
65 28
    payload = stringmime(MIME("application/vnd.vega.v$major_version+json"), x)
66 29
    ans = _maybe_fallback_to(MIME"image/png"(), d, x, payload)
67 30
    ans === nothing || return ans
68 -
69 -
    html_page = """
70 -
    <html>
71 -
72 -
    <head>
73 -
        <script src="file:///$(asset("vega-$major_version", "vega.min.js"))"></script>
74 -
        <script src="file:///$(asset("vega-embed", "vega-embed.min.js"))"></script>
75 -
    </head>
76 -
    <body>
77 -
      <div id="plotdiv"></div>
78 -
    </body>
79 -
80 -
    <style media="screen">
81 -
      .vega-actions a {
82 -
        margin-right: 10px;
83 -
        font-family: sans-serif;
84 -
        font-size: x-small;
85 -
        font-style: italic;
86 -
      }
87 -
    </style>
88 -
89 -
    <script type="text/javascript">
90 -
91 -
      var opt = {
92 -
        mode: "vega",
93 -
        actions: false
94 -
      }
95 -
96 -
      var spec = $payload
97 -
98 -
      vegaEmbed('#plotdiv', spec, opt);
99 -
100 -
    </script>
101 -
102 -
    </html>
103 -
    """
104 -
105 -
    displayhtml(d, html_page, options=Dict("webPreferences" => Dict("webSecurity" => false)))  
31 +
    displayplot(d, "vega", JSON.JSONText(payload), options=Dict("webPreferences" => Dict("webSecurity" => false)))  
106 32
end
107 33
108 34
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vegalite.v2+json")}, x)
@@ -113,6 +39,10 @@
Loading
113 39
    return _display_vegalite(d, "3", "5", x)
114 40
end
115 41
42 +
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vegalite.v4+json")}, x)
43 +
    return _display_vegalite(d, "4", "5", x)
44 +
end
45 +
116 46
function Base.display(d::ElectronDisplayType, ::MIME{Symbol("application/vnd.vega.v3+json")}, x)
117 47
    return _display_vega(d, "3", x)
118 48
end

Unable to process changes.

No base report to compare against.

58 Commits

Hiding 43 contexual commits
+13
+12
+1
Hiding 13 contexual commits
Pull Request Base Commit
Files Coverage
src 83.20%
Project Totals (2 files) 83.20%
Loading