mirror of
https://github.com/taigrr/wails.git
synced 2026-04-17 04:05:12 -07:00
Compare commits
23 Commits
v2.0.0-alp
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
913fe8d184 | ||
|
|
4ce8130cdf | ||
|
|
fe87463b78 | ||
|
|
fe0f0e29e8 | ||
|
|
83d6dac7cf | ||
|
|
02500e0930 | ||
|
|
5e1187f437 | ||
|
|
064ff3b65e | ||
|
|
b5c7019bf0 | ||
|
|
e9d16e77a3 | ||
|
|
2415d4c531 | ||
|
|
3f75213ce3 | ||
|
|
6120ceabf1 | ||
|
|
95a95d1750 | ||
|
|
d923e84456 | ||
|
|
343f573e78 | ||
|
|
c6d87da4f0 | ||
|
|
a9faebe51a | ||
|
|
d436f5d1be | ||
|
|
f40899821f | ||
|
|
2a64ed19a3 | ||
|
|
47bca0be88 | ||
|
|
7ac8cc6b8b |
@@ -26,7 +26,7 @@ export function OpenURL(url) {
|
|||||||
* Opens the given filename using the system's default file handler
|
* Opens the given filename using the system's default file handler
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @param {sting} filename
|
* @param {string} filename
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function OpenFile(filename) {
|
export function OpenFile(filename) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ if (window.crypto) {
|
|||||||
export function Call(bindingName, data, timeout) {
|
export function Call(bindingName, data, timeout) {
|
||||||
|
|
||||||
// Timeout infinite by default
|
// Timeout infinite by default
|
||||||
if (timeout == null || timeout == undefined) {
|
if (timeout == null) {
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ function Invoke(message) {
|
|||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {string} payload
|
* @param {Object} payload
|
||||||
* @param {string=} callbackID
|
* @param {string=} callbackID
|
||||||
*/
|
*/
|
||||||
export function SendMessage(type, payload, callbackID) {
|
export function SendMessage(type, payload, callbackID) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
var version = "v2.0.0-alpha.10"
|
var version = "v2.0.0-alpha.16"
|
||||||
|
|||||||
@@ -2,11 +2,39 @@
|
|||||||
|
|
||||||
package app
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Init initialises the application for a debug environment
|
// Init initialises the application for a debug environment
|
||||||
func (a *App) Init() error {
|
func (a *App) Init() error {
|
||||||
// Indicate debug mode
|
// Indicate debug mode
|
||||||
a.debug = true
|
a.debug = true
|
||||||
// Enable dev tools
|
|
||||||
a.options.DevTools = true
|
if a.appType == "desktop" {
|
||||||
|
// Enable dev tools
|
||||||
|
a.options.DevTools = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set log levels
|
||||||
|
greeting := flag.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error")
|
||||||
|
flag.Parse()
|
||||||
|
if len(*greeting) > 0 {
|
||||||
|
switch strings.ToLower(*greeting) {
|
||||||
|
case "trace":
|
||||||
|
a.logger.SetLogLevel(logger.TRACE)
|
||||||
|
case "info":
|
||||||
|
a.logger.SetLogLevel(logger.INFO)
|
||||||
|
case "warning":
|
||||||
|
a.logger.SetLogLevel(logger.WARNING)
|
||||||
|
case "error":
|
||||||
|
a.logger.SetLogLevel(logger.ERROR)
|
||||||
|
default:
|
||||||
|
a.logger.SetLogLevel(logger.DEBUG)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ package app
|
|||||||
// will be unknown and the application will not work as expected.
|
// will be unknown and the application will not work as expected.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,7 +39,3 @@ func (a *App) Run() error {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind the dummy interface
|
|
||||||
func (a *App) Bind(_ interface{}) {
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import (
|
|||||||
|
|
||||||
// App defines a Wails application structure
|
// App defines a Wails application structure
|
||||||
type App struct {
|
type App struct {
|
||||||
|
appType string
|
||||||
|
|
||||||
window *ffenestri.Application
|
window *ffenestri.Application
|
||||||
servicebus *servicebus.ServiceBus
|
servicebus *servicebus.ServiceBus
|
||||||
logger *logger.Logger
|
logger *logger.Logger
|
||||||
@@ -80,10 +82,11 @@ func CreateApp(appoptions *options.App) (*App, error) {
|
|||||||
window := ffenestri.NewApplicationWithConfig(appoptions, myLogger, menuManager)
|
window := ffenestri.NewApplicationWithConfig(appoptions, myLogger, menuManager)
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
|
appType: "desktop",
|
||||||
window: window,
|
window: window,
|
||||||
servicebus: servicebus.New(myLogger),
|
servicebus: servicebus.New(myLogger),
|
||||||
logger: myLogger,
|
logger: myLogger,
|
||||||
bindings: binding.NewBindings(myLogger),
|
bindings: binding.NewBindings(myLogger, appoptions.Bind),
|
||||||
menuManager: menuManager,
|
menuManager: menuManager,
|
||||||
startupCallback: appoptions.Startup,
|
startupCallback: appoptions.Startup,
|
||||||
shutdownCallback: appoptions.Shutdown,
|
shutdownCallback: appoptions.Shutdown,
|
||||||
@@ -213,14 +216,3 @@ func (a *App) Run() error {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a struct to the application by passing in
|
|
||||||
// a pointer to it
|
|
||||||
func (a *App) Bind(structPtr interface{}) {
|
|
||||||
|
|
||||||
// Add the struct to the bindings
|
|
||||||
err := a.bindings.Add(structPtr)
|
|
||||||
if err != nil {
|
|
||||||
a.logger.Fatal("Error during binding: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func CreateApp(options *Options) *App {
|
|||||||
webserver: webserver.NewWebServer(myLogger),
|
webserver: webserver.NewWebServer(myLogger),
|
||||||
servicebus: servicebus.New(myLogger),
|
servicebus: servicebus.New(myLogger),
|
||||||
logger: myLogger,
|
logger: myLogger,
|
||||||
bindings: binding.NewBindings(myLogger),
|
bindings: binding.NewBindings(myLogger, options.Bind),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the app
|
// Initialise the app
|
||||||
@@ -192,14 +192,3 @@ func (a *App) Run() error {
|
|||||||
|
|
||||||
return cli.Run()
|
return cli.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a struct to the application by passing in
|
|
||||||
// a pointer to it
|
|
||||||
func (a *App) Bind(structPtr interface{}) {
|
|
||||||
|
|
||||||
// Add the struct to the bindings
|
|
||||||
err := a.bindings.Add(structPtr)
|
|
||||||
if err != nil {
|
|
||||||
a.logger.Fatal("Error during binding: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
|
|
||||||
"github.com/leaanthony/clir"
|
"github.com/leaanthony/clir"
|
||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/logger"
|
"github.com/wailsapp/wails/v2/internal/logger"
|
||||||
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
"github.com/wailsapp/wails/v2/internal/messagedispatcher"
|
||||||
|
"github.com/wailsapp/wails/v2/internal/runtime"
|
||||||
"github.com/wailsapp/wails/v2/internal/servicebus"
|
"github.com/wailsapp/wails/v2/internal/servicebus"
|
||||||
"github.com/wailsapp/wails/v2/internal/subsystem"
|
"github.com/wailsapp/wails/v2/internal/subsystem"
|
||||||
"github.com/wailsapp/wails/v2/internal/webserver"
|
"github.com/wailsapp/wails/v2/internal/webserver"
|
||||||
@@ -17,12 +20,16 @@ import (
|
|||||||
|
|
||||||
// App defines a Wails application structure
|
// App defines a Wails application structure
|
||||||
type App struct {
|
type App struct {
|
||||||
|
appType string
|
||||||
|
|
||||||
binding *subsystem.Binding
|
binding *subsystem.Binding
|
||||||
call *subsystem.Call
|
call *subsystem.Call
|
||||||
event *subsystem.Event
|
event *subsystem.Event
|
||||||
log *subsystem.Log
|
log *subsystem.Log
|
||||||
runtime *subsystem.Runtime
|
runtime *subsystem.Runtime
|
||||||
|
|
||||||
|
options *options.App
|
||||||
|
|
||||||
bindings *binding.Bindings
|
bindings *binding.Bindings
|
||||||
logger *logger.Logger
|
logger *logger.Logger
|
||||||
dispatcher *messagedispatcher.Dispatcher
|
dispatcher *messagedispatcher.Dispatcher
|
||||||
@@ -30,28 +37,40 @@ type App struct {
|
|||||||
webserver *webserver.WebServer
|
webserver *webserver.WebServer
|
||||||
|
|
||||||
debug bool
|
debug bool
|
||||||
|
|
||||||
|
// Application Stores
|
||||||
|
loglevelStore *runtime.Store
|
||||||
|
appconfigStore *runtime.Store
|
||||||
|
|
||||||
|
// Startup/Shutdown
|
||||||
|
startupCallback func(*runtime.Runtime)
|
||||||
|
shutdownCallback func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create App
|
// Create App
|
||||||
func CreateApp(options *Options) *App {
|
func CreateApp(appoptions *options.App) (*App, error) {
|
||||||
options.mergeDefaults()
|
|
||||||
// We ignore the inputs (for now)
|
|
||||||
|
|
||||||
// TODO: Allow logger output override on CLI
|
// Merge default options
|
||||||
myLogger := logger.New(os.Stdout)
|
options.MergeDefaults(appoptions)
|
||||||
myLogger.SetLogLevel(logger.TRACE)
|
|
||||||
|
// Set up logger
|
||||||
|
myLogger := logger.New(appoptions.Logger)
|
||||||
|
myLogger.SetLogLevel(appoptions.LogLevel)
|
||||||
|
|
||||||
result := &App{
|
result := &App{
|
||||||
bindings: binding.NewBindings(myLogger),
|
appType: "server",
|
||||||
logger: myLogger,
|
bindings: binding.NewBindings(myLogger, options.Bind),
|
||||||
servicebus: servicebus.New(myLogger),
|
logger: myLogger,
|
||||||
webserver: webserver.NewWebServer(myLogger),
|
servicebus: servicebus.New(myLogger),
|
||||||
|
webserver: webserver.NewWebServer(myLogger),
|
||||||
|
startupCallback: appoptions.Startup,
|
||||||
|
shutdownCallback: appoptions.Shutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise app
|
// Initialise app
|
||||||
result.Init()
|
result.Init()
|
||||||
|
|
||||||
return result
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the application
|
// Run the application
|
||||||
@@ -88,8 +107,21 @@ func (a *App) Run() error {
|
|||||||
if debugMode {
|
if debugMode {
|
||||||
a.servicebus.Debug()
|
a.servicebus.Debug()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the runtime
|
||||||
|
runtime, err := subsystem.NewRuntime(a.servicebus, a.logger, a.startupCallback, a.shutdownCallback)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
a.runtime = runtime
|
||||||
|
a.runtime.Start()
|
||||||
|
|
||||||
|
// Application Stores
|
||||||
|
a.loglevelStore = a.runtime.GoRuntime().Store.New("wails:loglevel", a.options.LogLevel)
|
||||||
|
a.appconfigStore = a.runtime.GoRuntime().Store.New("wails:appconfig", a.options)
|
||||||
|
|
||||||
a.servicebus.Start()
|
a.servicebus.Start()
|
||||||
log, err := subsystem.NewLog(a.servicebus, a.logger)
|
log, err := subsystem.NewLog(a.servicebus, a.logger, a.loglevelStore)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -102,14 +134,6 @@ func (a *App) Run() error {
|
|||||||
a.dispatcher = dispatcher
|
a.dispatcher = dispatcher
|
||||||
a.dispatcher.Start()
|
a.dispatcher.Start()
|
||||||
|
|
||||||
// Start the runtime
|
|
||||||
runtime, err := subsystem.NewRuntime(a.servicebus, a.logger)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.runtime = runtime
|
|
||||||
a.runtime.Start()
|
|
||||||
|
|
||||||
// Start the binding subsystem
|
// Start the binding subsystem
|
||||||
binding, err := subsystem.NewBinding(a.servicebus, a.logger, a.bindings, runtime.GoRuntime())
|
binding, err := subsystem.NewBinding(a.servicebus, a.logger, a.bindings, runtime.GoRuntime())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -127,7 +151,7 @@ func (a *App) Run() error {
|
|||||||
a.event.Start()
|
a.event.Start()
|
||||||
|
|
||||||
// Start the call subsystem
|
// Start the call subsystem
|
||||||
call, err := subsystem.NewCall(a.servicebus, a.logger, a.bindings.DB())
|
call, err := subsystem.NewCall(a.servicebus, a.logger, a.bindings.DB(), a.runtime.GoRuntime())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -147,14 +171,3 @@ func (a *App) Run() error {
|
|||||||
|
|
||||||
return cli.Run()
|
return cli.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind a struct to the application by passing in
|
|
||||||
// a pointer to it
|
|
||||||
func (a *App) Bind(structPtr interface{}) {
|
|
||||||
|
|
||||||
// Add the struct to the bindings
|
|
||||||
err := a.bindings.Add(structPtr)
|
|
||||||
if err != nil {
|
|
||||||
a.logger.Fatal("Error during binding: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,11 +13,21 @@ type Bindings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewBindings returns a new Bindings object
|
// NewBindings returns a new Bindings object
|
||||||
func NewBindings(logger *logger.Logger) *Bindings {
|
func NewBindings(logger *logger.Logger, structPointersToBind []interface{}) *Bindings {
|
||||||
return &Bindings{
|
result := &Bindings{
|
||||||
db: newDB(),
|
db: newDB(),
|
||||||
logger: logger.CustomLogger("Bindings"),
|
logger: logger.CustomLogger("Bindings"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the structs to bind
|
||||||
|
for _, ptr := range structPointersToBind {
|
||||||
|
err := result.Add(ptr)
|
||||||
|
if err != nil {
|
||||||
|
logger.Fatal("Error during binding: " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the given struct methods to the Bindings
|
// Add the given struct methods to the Bindings
|
||||||
|
|||||||
@@ -86,3 +86,10 @@ bool getJSONInt(JsonNode *item, const char* key, int *result) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonNode* mustParseJSON(const char* JSON) {
|
||||||
|
JsonNode* parsedUpdate = json_decode(JSON);
|
||||||
|
if ( parsedUpdate == NULL ) {
|
||||||
|
ABORT("Unable to decode JSON: %s\n", JSON);
|
||||||
|
}
|
||||||
|
return parsedUpdate;
|
||||||
|
}
|
||||||
@@ -35,4 +35,6 @@ JsonNode* mustJSONObject(JsonNode *node, const char* key);
|
|||||||
bool getJSONBool(JsonNode *item, const char* key, bool *result);
|
bool getJSONBool(JsonNode *item, const char* key, bool *result);
|
||||||
bool getJSONInt(JsonNode *item, const char* key, int *result);
|
bool getJSONInt(JsonNode *item, const char* key, int *result);
|
||||||
|
|
||||||
|
JsonNode* mustParseJSON(const char* JSON);
|
||||||
|
|
||||||
#endif //ASSETS_C_COMMON_H
|
#endif //ASSETS_C_COMMON_H
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ extern void DarkModeEnabled(struct Application*, char *callbackID);
|
|||||||
extern void SetApplicationMenu(struct Application*, const char *);
|
extern void SetApplicationMenu(struct Application*, const char *);
|
||||||
extern void AddTrayMenu(struct Application*, const char *menuTrayJSON);
|
extern void AddTrayMenu(struct Application*, const char *menuTrayJSON);
|
||||||
extern void SetTrayMenu(struct Application*, const char *menuTrayJSON);
|
extern void SetTrayMenu(struct Application*, const char *menuTrayJSON);
|
||||||
|
extern void UpdateTrayMenuLabel(struct Application*, const char* JSON);
|
||||||
extern void AddContextMenu(struct Application*, char *contextMenuJSON);
|
extern void AddContextMenu(struct Application*, char *contextMenuJSON);
|
||||||
extern void UpdateContextMenu(struct Application*, char *contextMenuJSON);
|
extern void UpdateContextMenu(struct Application*, char *contextMenuJSON);
|
||||||
|
|
||||||
|
|||||||
@@ -192,6 +192,10 @@ func (c *Client) SetTrayMenu(trayMenuJSON string) {
|
|||||||
C.SetTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON))
|
C.SetTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) UpdateTrayMenuLabel(JSON string) {
|
||||||
|
C.UpdateTrayMenuLabel(c.app.app, c.app.string2CString(JSON))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) UpdateContextMenu(contextMenuJSON string) {
|
func (c *Client) UpdateContextMenu(contextMenuJSON string) {
|
||||||
C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON))
|
C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,12 @@ void Fatal(struct Application *app, const char *message, ... ) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Requires NSString input EG lookupStringConstant(str("NSFontAttributeName"))
|
||||||
|
void* lookupStringConstant(id constantName) {
|
||||||
|
void ** dataPtr = CFBundleGetDataPointerForName(CFBundleGetBundleWithIdentifier((CFStringRef)str("com.apple.AppKit")), (CFStringRef) constantName);
|
||||||
|
return (dataPtr ? *dataPtr : nil);
|
||||||
|
}
|
||||||
|
|
||||||
bool isRetina(struct Application *app) {
|
bool isRetina(struct Application *app) {
|
||||||
CGFloat scale = GET_BACKINGSCALEFACTOR(app->mainWindow);
|
CGFloat scale = GET_BACKINGSCALEFACTOR(app->mainWindow);
|
||||||
if( (int)scale == 1 ) {
|
if( (int)scale == 1 ) {
|
||||||
@@ -913,7 +919,8 @@ void SetDebug(void *applicationPointer, int flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// SetContextMenus sets the context menu map for this application
|
|
||||||
|
// AddContextMenu sets the context menu map for this application
|
||||||
void AddContextMenu(struct Application *app, const char *contextMenuJSON) {
|
void AddContextMenu(struct Application *app, const char *contextMenuJSON) {
|
||||||
AddContextMenuToStore(app->contextMenuStore, contextMenuJSON);
|
AddContextMenuToStore(app->contextMenuStore, contextMenuJSON);
|
||||||
}
|
}
|
||||||
@@ -932,6 +939,13 @@ void SetTrayMenu(struct Application *app, const char* trayMenuJSON) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateTrayMenuLabel(struct Application* app, const char* JSON) {
|
||||||
|
ON_MAIN_THREAD(
|
||||||
|
UpdateTrayMenuLabelInStore(app->trayMenuStore, JSON);
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetBindings(struct Application *app, const char *bindings) {
|
void SetBindings(struct Application *app, const char *bindings) {
|
||||||
const char* temp = concat("window.wailsbindings = \"", bindings);
|
const char* temp = concat("window.wailsbindings = \"", bindings);
|
||||||
const char* jscall = concat(temp, "\";");
|
const char* jscall = concat(temp, "\";");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ffenestri
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo darwin CFLAGS: -DFFENESTRI_DARWIN=1
|
#cgo darwin CFLAGS: -DFFENESTRI_DARWIN=1
|
||||||
#cgo darwin LDFLAGS: -framework WebKit -lobjc
|
#cgo darwin LDFLAGS: -framework WebKit -framework CoreFoundation -lobjc
|
||||||
|
|
||||||
#include "ffenestri.h"
|
#include "ffenestri.h"
|
||||||
#include "ffenestri_darwin.h"
|
#include "ffenestri_darwin.h"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#define OBJC_OLD_DISPATCH_PROTOTYPES 1
|
#define OBJC_OLD_DISPATCH_PROTOTYPES 1
|
||||||
#include <objc/objc-runtime.h>
|
#include <objc/objc-runtime.h>
|
||||||
#include <CoreGraphics/CoreGraphics.h>
|
#include <CoreGraphics/CoreGraphics.h>
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
@@ -20,7 +21,6 @@
|
|||||||
#define strunicode(input) msg(c("NSString"), s("stringWithFormat:"), str("%C"), (unsigned short)input)
|
#define strunicode(input) msg(c("NSString"), s("stringWithFormat:"), str("%C"), (unsigned short)input)
|
||||||
#define cstr(input) (const char *)msg(input, s("UTF8String"))
|
#define cstr(input) (const char *)msg(input, s("UTF8String"))
|
||||||
#define url(input) msg(c("NSURL"), s("fileURLWithPath:"), str(input))
|
#define url(input) msg(c("NSURL"), s("fileURLWithPath:"), str(input))
|
||||||
|
|
||||||
#define ALLOC(classname) msg(c(classname), s("alloc"))
|
#define ALLOC(classname) msg(c(classname), s("alloc"))
|
||||||
#define ALLOC_INIT(classname) msg(msg(c(classname), s("alloc")), s("init"))
|
#define ALLOC_INIT(classname) msg(msg(c(classname), s("alloc")), s("init"))
|
||||||
#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("frame"))
|
#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("frame"))
|
||||||
@@ -107,7 +107,9 @@ void SetAppearance(struct Application* app, const char *);
|
|||||||
void WebviewIsTransparent(struct Application* app);
|
void WebviewIsTransparent(struct Application* app);
|
||||||
void WindowBackgroundIsTranslucent(struct Application* app);
|
void WindowBackgroundIsTranslucent(struct Application* app);
|
||||||
void SetTray(struct Application* app, const char *, const char *, const char *);
|
void SetTray(struct Application* app, const char *, const char *, const char *);
|
||||||
void SetContextMenus(struct Application* app, const char *);
|
//void SetContextMenus(struct Application* app, const char *);
|
||||||
void AddTrayMenu(struct Application* app, const char *);
|
void AddTrayMenu(struct Application* app, const char *);
|
||||||
|
|
||||||
|
void* lookupStringConstant(id constantName);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "ffenestri_darwin.h"
|
#include "ffenestri_darwin.h"
|
||||||
#include "menu_darwin.h"
|
#include "menu_darwin.h"
|
||||||
#include "contextmenus_darwin.h"
|
#include "contextmenus_darwin.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
// NewMenu creates a new Menu struct, saving the given menu structure as JSON
|
// NewMenu creates a new Menu struct, saving the given menu structure as JSON
|
||||||
Menu* NewMenu(JsonNode *menuData) {
|
Menu* NewMenu(JsonNode *menuData) {
|
||||||
@@ -63,8 +64,6 @@ MenuItemCallbackData* CreateMenuItemCallbackData(Menu *menu, id menuItem, const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DeleteMenu(Menu *menu) {
|
void DeleteMenu(Menu *menu) {
|
||||||
|
|
||||||
// Free menu item hashmap
|
// Free menu item hashmap
|
||||||
@@ -99,7 +98,11 @@ void DeleteMenu(Menu *menu) {
|
|||||||
|
|
||||||
// Creates a JSON message for the given menuItemID and data
|
// Creates a JSON message for the given menuItemID and data
|
||||||
const char* createMenuClickedMessage(const char *menuItemID, const char *data, enum MenuType menuType, const char *parentID) {
|
const char* createMenuClickedMessage(const char *menuItemID, const char *data, enum MenuType menuType, const char *parentID) {
|
||||||
|
|
||||||
JsonNode *jsonObject = json_mkobject();
|
JsonNode *jsonObject = json_mkobject();
|
||||||
|
if (menuItemID == NULL ) {
|
||||||
|
ABORT("Item ID NULL for menu!!\n");
|
||||||
|
}
|
||||||
json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
|
json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
|
||||||
json_append_member(jsonObject, "menuType", json_mkstring(MenuTypeAsString[(int)menuType]));
|
json_append_member(jsonObject, "menuType", json_mkstring(MenuTypeAsString[(int)menuType]));
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
@@ -572,7 +575,7 @@ id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const c
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers) {
|
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA) {
|
||||||
id item = ALLOC("NSMenuItem");
|
id item = ALLOC("NSMenuItem");
|
||||||
|
|
||||||
// Create a MenuItemCallbackData
|
// Create a MenuItemCallbackData
|
||||||
@@ -585,6 +588,73 @@ id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char
|
|||||||
msg(item, s("initWithTitle:action:keyEquivalent:"), str(title),
|
msg(item, s("initWithTitle:action:keyEquivalent:"), str(title),
|
||||||
s("menuItemCallback:"), key);
|
s("menuItemCallback:"), key);
|
||||||
|
|
||||||
|
if( tooltip != NULL ) {
|
||||||
|
msg(item, s("setToolTip:"), str(tooltip));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process image
|
||||||
|
if( image != NULL && strlen(image) > 0) {
|
||||||
|
id data = ALLOC("NSData");
|
||||||
|
id imageData = msg(data, s("initWithBase64EncodedString:options:"), str(image), 0);
|
||||||
|
id nsimage = ALLOC("NSImage");
|
||||||
|
msg(nsimage, s("initWithData:"), imageData);
|
||||||
|
msg(item, s("setImage:"), nsimage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process Menu Item attributes
|
||||||
|
id dictionary = ALLOC_INIT("NSMutableDictionary");
|
||||||
|
|
||||||
|
// Process font
|
||||||
|
id font;
|
||||||
|
CGFloat fontSizeFloat = (CGFloat)fontSize;
|
||||||
|
|
||||||
|
// Check if valid
|
||||||
|
id fontNameAsNSString = str(fontName);
|
||||||
|
id fontsOnSystem = msg(msg(c("NSFontManager"), s("sharedFontManager")), s("availableFonts"));
|
||||||
|
bool valid = msg(fontsOnSystem, s("containsObject:"), fontNameAsNSString);
|
||||||
|
if( valid ) {
|
||||||
|
font = msg(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
|
||||||
|
} else {
|
||||||
|
bool supportsMonospacedDigitSystemFont = (bool) msg(c("NSFont"), s("respondsToSelector:"), s("monospacedDigitSystemFontOfSize:weight:"));
|
||||||
|
if( supportsMonospacedDigitSystemFont ) {
|
||||||
|
font = msg(c("NSFont"), s("monospacedDigitSystemFontOfSize:weight:"), fontSizeFloat, NSFontWeightRegular);
|
||||||
|
} else {
|
||||||
|
font = msg(c("NSFont"), s("menuFontOfSize:"), fontSizeFloat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add font to dictionary
|
||||||
|
msg(dictionary, s("setObject:forKey:"), font, lookupStringConstant(str("NSFontAttributeName")));
|
||||||
|
|
||||||
|
// Add offset to dictionary
|
||||||
|
id offset = msg(c("NSNumber"), s("numberWithFloat:"), 0.0);
|
||||||
|
msg(dictionary, s("setObject:forKey:"), offset, lookupStringConstant(str("NSBaselineOffsetAttributeName")));
|
||||||
|
|
||||||
|
// RGBA
|
||||||
|
if( RGBA != NULL && strlen(RGBA) > 0) {
|
||||||
|
unsigned short r, g, b, a;
|
||||||
|
|
||||||
|
// white by default
|
||||||
|
r = g = b = a = 255;
|
||||||
|
int count = sscanf(RGBA, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
|
||||||
|
if (count > 0) {
|
||||||
|
id colour = msg(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
|
||||||
|
(float)r / 255.0,
|
||||||
|
(float)g / 255.0,
|
||||||
|
(float)b / 255.0,
|
||||||
|
(float)a / 255.0);
|
||||||
|
msg(dictionary, s("setObject:forKey:"), colour, lookupStringConstant(str("NSForegroundColorAttributeName")));
|
||||||
|
msg(colour, s("release"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id attributedString = ALLOC("NSMutableAttributedString");
|
||||||
|
msg(attributedString, s("initWithString:attributes:"), str(title), dictionary);
|
||||||
|
msg(dictionary, s("release"));
|
||||||
|
|
||||||
|
msg(item, s("setAttributedTitle:"), attributedString);
|
||||||
|
msg(attributedString, s("autorelease"));
|
||||||
|
|
||||||
msg(item, s("setEnabled:"), !disabled);
|
msg(item, s("setEnabled:"), !disabled);
|
||||||
msg(item, s("autorelease"));
|
msg(item, s("autorelease"));
|
||||||
|
|
||||||
@@ -666,6 +736,13 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
|||||||
const char *acceleratorkey = NULL;
|
const char *acceleratorkey = NULL;
|
||||||
const char **modifiers = NULL;
|
const char **modifiers = NULL;
|
||||||
|
|
||||||
|
const char *tooltip = getJSONString(item, "Tooltip");
|
||||||
|
const char *image = getJSONString(item, "Image");
|
||||||
|
const char *fontName = getJSONString(item, "FontName");
|
||||||
|
const char *RGBA = getJSONString(item, "RGBA");
|
||||||
|
int fontSize = 0;
|
||||||
|
getJSONInt(item, "FontSize", &fontSize);
|
||||||
|
|
||||||
// If we have an accelerator
|
// If we have an accelerator
|
||||||
if( accelerator != NULL ) {
|
if( accelerator != NULL ) {
|
||||||
// Get the key
|
// Get the key
|
||||||
@@ -698,7 +775,7 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
|||||||
if( type != NULL ) {
|
if( type != NULL ) {
|
||||||
|
|
||||||
if( STREQ(type->string_, "Text")) {
|
if( STREQ(type->string_, "Text")) {
|
||||||
processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers);
|
processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA);
|
||||||
}
|
}
|
||||||
else if ( STREQ(type->string_, "Separator")) {
|
else if ( STREQ(type->string_, "Separator")) {
|
||||||
addSeparator(parentMenu);
|
addSeparator(parentMenu);
|
||||||
|
|||||||
@@ -14,6 +14,21 @@ static const char *MenuTypeAsString[] = {
|
|||||||
"ApplicationMenu", "ContextMenu", "TrayMenu",
|
"ApplicationMenu", "ContextMenu", "TrayMenu",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _NSRange {
|
||||||
|
unsigned long location;
|
||||||
|
unsigned long length;
|
||||||
|
} NSRange;
|
||||||
|
|
||||||
|
#define NSFontWeightUltraLight -0.8
|
||||||
|
#define NSFontWeightThin -0.6
|
||||||
|
#define NSFontWeightLight -0.4
|
||||||
|
#define NSFontWeightRegular 0
|
||||||
|
#define NSFontWeightMedium 0.23
|
||||||
|
#define NSFontWeightSemibold 0.3
|
||||||
|
#define NSFontWeightBold 0.4
|
||||||
|
#define NSFontWeightHeavy 0.56
|
||||||
|
#define NSFontWeightBlack 0.62
|
||||||
|
|
||||||
extern void messageFromWindowCallback(const char *);
|
extern void messageFromWindowCallback(const char *);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -90,8 +105,7 @@ id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char
|
|||||||
|
|
||||||
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
|
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
|
||||||
|
|
||||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers);
|
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA);
|
||||||
|
|
||||||
void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
|
void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
|
||||||
void processMenuData(Menu *menu, JsonNode *menuData);
|
void processMenuData(Menu *menu, JsonNode *menuData);
|
||||||
|
|
||||||
|
|||||||
@@ -49,42 +49,19 @@ void DumpTrayMenu(TrayMenu* trayMenu) {
|
|||||||
printf(" ['%s':%p] = { label: '%s', icon: '%s', menu: %p, statusbar: %p }\n", trayMenu->ID, trayMenu, trayMenu->label, trayMenu->icon, trayMenu->menu, trayMenu->statusbaritem );
|
printf(" ['%s':%p] = { label: '%s', icon: '%s', menu: %p, statusbar: %p }\n", trayMenu->ID, trayMenu, trayMenu->label, trayMenu->icon, trayMenu->menu, trayMenu->statusbaritem );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTrayMenu(TrayMenu* trayMenu) {
|
|
||||||
|
|
||||||
// Create a status bar item if we don't have one
|
void UpdateTrayLabel(TrayMenu *trayMenu, const char *label) {
|
||||||
if( trayMenu->statusbaritem == NULL ) {
|
|
||||||
id statusBar = msg( c("NSStatusBar"), s("systemStatusBar") );
|
|
||||||
trayMenu->statusbaritem = msg(statusBar, s("statusItemWithLength:"), NSVariableStatusItemLength);
|
|
||||||
msg(trayMenu->statusbaritem, s("retain"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
id statusBarButton = msg(trayMenu->statusbaritem, s("button"));
|
|
||||||
msg(statusBarButton, s("setImagePosition:"), trayMenu->trayIconPosition);
|
|
||||||
|
|
||||||
// Update the icon if needed
|
|
||||||
UpdateTrayMenuIcon(trayMenu);
|
|
||||||
|
|
||||||
// Update the label if needed
|
|
||||||
UpdateTrayMenuLabel(trayMenu);
|
|
||||||
|
|
||||||
// Update the menu
|
|
||||||
id menu = GetMenu(trayMenu->menu);
|
|
||||||
msg(trayMenu->statusbaritem, s("setMenu:"), menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateTrayMenuLabel(TrayMenu *trayMenu) {
|
|
||||||
|
|
||||||
// Exit early if NULL
|
// Exit early if NULL
|
||||||
if( trayMenu->label == NULL ) {
|
if( trayMenu->label == NULL ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We don't check for a
|
// Update button label
|
||||||
id statusBarButton = msg(trayMenu->statusbaritem, s("button"));
|
id statusBarButton = msg(trayMenu->statusbaritem, s("button"));
|
||||||
msg(statusBarButton, s("setTitle:"), str(trayMenu->label));
|
msg(statusBarButton, s("setTitle:"), str(label));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTrayMenuIcon(TrayMenu *trayMenu) {
|
void UpdateTrayIcon(TrayMenu *trayMenu) {
|
||||||
|
|
||||||
// Exit early if NULL
|
// Exit early if NULL
|
||||||
if( trayMenu->icon == NULL ) {
|
if( trayMenu->icon == NULL ) {
|
||||||
@@ -105,6 +82,32 @@ void UpdateTrayMenuIcon(TrayMenu *trayMenu) {
|
|||||||
msg(statusBarButton, s("setImage:"), trayImage);
|
msg(statusBarButton, s("setImage:"), trayImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ShowTrayMenu(TrayMenu* trayMenu) {
|
||||||
|
|
||||||
|
// Create a status bar item if we don't have one
|
||||||
|
if( trayMenu->statusbaritem == NULL ) {
|
||||||
|
id statusBar = msg( c("NSStatusBar"), s("systemStatusBar") );
|
||||||
|
trayMenu->statusbaritem = msg(statusBar, s("statusItemWithLength:"), NSVariableStatusItemLength);
|
||||||
|
msg(trayMenu->statusbaritem, s("retain"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
id statusBarButton = msg(trayMenu->statusbaritem, s("button"));
|
||||||
|
msg(statusBarButton, s("setImagePosition:"), trayMenu->trayIconPosition);
|
||||||
|
|
||||||
|
// Update the icon if needed
|
||||||
|
UpdateTrayIcon(trayMenu);
|
||||||
|
|
||||||
|
// Update the label if needed
|
||||||
|
UpdateTrayLabel(trayMenu, trayMenu->label);
|
||||||
|
|
||||||
|
// Update the menu
|
||||||
|
id menu = GetMenu(trayMenu->menu);
|
||||||
|
msg(trayMenu->statusbaritem, s("setMenu:"), menu);
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateTrayMenuInPlace receives 2 menus. The current menu gets
|
// UpdateTrayMenuInPlace receives 2 menus. The current menu gets
|
||||||
// updated with the data from the new menu.
|
// updated with the data from the new menu.
|
||||||
void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
|
void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ TrayMenu* NewTrayMenu(const char *trayJSON);
|
|||||||
void DumpTrayMenu(TrayMenu* trayMenu);
|
void DumpTrayMenu(TrayMenu* trayMenu);
|
||||||
void ShowTrayMenu(TrayMenu* trayMenu);
|
void ShowTrayMenu(TrayMenu* trayMenu);
|
||||||
void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu);
|
void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu);
|
||||||
void UpdateTrayMenuIcon(TrayMenu *trayMenu);
|
void UpdateTrayIcon(TrayMenu *trayMenu);
|
||||||
void UpdateTrayMenuLabel(TrayMenu *trayMenu);
|
void UpdateTrayLabel(TrayMenu *trayMenu, const char*);
|
||||||
|
|
||||||
void LoadTrayIcons();
|
void LoadTrayIcons();
|
||||||
void UnloadTrayIcons();
|
void UnloadTrayIcons();
|
||||||
|
|||||||
@@ -72,15 +72,38 @@ TrayMenu* GetTrayMenuFromStore(TrayMenuStore* store, const char* menuID) {
|
|||||||
return hashmap_get(&store->trayMenuMap, menuID, strlen(menuID));
|
return hashmap_get(&store->trayMenuMap, menuID, strlen(menuID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TrayMenu* MustGetTrayMenuFromStore(TrayMenuStore* store, const char* menuID) {
|
||||||
|
// Get the current menu
|
||||||
|
TrayMenu* result = hashmap_get(&store->trayMenuMap, menuID, strlen(menuID));
|
||||||
|
if (result == NULL ) {
|
||||||
|
ABORT("Unable to find TrayMenu with ID '%s' in the TrayMenuStore!", menuID);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON) {
|
||||||
|
// Parse the JSON
|
||||||
|
JsonNode *parsedUpdate = mustParseJSON(JSON);
|
||||||
|
|
||||||
|
// Get the data out
|
||||||
|
const char* ID = mustJSONString(parsedUpdate, "ID");
|
||||||
|
const char* Label = mustJSONString(parsedUpdate, "Label");
|
||||||
|
|
||||||
|
// Check we have this menu
|
||||||
|
TrayMenu *menu = MustGetTrayMenuFromStore(store, ID);
|
||||||
|
UpdateTrayLabel(menu, Label);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
|
void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
|
||||||
TrayMenu* newMenu = NewTrayMenu(menuJSON);
|
TrayMenu* newMenu = NewTrayMenu(menuJSON);
|
||||||
|
// DumpTrayMenu(newMenu);
|
||||||
|
|
||||||
// Get the current menu
|
// Get the current menu
|
||||||
TrayMenu *currentMenu = GetTrayMenuFromStore(store, newMenu->ID);
|
TrayMenu *currentMenu = GetTrayMenuFromStore(store, newMenu->ID);
|
||||||
|
|
||||||
// If we don't have a menu, we create one
|
// If we don't have a menu, we create one
|
||||||
if ( currentMenu == NULL ) {
|
if ( currentMenu == NULL ) {
|
||||||
|
|
||||||
// Store the new menu
|
// Store the new menu
|
||||||
hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
|
hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu);
|
||||||
|
|
||||||
@@ -88,6 +111,7 @@ void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
|
|||||||
ShowTrayMenu(newMenu);
|
ShowTrayMenu(newMenu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// DumpTrayMenu(currentMenu);
|
||||||
|
|
||||||
// Save the status bar reference
|
// Save the status bar reference
|
||||||
newMenu->statusbaritem = currentMenu->statusbaritem;
|
newMenu->statusbaritem = currentMenu->statusbaritem;
|
||||||
@@ -98,12 +122,6 @@ void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) {
|
|||||||
DeleteMenu(currentMenu->menu);
|
DeleteMenu(currentMenu->menu);
|
||||||
currentMenu->menu = NULL;
|
currentMenu->menu = NULL;
|
||||||
|
|
||||||
// Free JSON
|
|
||||||
if (currentMenu->processedJSON != NULL ) {
|
|
||||||
json_delete(currentMenu->processedJSON);
|
|
||||||
currentMenu->processedJSON = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free the tray menu memory
|
// Free the tray menu memory
|
||||||
MEMFREE(currentMenu);
|
MEMFREE(currentMenu);
|
||||||
|
|
||||||
|
|||||||
@@ -22,4 +22,6 @@ void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON);
|
|||||||
void ShowTrayMenusInStore(TrayMenuStore* store);
|
void ShowTrayMenusInStore(TrayMenuStore* store);
|
||||||
void DeleteTrayMenuStore(TrayMenuStore* store);
|
void DeleteTrayMenuStore(TrayMenuStore* store);
|
||||||
|
|
||||||
|
void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON);
|
||||||
|
|
||||||
#endif //TRAYMENUSTORE_DARWIN_H
|
#endif //TRAYMENUSTORE_DARWIN_H
|
||||||
|
|||||||
@@ -9,28 +9,35 @@ import (
|
|||||||
type ProcessedMenuItem struct {
|
type ProcessedMenuItem struct {
|
||||||
ID string
|
ID string
|
||||||
// Label is what appears as the menu text
|
// Label is what appears as the menu text
|
||||||
Label string
|
Label string `json:",omitempty"`
|
||||||
// Role is a predefined menu type
|
// Role is a predefined menu type
|
||||||
Role menu.Role `json:"Role,omitempty"`
|
Role menu.Role `json:",omitempty"`
|
||||||
// Accelerator holds a representation of a key binding
|
// Accelerator holds a representation of a key binding
|
||||||
Accelerator *keys.Accelerator `json:"Accelerator,omitempty"`
|
Accelerator *keys.Accelerator `json:",omitempty"`
|
||||||
// Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu
|
// Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu
|
||||||
Type menu.Type
|
Type menu.Type
|
||||||
// Disabled makes the item unselectable
|
// Disabled makes the item unselectable
|
||||||
Disabled bool
|
Disabled bool `json:",omitempty"`
|
||||||
// Hidden ensures that the item is not shown in the menu
|
// Hidden ensures that the item is not shown in the menu
|
||||||
Hidden bool
|
Hidden bool `json:",omitempty"`
|
||||||
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
|
// Checked indicates if the item is selected (used by Checkbox and Radio types only)
|
||||||
Checked bool
|
Checked bool `json:",omitempty"`
|
||||||
// Submenu contains a list of menu items that will be shown as a submenu
|
// Submenu contains a list of menu items that will be shown as a submenu
|
||||||
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
//SubMenu []*MenuItem `json:"SubMenu,omitempty"`
|
||||||
SubMenu *ProcessedMenu `json:"SubMenu,omitempty"`
|
SubMenu *ProcessedMenu `json:",omitempty"`
|
||||||
|
|
||||||
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
|
// Colour
|
||||||
Foreground int
|
RGBA string `json:",omitempty"`
|
||||||
|
|
||||||
// Background colour
|
// Font
|
||||||
Background int
|
FontSize int `json:",omitempty"`
|
||||||
|
FontName string `json:",omitempty"`
|
||||||
|
|
||||||
|
// Image - base64 image data
|
||||||
|
Image string `json:",omitempty"`
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
Tooltip string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem {
|
func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem {
|
||||||
@@ -45,8 +52,12 @@ func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *Pr
|
|||||||
Disabled: menuItem.Disabled,
|
Disabled: menuItem.Disabled,
|
||||||
Hidden: menuItem.Hidden,
|
Hidden: menuItem.Hidden,
|
||||||
Checked: menuItem.Checked,
|
Checked: menuItem.Checked,
|
||||||
Foreground: menuItem.Foreground,
|
SubMenu: nil,
|
||||||
Background: menuItem.Background,
|
RGBA: menuItem.RGBA,
|
||||||
|
FontSize: menuItem.FontSize,
|
||||||
|
FontName: menuItem.FontName,
|
||||||
|
Image: menuItem.Image,
|
||||||
|
Tooltip: menuItem.Tooltip,
|
||||||
}
|
}
|
||||||
|
|
||||||
if menuItem.SubMenu != nil {
|
if menuItem.SubMenu != nil {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package menumanager
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@@ -94,6 +95,31 @@ func (m *Manager) GetTrayMenus() ([]string, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) {
|
||||||
|
trayID, trayMenuKnown := m.trayMenuPointers[trayMenu]
|
||||||
|
if !trayMenuKnown {
|
||||||
|
return "", fmt.Errorf("[UpdateTrayMenuLabel] unknown tray id for tray %s", trayMenu.Label)
|
||||||
|
}
|
||||||
|
|
||||||
|
type LabelUpdate struct {
|
||||||
|
ID string
|
||||||
|
Label string
|
||||||
|
}
|
||||||
|
|
||||||
|
update := &LabelUpdate{
|
||||||
|
ID: trayID,
|
||||||
|
Label: trayMenu.Label,
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(update)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "[UpdateTrayMenuLabel] ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(data), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) GetContextMenus() ([]string, error) {
|
func (m *Manager) GetContextMenus() ([]string, error) {
|
||||||
result := []string{}
|
result := []string{}
|
||||||
for _, contextMenu := range m.contextMenus {
|
for _, contextMenu := range m.contextMenus {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ type Client interface {
|
|||||||
DarkModeEnabled(callbackID string)
|
DarkModeEnabled(callbackID string)
|
||||||
SetApplicationMenu(menuJSON string)
|
SetApplicationMenu(menuJSON string)
|
||||||
SetTrayMenu(trayMenuJSON string)
|
SetTrayMenu(trayMenuJSON string)
|
||||||
|
UpdateTrayMenuLabel(JSON string)
|
||||||
UpdateContextMenu(contextMenuJSON string)
|
UpdateContextMenu(contextMenuJSON string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,6 +473,20 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) {
|
|||||||
client.frontend.UpdateContextMenu(updatedContextMenu)
|
client.frontend.UpdateContextMenu(updatedContextMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "updatetraymenulabel":
|
||||||
|
updatedTrayMenuLabel, ok := result.Data().(string)
|
||||||
|
if !ok {
|
||||||
|
d.logger.Error("Invalid data for 'menufrontend:updatetraymenulabel' : %#v",
|
||||||
|
result.Data())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Work out what we mean in a multi window environment...
|
||||||
|
// For now we will just pick the first one
|
||||||
|
for _, client := range d.clients {
|
||||||
|
client.frontend.UpdateTrayMenuLabel(updatedTrayMenuLabel)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
d.logger.Error("Unknown menufrontend command: %s", command)
|
d.logger.Error("Unknown menufrontend command: %s", command)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ type Menu interface {
|
|||||||
UpdateApplicationMenu()
|
UpdateApplicationMenu()
|
||||||
UpdateContextMenu(contextMenu *menu.ContextMenu)
|
UpdateContextMenu(contextMenu *menu.ContextMenu)
|
||||||
SetTrayMenu(trayMenu *menu.TrayMenu)
|
SetTrayMenu(trayMenu *menu.TrayMenu)
|
||||||
|
UpdateTrayMenuLabel(trayMenu *menu.TrayMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
type menuRuntime struct {
|
type menuRuntime struct {
|
||||||
@@ -34,3 +35,7 @@ func (m *menuRuntime) UpdateContextMenu(contextMenu *menu.ContextMenu) {
|
|||||||
func (m *menuRuntime) SetTrayMenu(trayMenu *menu.TrayMenu) {
|
func (m *menuRuntime) SetTrayMenu(trayMenu *menu.TrayMenu) {
|
||||||
m.bus.Publish("menu:settraymenu", trayMenu)
|
m.bus.Publish("menu:settraymenu", trayMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *menuRuntime) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) {
|
||||||
|
m.bus.Publish("menu:updatetraymenulabel", trayMenu)
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,9 +146,13 @@ func (s *Store) setupListener() {
|
|||||||
// Resetting the curent data will resync
|
// Resetting the curent data will resync
|
||||||
s.resync()
|
s.resync()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Do initial resync
|
||||||
|
s.resync()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) resync() {
|
func (s *Store) resync() {
|
||||||
|
|
||||||
// Stringify data
|
// Stringify data
|
||||||
newdata, err := json.Marshal(s.data.Interface())
|
newdata, err := json.Marshal(s.data.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -131,6 +131,17 @@ func (m *Menu) Start() error {
|
|||||||
// Notify frontend of menu change
|
// Notify frontend of menu change
|
||||||
m.bus.Publish("menufrontend:settraymenu", updatedMenu)
|
m.bus.Publish("menufrontend:settraymenu", updatedMenu)
|
||||||
|
|
||||||
|
case "updatetraymenulabel":
|
||||||
|
trayMenu := menuMessage.Data().(*menu.TrayMenu)
|
||||||
|
updatedLabel, err := m.menuManager.UpdateTrayMenuLabel(trayMenu)
|
||||||
|
if err != nil {
|
||||||
|
m.logger.Trace("%s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify frontend of menu change
|
||||||
|
m.bus.Publish("menufrontend:updatetraymenulabel", updatedLabel)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
m.logger.Error("unknown menu message: %+v", menuMessage)
|
m.logger.Error("unknown menu message: %+v", menuMessage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func (r *Runtime) Start() error {
|
|||||||
if r.startupCallback != nil {
|
if r.startupCallback != nil {
|
||||||
go r.startupCallback(r.runtime)
|
go r.startupCallback(r.runtime)
|
||||||
} else {
|
} else {
|
||||||
r.logger.Error("no startup callback registered!")
|
r.logger.Warning("no startup callback registered!")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
r.logger.Error("unknown hook message: %+v", hooksMessage)
|
r.logger.Error("unknown hook message: %+v", hooksMessage)
|
||||||
@@ -131,6 +131,8 @@ func (r *Runtime) GoRuntime() *runtime.Runtime {
|
|||||||
func (r *Runtime) shutdown() {
|
func (r *Runtime) shutdown() {
|
||||||
if r.shutdownCallback != nil {
|
if r.shutdownCallback != nil {
|
||||||
go r.shutdownCallback()
|
go r.shutdownCallback()
|
||||||
|
} else {
|
||||||
|
r.logger.Warning("no shutdown callback registered!")
|
||||||
}
|
}
|
||||||
r.logger.Trace("Shutdown")
|
r.logger.Trace("Shutdown")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,21 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/wailsapp/wails/v2"
|
"github.com/wailsapp/wails/v2"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
// Create application with options
|
// Create application with options
|
||||||
app := wails.CreateApp("{{.ProjectName}}", 1024, 768)
|
app, err := wails.CreateApp("{{.ProjectName}}", 1024, 768)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
app.Bind(newBasic())
|
app.Bind(newBasic())
|
||||||
|
|
||||||
app.Run()
|
err = app.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ type WebClient struct {
|
|||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (wc *WebClient) SetTrayMenu(trayMenuJSON string) {
|
||||||
|
wc.logger.Info("Not implemented in server build")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WebClient) UpdateTrayMenuLabel(trayMenuJSON string) {
|
||||||
|
wc.logger.Info("Not implemented in server build")
|
||||||
|
}
|
||||||
|
|
||||||
func (wc *WebClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) {
|
func (wc *WebClient) MessageDialog(dialogOptions *dialog.MessageDialog, callbackID string) {
|
||||||
wc.logger.Info("Not implemented in server build")
|
wc.logger.Info("Not implemented in server build")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
|||||||
options.CompiledBinary = compiledBinary
|
options.CompiledBinary = compiledBinary
|
||||||
|
|
||||||
// Create the command
|
// Create the command
|
||||||
fmt.Printf("Compile command: %+v", commands.AsSlice())
|
|
||||||
cmd := exec.Command(options.Compiler, commands.AsSlice()...)
|
cmd := exec.Command(options.Compiler, commands.AsSlice()...)
|
||||||
|
|
||||||
// Set the directory
|
// Set the directory
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func Build(options *Options) (string, error) {
|
|||||||
// return "", err
|
// return "", err
|
||||||
// }
|
// }
|
||||||
if !options.IgnoreFrontend {
|
if !options.IgnoreFrontend {
|
||||||
outputLogger.Println(" - Building Wails Frontend")
|
outputLogger.Println(" - Building Project Frontend")
|
||||||
err = builder.BuildFrontend(outputLogger)
|
err = builder.BuildFrontend(outputLogger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
@@ -12,6 +12,14 @@ func (m *Menu) Append(item *MenuItem) {
|
|||||||
m.Items = append(m.Items, item)
|
m.Items = append(m.Items, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge will append the items in the given menu
|
||||||
|
// into this menu
|
||||||
|
func (m *Menu) Merge(menu *Menu) {
|
||||||
|
for _, item := range menu.Items {
|
||||||
|
m.Items = append(m.Items, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Menu) Prepend(item *MenuItem) {
|
func (m *Menu) Prepend(item *MenuItem) {
|
||||||
m.Items = append([]*MenuItem{item}, m.Items...)
|
m.Items = append([]*MenuItem{item}, m.Items...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,18 @@ type MenuItem struct {
|
|||||||
// Callback function when menu clicked
|
// Callback function when menu clicked
|
||||||
Click Callback `json:"-"`
|
Click Callback `json:"-"`
|
||||||
|
|
||||||
// Foreground colour in hex RGBA format EG: 0xFF0000FF = #FF0000FF = red
|
// Colour
|
||||||
Foreground int
|
RGBA string
|
||||||
|
|
||||||
// Background colour
|
// Font
|
||||||
Background int
|
FontSize int
|
||||||
|
FontName string
|
||||||
|
|
||||||
|
// Image - base64 image data
|
||||||
|
Image string
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
Tooltip string
|
||||||
|
|
||||||
// This holds the menu item's parent.
|
// This holds the menu item's parent.
|
||||||
parent *MenuItem
|
parent *MenuItem
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
wailsruntime "github.com/wailsapp/wails/v2/internal/runtime"
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
wailsruntime "github.com/wailsapp/wails/v2/internal/runtime"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||||
|
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"github.com/wailsapp/wails/v2/pkg/logger"
|
"github.com/wailsapp/wails/v2/pkg/logger"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||||||
@@ -33,6 +34,7 @@ type App struct {
|
|||||||
LogLevel logger.LogLevel
|
LogLevel logger.LogLevel
|
||||||
Startup func(*wailsruntime.Runtime) `json:"-"`
|
Startup func(*wailsruntime.Runtime) `json:"-"`
|
||||||
Shutdown func() `json:"-"`
|
Shutdown func() `json:"-"`
|
||||||
|
Bind []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MergeDefaults will set the minimum default values for an application
|
// MergeDefaults will set the minimum default values for an application
|
||||||
|
|||||||
10
v2/pkg/str/str.go
Normal file
10
v2/pkg/str/str.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package str
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UnixNow() string {
|
||||||
|
return fmt.Sprintf("%+v", time.Now().Unix())
|
||||||
|
}
|
||||||
@@ -58,6 +58,7 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
|||||||
19
v2/wails.go
19
v2/wails.go
@@ -14,19 +14,12 @@ type Runtime = runtime.Runtime
|
|||||||
// Store is an alias for the Store object
|
// Store is an alias for the Store object
|
||||||
type Store = runtime.Store
|
type Store = runtime.Store
|
||||||
|
|
||||||
// CreateAppWithOptions creates an application based on the given config
|
// Run creates an application based on the given config and executes it
|
||||||
func CreateAppWithOptions(options *options.App) (*app.App, error) {
|
func Run(options *options.App) error {
|
||||||
return app.CreateApp(options)
|
app, err := app.CreateApp(options)
|
||||||
}
|
if err != nil {
|
||||||
|
return err
|
||||||
// CreateApp creates an application based on the given title, width and height
|
|
||||||
func CreateApp(title string, width int, height int) (*app.App, error) {
|
|
||||||
|
|
||||||
options := &options.App{
|
|
||||||
Title: title,
|
|
||||||
Width: width,
|
|
||||||
Height: height,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return app.CreateApp(options)
|
return app.Run()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user