Monaco Editor hosted by PureBasic

Share your advanced PureBasic knowledge/code with the community.
User avatar
Kiffi
Addict
Addict
Posts: 1502
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Monaco Editor hosted by PureBasic

Post by Kiffi »

Here is an example of how to host the powerful Monaco Editor in PureBasic:

Code: Select all

EnableExplicit

Enumeration
  #Window
  #btnLoad
  #btnSave
  #WebViewGadget
EndEnumeration

Procedure.s GetMonacoEditor()
  
  ProcedureReturn ~"<!doctype html><html lang='en'>\n" +
                  ~"<head>\n" +
                  ~"  <meta charset='utf-8'>\n" +
                  ~"  <meta http-equiv='X-UA-Compatible' content='IE=edge'>\n" +
                  ~"</head>\n" +
                  ~"<body style='margin:0px'>\n" +
                  ~"  <div id='container' style='height: 100vh;overflow: hidden;'></div>\n" +
                  ~"  <script type='text/javascript' src='https://code.jquery.com/jquery-3.7.1.min.js'></script>\n" +
                  ~"  <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js'></script>\n" +
                  ~"  <script type='text/javascript' src='https://unpkg.com/monaco-editor@latest/min/vs/loader.js'></script>\n" +
                  ~"<script>\n" +
                  ~"  require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@latest/min/vs' }});\n" +
                  ~"\n" +
                  ~"  window.MonacoEnvironment = {\n" +
                  ~"    getWorkerUrl: function(workerId, label) {\n" +
                  ~"      return `data:text/javascript;charset=utf-8,${encodeURIComponent(`\n" +
                  ~"        self.MonacoEnvironment = {\n" +
                  ~"          baseUrl: 'https://unpkg.com/monaco-editor@latest/min/'\n" +
                  ~"        };\n" +
                  ~"        importScripts('https://unpkg.com/monaco-editor@latest/min/vs/base/worker/workerMain.js');`\n" +
                  ~"      )}`;\n" +
                  ~"    }\n" +
                  ~"  };\n" +
                  ~"" +
                  ~"require(['vs/editor/editor.main'], function () {\n" +
                  ~"" +
                  ~"  monaco.editor.onDidCreateEditor(function(event) {\n" +
                  ~"    window.EditorCreated();\n" +
                  ~"  });\n" +
                  ~"" +
                  ~"  var myEditorOptions = {\n" +
                  ~"    language: 'typescript',\n" +
                  ~"    automaticLayout: true,\n" +
                  ~"    scrollBeyondLastLine: false,\n" +
                  ~"    folding: true,\n" +
                  ~"  };\n" +
                  ~"" +
                  ~"  editor = monaco.editor.create(document.getElementById('container'), myEditorOptions);\n" +
                  ~"  $('#wait').hide();\n" + 
                  ~"  $('#container').show();\n" + 
                  ~"  editor.focus();\n" +
                  ~"" +
                  ~"  window.monaco = monaco\n" +
                  ~"  window.monacoeditor = editor;\n" +
                  ~"" +
                  ~"  window.loadText = function(textToLoad) { \n" +
                  ~"    monacoeditor.getModel().setValue(atob(textToLoad)); \n" + 
                  ~"    $.unblockUI(); \n" + 
                  ~"  }\n" +
                  ~"});\n" +
                  ~"" +
                  ~"</script></body></html>"
  
EndProcedure

Procedure btnLoadEvent()
  
  Protected FileToLoad.s
  Protected Pattern.s
  Protected PatternPosition
  Protected StringToLoad.s
  Protected FileHandle
  
  Pattern = "Text (*.txt;*.txt)|*.txt;*.bat|JavaScript (*.js)|*.js|All files (*.*)|*.*"
  PatternPosition = 1
  
  FileToLoad = OpenFileRequester("Please choose file to load", "", Pattern, PatternPosition)
  
  If FileToLoad
    FileHandle = ReadFile(#PB_Any, FileToLoad)
    If FileHandle
      WebViewExecuteScript(#WebViewGadget, "$.blockUI();")
      StringToLoad = ReadString(FileHandle, #PB_File_IgnoreEOL)
      CloseFile(FileHandle)
      StringToLoad = Base64Encoder(UTF8(StringToLoad), StringByteLength(StringToLoad, #PB_UTF8))
      WebViewExecuteScript(#WebViewGadget, "loadText('" + StringToLoad + "');")
    EndIf
  EndIf
  
EndProcedure

Procedure btnSaveEvent()
  
  WebViewExecuteScript(#WebViewGadget, "window.MonacoEditorValue(monacoeditor.getModel().getValue());")
  
EndProcedure

Procedure EditorCreated(JsonParameters$)
  DisableGadget(#btnLoad, #False)
  DisableGadget(#btnSave, #False)
EndProcedure

Procedure MonacoEditorValue(JsonParameters$)
  
  Protected FileToSave.s
  Protected Pattern.s
  Protected PatternPosition
  Protected StringToSave.s
  Protected FileHandle
  
  Dim Parameters.s(0)
  ParseJSON(0, JsonParameters$)
  ExtractJSONArray(JSONValue(0), Parameters())
  StringToSave = Parameters(0)
  
  Pattern = "Text (*.txt;*.txt)|*.txt;*.bat|JavaScript (*.js)|*.js|All files (*.*)|*.*"
  PatternPosition = 1
  
  FileToSave = SaveFileRequester("Please choose file to save", "", Pattern, PatternPosition)
  If FileToSave
    FileHandle = CreateFile(#PB_Any, FileToSave)
    If FileHandle
      WriteString(FileHandle, StringToSave)
      CloseFile(FileHandle)
    EndIf
  EndIf
  
EndProcedure

Procedure SizeWindowEvent()
  
  ResizeGadget(#WebViewGadget, #PB_Ignore, 40, WindowWidth(#Window), WindowHeight(#Window) - 40)
  
EndProcedure

OpenWindow(#Window, 0, 0, 1200, 800, "Monaco Editor hosted by PureBasic", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget) 
BindEvent(#PB_Event_SizeWindow, @SizeWindowEvent(), #Window)

ButtonGadget(#btnLoad, 5, 5, 100, 30, "Load")
DisableGadget(#btnLoad, #True)
BindGadgetEvent(#btnLoad, @btnLoadEvent())

ButtonGadget(#btnSave, 110, 5, 100, 30, "Save")
DisableGadget(#btnSave, #True)
BindGadgetEvent(#btnSave, @btnSaveEvent())

WebViewGadget(#WebViewGadget, 0, 40, 1200, WindowHeight(#Window) - 40, #PB_WebView_Debug)

BindWebViewCallback(#WebViewGadget, "EditorCreated", @EditorCreated())
BindWebViewCallback(#WebViewGadget, "MonacoEditorValue", @MonacoEditorValue())

SetGadgetItemText(#WebViewGadget, #PB_Web_HtmlCode, GetMonacoEditor())

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
The Monaco Editor supports many languages. Here, for example, TypeScript:

Image
Hygge
highend
Enthusiast
Enthusiast
Posts: 169
Joined: Tue Jun 17, 2014 4:49 pm

Re: Monaco Editor hosted by PureBasic

Post by highend »

Nice, thanks for sharing! :mrgreen:
Quin
Addict
Addict
Posts: 1133
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Monaco Editor hosted by PureBasic

Post by Quin »

Very cool, thanks 8)
User avatar
CDXbow
Enthusiast
Enthusiast
Posts: 100
Joined: Mon Aug 12, 2019 5:32 am
Location: Oz

Re: Monaco Editor hosted by PureBasic

Post by CDXbow »

Kiffi you are brilliant. Great work.
There seems to be a couple of levels of synchronicity going on. I was looking through an old hard drive yesterday and found some Monaco Editor code and over the last week I have been battling with the Webvbiewgadget - and mostly failing.
Post Reply