Initial support for OpenDialog

This commit is contained in:
Lea Anthony 2020-09-27 14:32:08 +10:00
commit d4224772b4
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
9 changed files with 96 additions and 60 deletions

View file

@ -29,6 +29,6 @@ extern void Fullscreen(void *app);
extern void UnFullscreen(void *app);
extern void ToggleFullscreen(void *app);
extern void DisableFrame(void *app);
extern char *OpenDialog(void *appPointer, char *title, char *filter);
extern void OpenDialog(void *appPointer, char *callbackID, char *title, char *filter);
#endif

View file

@ -12,11 +12,7 @@ package ffenestri
import "C"
import (
"encoding/json"
"fmt"
"log"
"strconv"
"unsafe"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options"
@ -124,27 +120,6 @@ func (c *Client) WindowSetColour(colour int) {
}
// OpenDialog will open a dialog with the given title and filter
func (c *Client) OpenDialog(dialogOptions *options.OpenDialog) []string {
var result []string
cstring := C.OpenDialog(c.app.app, c.app.string2CString(dialogOptions.Title), c.app.string2CString(dialogOptions.Filter))
if cstring == nil {
return result
}
jsondata := C.GoString(cstring)
// Free the C string that was allocated by the dialog
C.free(unsafe.Pointer(cstring))
// Unmarshal the json
err := json.Unmarshal([]byte(jsondata), &result)
if err != nil {
// ???
log.Fatal(err)
}
fmt.Printf("result = %+v\n", result)
return result
func (c *Client) OpenDialog(dialogOptions *options.OpenDialog, callbackID string) {
C.OpenDialog(c.app.app, c.app.string2CString(callbackID), c.app.string2CString(dialogOptions.Title), c.app.string2CString(dialogOptions.Filter))
}

View file

@ -416,14 +416,46 @@ char* OpenFileDialog(struct Application *app, char *title, char *filter) {
// OpenDialog opens a dialog to select files/directories
// NOTE: The result is a string that will need to be freed!
char* OpenDialog(void *appPointer, char *title, char *filter) {
Debug("OpenDirectoryDialog Called");
JsonNode *result = json_mkarray();
json_append_element(result, json_mkstring("BogusDirectory 1"));
json_append_element(result, json_mkstring("BogusDirectory 2"));
char *encoded = json_stringify(result, "");
json_delete(result);
return encoded;
void OpenDialog(struct Application *app, char* callbackID, char *title, char *filter) {
Debug("OpenDialog Called with callback id: %s", callbackID);
// Create an open panel
ON_MAIN_THREAD(
id dialog = msg(c("NSOpenPanel"), s("openPanel"));
msg(dialog, s("setTitle:"), str(title));
// TODO: Filters
// No filters: [dialog setAllowsOtherFileTypes:YES];
// TODO: Other options
msg(dialog, s("beginSheetModalForWindow:completionHandler:"), app->mainWindow, ^(id result) {
JsonNode *response = json_mkarray();
// If success
if( result == (id)1 ) {
id urls = msg(dialog, s("URLs"));
int noOfResults = (int)msg(urls, s("count"));
for( int index = 0; index < noOfResults; index++ ) {
id url = msg(urls, s("objectAtIndex:"), index);
const char *filename = (const char *)msg(msg(url, s("path")), s("UTF8String"));
json_append_element(response, json_mkstring(filename));
}
}
char *encoded = json_stringify(response, "");
json_delete(response);
const char *callback = concat("D", callbackID);
const char *header = concat(callback, "|");
const char *responseMessage = concat(header, encoded);
free((void*)callback);
free((void*)header);
app->sendMessageToBackend(responseMessage);
free(responseMessage);
});
msg( c("NSApp"), s("runModalForWindow:"), app->mainWindow);
)
}
const char *invoke = "window.external={invoke:function(x){window.webkit.messageHandlers.external.postMessage(x);}};";

View file

@ -14,7 +14,7 @@ type Client interface {
Quit()
NotifyEvent(message string)
CallResult(message string)
OpenDialog(*options.OpenDialog) []string
OpenDialog(dialogOptions *options.OpenDialog, callbackID string)
WindowSetTitle(title string)
WindowShow()
WindowHide()

View file

@ -0,0 +1,45 @@
package message
import (
"encoding/json"
"fmt"
"strings"
)
// dialogMessageParser does what it says on the tin!
func dialogMessageParser(message string) (*parsedMessage, error) {
// Sanity check: Dialog messages must be at least 4 bytes
if len(message) < 4 {
return nil, fmt.Errorf("dialog message was an invalid length")
}
var topic = "bad topic from dialogMessageParser"
var data []string
// Switch the event type (with or without data)
switch message[0] {
// Format of Dialog response messages: D<callbackID>|<[]string as json encoded string>
case 'D':
idx := strings.IndexByte(message[1:], '|')
if idx < 0 {
return nil, fmt.Errorf("Invalid dialog response message format")
}
callbackID := message[1 : idx+1]
jsonData := message[idx+2:]
topic = "dialog:openselected:" + callbackID
err := json.Unmarshal([]byte(jsonData), &data)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("Invalid message to dialogMessageParser()")
}
// Create a new parsed message struct
parsedMessage := &parsedMessage{Topic: topic, Data: data}
return parsedMessage, nil
}

View file

@ -1,8 +1,9 @@
package message
import "fmt"
import "encoding/json"
import (
"encoding/json"
"fmt"
)
type EventMessage struct {
Name string `json:"name"`

View file

@ -17,6 +17,7 @@ var messageParsers = map[byte]func(string) (*parsedMessage, error){
'e': eventMessageParser,
'C': callMessageParser,
'W': windowMessageParser,
'D': dialogMessageParser,
}
// Parse will attempt to parse the given message

View file

@ -335,20 +335,14 @@ func (d *Dispatcher) processDialogMessage(result *servicebus.Message) {
return
}
// This is hardcoded in the sender too
responseTopic := "dialog:openselected:" + splitTopic[3]
d.logger.Info("Opening File dialog! responseTopic = %s", responseTopic)
callbackID := splitTopic[3]
// TODO: Work out what we mean in a multi window environment...
// For now we will just pick the first one
var result []string
for _, client := range d.clients {
result = client.frontend.OpenDialog(dialogOptions)
client.frontend.OpenDialog(dialogOptions, callbackID)
}
// Send dummy response
d.servicebus.Publish(responseTopic, result)
default:
d.logger.Error("Unknown dialog command: %s", command)
}

View file

@ -1,8 +1,6 @@
package goruntime
import (
b64 "encoding/base64"
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/internal/crypto"
@ -68,13 +66,3 @@ func (r *dialog) Open(dialogOptions *options.OpenDialog) []string {
return result.Data().([]string)
}
func optionsToBase64(dialogOptions *options.OpenDialog) (string, error) {
encoded, err := json.Marshal(dialogOptions)
if err != nil {
return "", err
}
return b64.StdEncoding.EncodeToString(encoded), nil
}