mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 22:55:48 +01:00
[WIP] Normalisation of context menus creation/callbacks.
TODO: UpdateContextMenu()
This commit is contained in:
parent
bd74d45a91
commit
f460bf91ef
8 changed files with 484 additions and 298 deletions
|
|
@ -8,6 +8,12 @@
|
|||
#include "hashmap.h"
|
||||
#include "vec.h"
|
||||
|
||||
#define STREQ(a,b) strcmp(a, b) == 0
|
||||
#define STRCOPY(a) concat(a, "")
|
||||
#define STR_HAS_CHARS(input) input != NULL && strlen(input) > 0
|
||||
#define MEMFREE(input) free((void*)input); input = NULL;
|
||||
#define FREE_AND_SET(variable, value) if( variable != NULL ) { MEMFREE(variable); } variable = value
|
||||
|
||||
// Credit: https://stackoverflow.com/a/8465083
|
||||
char* concat(const char *string1, const char *string2)
|
||||
{
|
||||
|
|
|
|||
251
v2/internal/ffenestri/contextmenus_darwin.h
Normal file
251
v2/internal/ffenestri/contextmenus_darwin.h
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
////
|
||||
//// Created by Lea Anthony on 6/1/21.
|
||||
////
|
||||
//
|
||||
#ifndef CONTEXTMENU_DARWIN_H
|
||||
#define CONTEXTMENU_DARWIN_H
|
||||
|
||||
#include "common.h"
|
||||
#include "menu_darwin.h"
|
||||
#include "contextmenustore_darwin.h"
|
||||
|
||||
typedef struct {
|
||||
const char* ID;
|
||||
id nsmenu;
|
||||
Menu* menu;
|
||||
} ContextMenu;
|
||||
|
||||
|
||||
ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore *store) {
|
||||
ContextMenu* result = malloc(sizeof(ContextMenu));
|
||||
result->menu = NewMenu(menuData);
|
||||
result->nsmenu = NULL;
|
||||
result->menu->menuType = ContextMenuType;
|
||||
result->menu->parentData = store;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ContextMenuStore* NewContextMenuStore(const char* contextMenusAsJSON) {
|
||||
|
||||
ContextMenuStore* result = malloc(sizeof(ContextMenuStore));
|
||||
|
||||
// Init members
|
||||
result->contextMenusAsJSON = contextMenusAsJSON;
|
||||
result->processedContextMenus = NULL;
|
||||
result->contextMenuData = NULL;
|
||||
|
||||
// Allocate Context Menu Store
|
||||
if( 0 != hashmap_create((const unsigned)4, &result->contextMenuStore)) {
|
||||
ABORT("[NewContextMenus] Not enough memory to allocate contextMenuStore!");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ContextMenu* GetContextMenuByID(ContextMenuStore* store, const char *contextMenuID) {
|
||||
return (ContextMenu*)hashmap_get(&store->contextMenuStore, (char*)contextMenuID, strlen(contextMenuID));
|
||||
}
|
||||
|
||||
void DeleteContextMenu(ContextMenu* contextMenu) {
|
||||
// Free Menu
|
||||
DeleteMenu(contextMenu->menu);
|
||||
|
||||
// Free context menu
|
||||
free(contextMenu);
|
||||
}
|
||||
|
||||
int freeContextMenu(void *const context, struct hashmap_element_s *const e) {
|
||||
DeleteContextMenu(e->data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DeleteContextMenuStore(ContextMenuStore* store) {
|
||||
|
||||
// Delete context menus
|
||||
if( hashmap_num_entries(&store->contextMenuStore) > 0 ) {
|
||||
if (0 != hashmap_iterate_pairs(&store->contextMenuStore, freeContextMenu, NULL)) {
|
||||
ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!");
|
||||
}
|
||||
}
|
||||
|
||||
// Free context menu hashmap
|
||||
hashmap_destroy(&store->contextMenuStore);
|
||||
|
||||
// Destroy processed Context Menus
|
||||
if( store->processedContextMenus != NULL) {
|
||||
json_delete(store->processedContextMenus);
|
||||
store->processedContextMenus = NULL;
|
||||
}
|
||||
|
||||
// Delete any context menu data we may have stored
|
||||
if( store->contextMenuData != NULL ) {
|
||||
MEMFREE(store->contextMenuData);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessContextMenus(ContextMenuStore* store) {
|
||||
|
||||
// Decode the context menus JSON
|
||||
store->processedContextMenus = json_decode(store->contextMenusAsJSON);
|
||||
if( store->processedContextMenus == NULL ) {
|
||||
ABORT("[ProcessContextMenus] Unable to parse Context Menus JSON: %s", store->contextMenusAsJSON);
|
||||
}
|
||||
|
||||
// // Get the context menu items
|
||||
// JsonNode *contextMenuItems = json_find_member(store->processedContextMenus, "Items");
|
||||
// if( contextMenuItems == NULL ) {
|
||||
// ABORT("[ProcessContextMenus] Unable to find Items in processedContextMenus!");
|
||||
// }
|
||||
|
||||
// Iterate context menus
|
||||
JsonNode *contextMenu;
|
||||
json_foreach(contextMenu, store->processedContextMenus) {
|
||||
|
||||
const char* ID = getJSONString(contextMenu, "ID");
|
||||
if ( ID == NULL ) {
|
||||
ABORT("Unable to read ID of contextMenu\n");
|
||||
}
|
||||
|
||||
JsonNode* processedMenu = json_find_member(contextMenu, "ProcessedMenu");
|
||||
if ( processedMenu == NULL ) {
|
||||
ABORT("Unable to read ProcessedMenu of contextMenu\n");
|
||||
}
|
||||
// Create a new context menu instance
|
||||
ContextMenu *thisContextMenu = NewContextMenu(processedMenu, store);
|
||||
|
||||
// Store the item in the context menu map
|
||||
hashmap_put(&store->contextMenuStore, (char*)ID, strlen(ID), thisContextMenu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//bool ContextMenuExists(ContextMenus *contextMenus, const char* contextMenuID) {
|
||||
// return hashmap_get(&contextMenus->contextMenuStore, contextMenuID, strlen(contextMenuID)) != NULL;
|
||||
//}
|
||||
//
|
||||
//bool AddContextMenu(ContextMenu* contextMenu) {
|
||||
//
|
||||
// // Check if we already have this
|
||||
// if( ContextMenuExists(contextMenu->ID) ) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// // Store the context menu
|
||||
// if (0 != hashmap_put(&contextMenus->contextMenuStore, contextMenu->ID, strlen(contextMenu->ID), contextMenu)) {
|
||||
// ABORT("Unable to add context menu with ID '%s'", contextMenu->ID);
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//ContextMenus* NewContextMenus(const char* contextMenusAsJSON) {
|
||||
//
|
||||
// ContextMenus* result = malloc(sizeof(ContextMenus));
|
||||
//
|
||||
// // Allocate Context Menu Store
|
||||
// if( 0 != hashmap_create((const unsigned)4, &result->contextMenuStore)) {
|
||||
// ABORT("[NewContextMenus] Not enough memory to allocate contextMenuStore!");
|
||||
// }
|
||||
//
|
||||
// //
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
//
|
||||
//void ProcessContextMenus() {
|
||||
// // Parse the context menu json
|
||||
// processedContextMenus = json_decode(contextMenusAsJSON);
|
||||
// if( processedContextMenus == NULL ) {
|
||||
// // Parse error!
|
||||
// ABORT("Unable to parse Context Menus JSON: %s", contextMenusAsJSON);
|
||||
// }
|
||||
//
|
||||
// JsonNode *contextMenuItems = json_find_member(processedContextMenus, "Items");
|
||||
// if( contextMenuItems == NULL ) {
|
||||
// // Parse error!
|
||||
// ABORT("Unable to find Items in Context menus");
|
||||
// }
|
||||
// // Iterate context menus
|
||||
// JsonNode *contextMenu;
|
||||
// json_foreach(contextMenu, contextMenuItems) {
|
||||
// Menu *contextMenu = NewMenu()
|
||||
//
|
||||
// // Store the item in the context menu map
|
||||
// hashmap_put(&contextMenuMap, (char*)contextMenu->key, strlen(contextMenu->key), menu);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//ContextMenu* NewContextMenu() {
|
||||
// ContextMenu* result = malloc(sizeof(ContextMenu));
|
||||
//
|
||||
// result->menu = NewMenu(contextMenuAsJSON);
|
||||
//
|
||||
// return result;
|
||||
//}
|
||||
//
|
||||
|
||||
//
|
||||
//void InitContextMenuStore() {
|
||||
//
|
||||
//}
|
||||
//
|
||||
|
||||
//
|
||||
//void DeleteContextMenuStore() {
|
||||
// // Free radio group members
|
||||
// if( hashmap_num_entries(&contextMenuStore) > 0 ) {
|
||||
// if (0 != hashmap_iterate_pairs(&contextMenuStore, freeContextMenu, NULL)) {
|
||||
// ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData) {
|
||||
|
||||
printf("Show context menu '%s'. Also got data '%s'.\n\n", contextMenuID, contextMenuData);
|
||||
|
||||
// If no context menu ID was given, abort
|
||||
if( contextMenuID == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContextMenu* contextMenu = GetContextMenuByID(store, contextMenuID);
|
||||
|
||||
// We don't need the ID now
|
||||
MEMFREE(contextMenuID);
|
||||
|
||||
if( contextMenu == NULL ) {
|
||||
// Free context menu data
|
||||
if( contextMenuData != NULL ) {}
|
||||
MEMFREE(contextMenuData);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to store the context menu data. Free existing data if we have it
|
||||
// and set to the new value.
|
||||
FREE_AND_SET(store->contextMenuData, contextMenuData);
|
||||
|
||||
// Grab the content view and show the menu
|
||||
id contentView = msg(mainWindow, s("contentView"));
|
||||
|
||||
// Get the triggering event
|
||||
id menuEvent = msg(mainWindow, s("currentEvent"));
|
||||
|
||||
if( contextMenu->nsmenu == NULL ) {
|
||||
// GetMenu creates the NSMenu
|
||||
contextMenu->nsmenu = GetMenu(contextMenu->menu);
|
||||
}
|
||||
|
||||
printf("\n\nContext menu NSMenu = %p\n\n", contextMenu->menu->menu);
|
||||
|
||||
// Show popup
|
||||
msg(c("NSMenu"), s("popUpContextMenu:withEvent:forView:"), contextMenu->nsmenu, menuEvent, contentView);
|
||||
|
||||
}
|
||||
|
||||
#endif //CONTEXTMENU_DARWIN_H
|
||||
24
v2/internal/ffenestri/contextmenustore_darwin.h
Normal file
24
v2/internal/ffenestri/contextmenustore_darwin.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// Created by Lea Anthony on 7/1/21.
|
||||
//
|
||||
|
||||
#ifndef CONTEXTMENUSTORE_DARWIN_H
|
||||
#define CONTEXTMENUSTORE_DARWIN_H
|
||||
|
||||
typedef struct {
|
||||
// This is our context menu store which keeps track
|
||||
// of all instances of ContextMenus
|
||||
struct hashmap_s contextMenuStore;
|
||||
|
||||
// The raw JSON defining the context menus
|
||||
const char* contextMenusAsJSON;
|
||||
|
||||
// The optional data that may be passed with a context menu selection
|
||||
const char* contextMenuData;
|
||||
|
||||
// The processed context menus
|
||||
JsonNode* processedContextMenus;
|
||||
|
||||
} ContextMenuStore;
|
||||
|
||||
#endif //ASSETS_C_CONTEXTMENUSTORE_DARWIN_H
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "ffenestri_darwin.h"
|
||||
#include "menu_darwin.h"
|
||||
#include "contextmenus_darwin.h"
|
||||
|
||||
|
||||
// References to assets
|
||||
|
|
@ -28,15 +29,6 @@ struct hashmap_s radioGroupMapForTrayMenu;
|
|||
// A cache for all our tray icons
|
||||
struct hashmap_s trayIconCache;
|
||||
|
||||
// contextMenuMap is a hashmap of context menus keyed on a string ID
|
||||
struct hashmap_s contextMenuMap;
|
||||
|
||||
// MenuItem map for the context menus
|
||||
struct hashmap_s menuItemMapForContextMenus;
|
||||
|
||||
// RadioGroup map for the context menus. Maps a menuitem id with its associated radio group items
|
||||
struct hashmap_s radioGroupMapForContextMenus;
|
||||
|
||||
// A cache for all our dialog icons
|
||||
struct hashmap_s dialogIconCache;
|
||||
|
||||
|
|
@ -140,6 +132,7 @@ struct Application {
|
|||
id statusItem;
|
||||
|
||||
// Context Menus
|
||||
ContextMenuStore *contextMenuStore;
|
||||
const char *contextMenusAsJSON;
|
||||
JsonNode *processedContextMenus;
|
||||
|
||||
|
|
@ -232,40 +225,6 @@ void applyWindowColour(struct Application *app) {
|
|||
}
|
||||
}
|
||||
|
||||
void showContextMenu(struct Application *app, const char *contextMenuID) {
|
||||
|
||||
// If no context menu ID was given
|
||||
if( contextMenuID == NULL ) {
|
||||
// Show default context menu if we have one
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for the context menu for this ID
|
||||
id contextMenu = (id)hashmap_get(&contextMenuMap, (char*)contextMenuID, strlen(contextMenuID));
|
||||
|
||||
if( contextMenu == NULL ) {
|
||||
// printf("No context menu called '%s'. Available:", contextMenuID);
|
||||
// dumpHashmap("contextMenuMap", &contextMenuMap);
|
||||
|
||||
// Free menu id
|
||||
MEMFREE(contextMenuID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Free menu id
|
||||
MEMFREE(contextMenuID);
|
||||
|
||||
// Grab the content view and show the menu
|
||||
id contentView = msg(app->mainWindow, s("contentView"));
|
||||
|
||||
// Get the triggering event
|
||||
id menuEvent = msg(app->mainWindow, s("currentEvent"));
|
||||
|
||||
// Show popup
|
||||
msg(c("NSMenu"), s("popUpContextMenu:withEvent:forView:"), contextMenu, menuEvent, contentView);
|
||||
|
||||
}
|
||||
|
||||
void SetColour(struct Application *app, int red, int green, int blue, int alpha) {
|
||||
app->red = red;
|
||||
app->green = green;
|
||||
|
|
@ -345,10 +304,12 @@ void messageHandler(id self, SEL cmd, id contentController, id message) {
|
|||
JsonNode *contextMenuIDNode = json_find_member(contextMenuMessageJSON, "id");
|
||||
if( contextMenuIDNode == NULL ) {
|
||||
Debug(app, "Error decoding context menu ID: %s", contextMenuMessage);
|
||||
json_delete(contextMenuMessageJSON);
|
||||
return;
|
||||
}
|
||||
if( contextMenuIDNode->tag != JSON_STRING ) {
|
||||
Debug(app, "Error decoding context menu ID (Not a string): %s", contextMenuMessage);
|
||||
json_delete(contextMenuMessageJSON);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -356,23 +317,26 @@ void messageHandler(id self, SEL cmd, id contentController, id message) {
|
|||
JsonNode *contextMenuDataNode = json_find_member(contextMenuMessageJSON, "data");
|
||||
if( contextMenuDataNode == NULL ) {
|
||||
Debug(app, "Error decoding context menu data: %s", contextMenuMessage);
|
||||
json_delete(contextMenuMessageJSON);
|
||||
return;
|
||||
}
|
||||
if( contextMenuDataNode->tag != JSON_STRING ) {
|
||||
Debug(app, "Error decoding context menu data (Not a string): %s", contextMenuMessage);
|
||||
json_delete(contextMenuMessageJSON);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save a copy of the context menu data
|
||||
if ( contextMenuData != NULL ) {
|
||||
MEMFREE(contextMenuData);
|
||||
}
|
||||
contextMenuData = STRCOPY(contextMenuDataNode->string_);
|
||||
// We need to copy these as the JSON node will be destroyed on this thread and the
|
||||
// string data will become corrupt. These need to be freed by the context menu code.
|
||||
const char* contextMenuID = STRCOPY(contextMenuIDNode->string_);
|
||||
const char* contextMenuData = STRCOPY(contextMenuDataNode->string_);
|
||||
|
||||
ON_MAIN_THREAD(
|
||||
showContextMenu(app, contextMenuIDNode->string_);
|
||||
ShowContextMenu(app->contextMenuStore, app->mainWindow, contextMenuID, contextMenuData);
|
||||
);
|
||||
|
||||
json_delete(contextMenuMessageJSON);
|
||||
|
||||
} else {
|
||||
// const char *m = (const char *)msg(msg(message, s("body")), s("UTF8String"));
|
||||
const char *m = cstr(msg(message, s("body")));
|
||||
|
|
@ -380,15 +344,7 @@ void messageHandler(id self, SEL cmd, id contentController, id message) {
|
|||
}
|
||||
}
|
||||
|
||||
// Creates a JSON message for the given menuItemID and data
|
||||
const char* createContextMenuMessage(const char *menuItemID, const char *givenContextMenuData) {
|
||||
JsonNode *jsonObject = json_mkobject();
|
||||
json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
|
||||
json_append_member(jsonObject, "data", json_mkstring(givenContextMenuData));
|
||||
const char *result = json_encode(jsonObject);
|
||||
json_delete(jsonObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Callback for tray items
|
||||
void menuItemPressedForTrayMenu(id self, SEL cmd, id sender) {
|
||||
|
|
@ -400,16 +356,16 @@ void menuItemPressedForTrayMenu(id self, SEL cmd, id sender) {
|
|||
}
|
||||
|
||||
|
||||
// Callback for context menu items
|
||||
void menuItemPressedForContextMenus(id self, SEL cmd, id sender) {
|
||||
const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
// Notify the backend
|
||||
const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
const char *message = concat("XC", contextMenuMessage);
|
||||
messageFromWindowCallback(message);
|
||||
MEMFREE(message);
|
||||
MEMFREE(contextMenuMessage);
|
||||
}
|
||||
//// Callback for context menu items
|
||||
//void menuItemPressedForContextMenus(id self, SEL cmd, id sender) {
|
||||
// const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
// // Notify the backend
|
||||
// const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
// const char *message = concat("XC", contextMenuMessage);
|
||||
// messageFromWindowCallback(message);
|
||||
// MEMFREE(message);
|
||||
// MEMFREE(contextMenuMessage);
|
||||
//}
|
||||
|
||||
// Callback for tray menu items
|
||||
void checkboxMenuItemPressedForTrayMenu(id self, SEL cmd, id sender, struct hashmap_s *menuItemMap) {
|
||||
|
|
@ -431,25 +387,25 @@ void checkboxMenuItemPressedForTrayMenu(id self, SEL cmd, id sender, struct hash
|
|||
}
|
||||
|
||||
// Callback for context menu items
|
||||
void checkboxMenuItemPressedForContextMenus(id self, SEL cmd, id sender, struct hashmap_s *menuItemMap) {
|
||||
const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
|
||||
// Get the menu item from the menu item map
|
||||
id menuItem = (id)hashmap_get(&menuItemMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
|
||||
// Get the current state
|
||||
bool state = msg(menuItem, s("state"));
|
||||
|
||||
// Toggle the state
|
||||
msg(menuItem, s("setState:"), (state? NSControlStateValueOff : NSControlStateValueOn));
|
||||
|
||||
// Notify the backend
|
||||
const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
const char *message = concat("XC", contextMenuMessage);
|
||||
messageFromWindowCallback(message);
|
||||
MEMFREE(message);
|
||||
MEMFREE(contextMenuMessage);
|
||||
}
|
||||
//void checkboxMenuItemPressedForContextMenus(id self, SEL cmd, id sender, struct hashmap_s *menuItemMap) {
|
||||
// const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
//
|
||||
// // Get the menu item from the menu item map
|
||||
// id menuItem = (id)hashmap_get(&menuItemMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
//
|
||||
// // Get the current state
|
||||
// bool state = msg(menuItem, s("state"));
|
||||
//
|
||||
// // Toggle the state
|
||||
// msg(menuItem, s("setState:"), (state? NSControlStateValueOff : NSControlStateValueOn));
|
||||
//
|
||||
// // Notify the backend
|
||||
// const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
// const char *message = concat("XC", contextMenuMessage);
|
||||
// messageFromWindowCallback(message);
|
||||
// MEMFREE(message);
|
||||
// MEMFREE(contextMenuMessage);
|
||||
//}
|
||||
|
||||
// radioMenuItemPressedForTrayMenu
|
||||
void radioMenuItemPressedForTrayMenu(id self, SEL cmd, id sender) {
|
||||
|
|
@ -488,42 +444,42 @@ void radioMenuItemPressedForTrayMenu(id self, SEL cmd, id sender) {
|
|||
}
|
||||
|
||||
// radioMenuItemPressedForContextMenus
|
||||
void radioMenuItemPressedForContextMenus(id self, SEL cmd, id sender) {
|
||||
const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
|
||||
// Get the menu item from the menu item map
|
||||
id menuItem = (id)hashmap_get(&menuItemMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
|
||||
// Check the menu items' current state
|
||||
bool selected = msg(menuItem, s("state"));
|
||||
|
||||
// If it's already selected, exit early
|
||||
if (selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get this item's radio group members and turn them off
|
||||
id *members = (id*)hashmap_get(&radioGroupMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
|
||||
// Uncheck all members of the group
|
||||
id thisMember = members[0];
|
||||
int count = 0;
|
||||
while(thisMember != NULL) {
|
||||
msg(thisMember, s("setState:"), NSControlStateValueOff);
|
||||
count = count + 1;
|
||||
thisMember = members[count];
|
||||
}
|
||||
|
||||
// check the selected menu item
|
||||
msg(menuItem, s("setState:"), NSControlStateValueOn);
|
||||
|
||||
// Notify the backend
|
||||
const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
const char *message = concat("XC", contextMenuMessage);
|
||||
messageFromWindowCallback(message);
|
||||
MEMFREE(message);
|
||||
MEMFREE(contextMenuMessage);
|
||||
}
|
||||
//void radioMenuItemPressedForContextMenus(id self, SEL cmd, id sender) {
|
||||
// const char *menuItemID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue"));
|
||||
//
|
||||
// // Get the menu item from the menu item map
|
||||
// id menuItem = (id)hashmap_get(&menuItemMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
//
|
||||
// // Check the menu items' current state
|
||||
// bool selected = msg(menuItem, s("state"));
|
||||
//
|
||||
// // If it's already selected, exit early
|
||||
// if (selected) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // Get this item's radio group members and turn them off
|
||||
// id *members = (id*)hashmap_get(&radioGroupMapForContextMenus, (char*)menuItemID, strlen(menuItemID));
|
||||
//
|
||||
// // Uncheck all members of the group
|
||||
// id thisMember = members[0];
|
||||
// int count = 0;
|
||||
// while(thisMember != NULL) {
|
||||
// msg(thisMember, s("setState:"), NSControlStateValueOff);
|
||||
// count = count + 1;
|
||||
// thisMember = members[count];
|
||||
// }
|
||||
//
|
||||
// // check the selected menu item
|
||||
// msg(menuItem, s("setState:"), NSControlStateValueOn);
|
||||
//
|
||||
// // Notify the backend
|
||||
// const char *contextMenuMessage = createContextMenuMessage(menuItemID, contextMenuData);
|
||||
// const char *message = concat("XC", contextMenuMessage);
|
||||
// messageFromWindowCallback(message);
|
||||
// MEMFREE(message);
|
||||
// MEMFREE(contextMenuMessage);
|
||||
//}
|
||||
|
||||
// closeWindow is called when the close button is pressed
|
||||
void closeWindow(id self, SEL cmd, id sender) {
|
||||
|
|
@ -600,28 +556,6 @@ void allocateTrayHashMaps(struct Application *app) {
|
|||
}
|
||||
}
|
||||
|
||||
void allocateContextMenuHashMaps(struct Application *app) {
|
||||
|
||||
// Allocate new context menu map
|
||||
if( 0 != hashmap_create((const unsigned)4, &contextMenuMap)) {
|
||||
// Couldn't allocate map
|
||||
Fatal(app, "Not enough memory to allocate contextMenuMap!");
|
||||
}
|
||||
|
||||
// Allocate new menuItem map
|
||||
if( 0 != hashmap_create((const unsigned)16, &menuItemMapForContextMenus)) {
|
||||
// Couldn't allocate map
|
||||
Fatal(app, "Not enough memory to allocate menuItemMapForContextMenus!");
|
||||
}
|
||||
|
||||
// Allocate the Radio Group Cache
|
||||
if( 0 != hashmap_create((const unsigned)4, &radioGroupMapForContextMenus)) {
|
||||
// Couldn't allocate map
|
||||
Fatal(app, "Not enough memory to allocate radioGroupMapForContextMenus!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void* NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel) {
|
||||
// Setup main application struct
|
||||
struct Application *result = malloc(sizeof(struct Application));
|
||||
|
|
@ -670,6 +604,7 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
|
|||
result->statusItem = NULL;
|
||||
|
||||
// Context Menus
|
||||
result->contextMenuStore = NULL;
|
||||
result->contextMenusAsJSON = NULL;
|
||||
result->processedContextMenus = NULL;
|
||||
contextMenuData = NULL;
|
||||
|
|
@ -690,36 +625,7 @@ int releaseNSObject(void *const context, struct hashmap_element_s *const e) {
|
|||
}
|
||||
|
||||
void destroyContextMenus(struct Application *app) {
|
||||
|
||||
// Free menu item hashmap
|
||||
hashmap_destroy(&menuItemMapForContextMenus);
|
||||
|
||||
// Free radio group members
|
||||
if( hashmap_num_entries(&radioGroupMapForContextMenus) > 0 ) {
|
||||
if (0!=hashmap_iterate_pairs(&radioGroupMapForContextMenus, freeHashmapItem, NULL)) {
|
||||
Fatal(app, "failed to deallocate hashmap entries!");
|
||||
}
|
||||
}
|
||||
|
||||
//Free radio groups hashmap
|
||||
hashmap_destroy(&radioGroupMapForContextMenus);
|
||||
|
||||
// Free context menus
|
||||
if( hashmap_num_entries(&contextMenuMap) > 0 ) {
|
||||
if (0!=hashmap_iterate_pairs(&contextMenuMap, releaseNSObject, NULL)) {
|
||||
Fatal(app, "failed to deallocate hashmap entries!");
|
||||
}
|
||||
}
|
||||
|
||||
//Free context menu map
|
||||
hashmap_destroy(&contextMenuMap);
|
||||
|
||||
// Destroy processed Context Menus
|
||||
if( app->processedContextMenus != NULL) {
|
||||
json_delete(app->processedContextMenus);
|
||||
app->processedContextMenus = NULL;
|
||||
}
|
||||
|
||||
DeleteContextMenuStore(app->contextMenuStore);
|
||||
}
|
||||
|
||||
void freeDialogIconCache(struct Application *app) {
|
||||
|
|
@ -1298,10 +1204,9 @@ void SetTray(struct Application *app, const char *trayMenuAsJSON, const char *tr
|
|||
|
||||
// SetContextMenus sets the context menu map for this application
|
||||
void SetContextMenus(struct Application *app, const char *contextMenusAsJSON) {
|
||||
app->contextMenusAsJSON = contextMenusAsJSON;
|
||||
app->contextMenuStore = NewContextMenuStore(contextMenusAsJSON);
|
||||
}
|
||||
|
||||
|
||||
void SetBindings(struct Application *app, const char *bindings) {
|
||||
const char* temp = concat("window.wailsbindings = \"", bindings);
|
||||
const char* jscall = concat(temp, "\";");
|
||||
|
|
@ -1391,9 +1296,9 @@ void createDelegate(struct Application *app) {
|
|||
class_addMethod(delegateClass, s("menuCallbackForTrayMenu:"), (IMP)menuItemPressedForTrayMenu, "v@:@");
|
||||
class_addMethod(delegateClass, s("checkboxMenuCallbackForTrayMenu:"), (IMP) checkboxMenuItemPressedForTrayMenu, "v@:@");
|
||||
class_addMethod(delegateClass, s("radioMenuCallbackForTrayMenu:"), (IMP) radioMenuItemPressedForTrayMenu, "v@:@");
|
||||
class_addMethod(delegateClass, s("menuCallbackForContextMenus:"), (IMP)menuItemPressedForContextMenus, "v@:@");
|
||||
class_addMethod(delegateClass, s("checkboxMenuCallbackForContextMenus:"), (IMP) checkboxMenuItemPressedForContextMenus, "v@:@");
|
||||
class_addMethod(delegateClass, s("radioMenuCallbackForContextMenus:"), (IMP) radioMenuItemPressedForContextMenus, "v@:@");
|
||||
// class_addMethod(delegateClass, s("menuCallbackForContextMenus:"), (IMP)menuItemPressedForContextMenus, "v@:@");
|
||||
// class_addMethod(delegateClass, s("checkboxMenuCallbackForContextMenus:"), (IMP) checkboxMenuItemPressedForContextMenus, "v@:@");
|
||||
// class_addMethod(delegateClass, s("radioMenuCallbackForContextMenus:"), (IMP) radioMenuItemPressedForContextMenus, "v@:@");
|
||||
|
||||
// Refactoring menu handling
|
||||
class_addMethod(delegateClass, s("menuItemCallback:"), (IMP)menuItemCallback, "v@:@");
|
||||
|
|
@ -1799,52 +1704,52 @@ void UpdateMenu(struct Application *app, const char *menuAsJSON) {
|
|||
);
|
||||
}
|
||||
|
||||
void dumpContextMenus(struct Application *app) {
|
||||
dumpHashmap("menuItemMapForContextMenus", &menuItemMapForContextMenus);
|
||||
printf("&menuItemMapForContextMenus = %p\n", &menuItemMapForContextMenus);
|
||||
//void dumpContextMenus(struct Application *app) {
|
||||
// dumpHashmap("menuItemMapForContextMenus", &menuItemMapForContextMenus);
|
||||
// printf("&menuItemMapForContextMenus = %p\n", &menuItemMapForContextMenus);
|
||||
//
|
||||
// //Free radio groups hashmap
|
||||
// dumpHashmap("radioGroupMapForContextMenus", &radioGroupMapForContextMenus);
|
||||
// printf("&radioGroupMapForContextMenus = %p\n", &radioGroupMapForContextMenus);
|
||||
//
|
||||
// //Free context menu map
|
||||
// dumpHashmap("contextMenuMap", &contextMenuMap);
|
||||
// printf("&contextMenuMap = %p\n", &contextMenuMap);
|
||||
//}
|
||||
|
||||
//Free radio groups hashmap
|
||||
dumpHashmap("radioGroupMapForContextMenus", &radioGroupMapForContextMenus);
|
||||
printf("&radioGroupMapForContextMenus = %p\n", &radioGroupMapForContextMenus);
|
||||
|
||||
//Free context menu map
|
||||
dumpHashmap("contextMenuMap", &contextMenuMap);
|
||||
printf("&contextMenuMap = %p\n", &contextMenuMap);
|
||||
}
|
||||
|
||||
void parseContextMenus(struct Application *app) {
|
||||
|
||||
// Parse the context menu json
|
||||
app->processedContextMenus = json_decode(app->contextMenusAsJSON);
|
||||
|
||||
if( app->processedContextMenus == NULL ) {
|
||||
// Parse error!
|
||||
Fatal(app, "Unable to parse Context Menus JSON: %s", app->contextMenusAsJSON);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonNode *contextMenuItems = json_find_member(app->processedContextMenus, "Items");
|
||||
if( contextMenuItems == NULL ) {
|
||||
// Parse error!
|
||||
Fatal(app, "Unable to find Items:", app->processedContextMenus);
|
||||
return;
|
||||
}
|
||||
// Iterate context menus
|
||||
JsonNode *contextMenu;
|
||||
json_foreach(contextMenu, contextMenuItems) {
|
||||
// Create a new menu
|
||||
id menu = createMenu(str(""));
|
||||
|
||||
// parse the menu
|
||||
parseMenu(app, menu, contextMenu, &menuItemMapForContextMenus,
|
||||
"checkboxMenuCallbackForContextMenus:", "radioMenuCallbackForContextMenus:", "menuCallbackForContextMenus:");
|
||||
|
||||
// Store the item in the context menu map
|
||||
hashmap_put(&contextMenuMap, (char*)contextMenu->key, strlen(contextMenu->key), menu);
|
||||
}
|
||||
|
||||
// dumpContextMenus(app);
|
||||
}
|
||||
//void parseContextMenus(struct Application *app) {
|
||||
//
|
||||
// // Parse the context menu json
|
||||
// app->processedContextMenus = json_decode(app->contextMenusAsJSON);
|
||||
//
|
||||
// if( app->processedContextMenus == NULL ) {
|
||||
// // Parse error!
|
||||
// Fatal(app, "Unable to parse Context Menus JSON: %s", app->contextMenusAsJSON);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// JsonNode *contextMenuItems = json_find_member(app->processedContextMenus, "Items");
|
||||
// if( contextMenuItems == NULL ) {
|
||||
// // Parse error!
|
||||
// Fatal(app, "Unable to find Items:", app->processedContextMenus);
|
||||
// return;
|
||||
// }
|
||||
// // Iterate context menus
|
||||
// JsonNode *contextMenu;
|
||||
// json_foreach(contextMenu, contextMenuItems) {
|
||||
// // Create a new menu
|
||||
// id menu = createMenu(str(""));
|
||||
//
|
||||
// // parse the menu
|
||||
// parseMenu(app, menu, contextMenu, &menuItemMapForContextMenus,
|
||||
// "checkboxMenuCallbackForContextMenus:", "radioMenuCallbackForContextMenus:", "menuCallbackForContextMenus:");
|
||||
//
|
||||
// // Store the item in the context menu map
|
||||
// hashmap_put(&contextMenuMap, (char*)contextMenu->key, strlen(contextMenu->key), menu);
|
||||
// }
|
||||
//
|
||||
//// dumpContextMenus(app);
|
||||
//}
|
||||
|
||||
void UpdateTrayLabel(struct Application *app, const char *label) {
|
||||
id statusBarButton = msg(app->statusItem, s("button"));
|
||||
|
|
@ -1971,17 +1876,17 @@ void UpdateTray(struct Application *app, const char *trayMenuAsJSON) {
|
|||
}
|
||||
|
||||
void UpdateContextMenus(struct Application *app, const char *contextMenusAsJSON) {
|
||||
ON_MAIN_THREAD (
|
||||
|
||||
dumpContextMenus(app);
|
||||
|
||||
// Free up memory
|
||||
destroyContextMenus(app);
|
||||
|
||||
// Set the context menu JSON
|
||||
app->contextMenusAsJSON = contextMenusAsJSON;
|
||||
parseContextMenus(app);
|
||||
);
|
||||
// ON_MAIN_THREAD (
|
||||
//
|
||||
// dumpContextMenus(app);
|
||||
//
|
||||
// // Free up memory
|
||||
// destroyContextMenus(app);
|
||||
//
|
||||
// // Set the context menu JSON
|
||||
// app->contextMenusAsJSON = contextMenusAsJSON;
|
||||
// parseContextMenus(app);
|
||||
// );
|
||||
}
|
||||
|
||||
void processDialogIcons(struct hashmap_s *hashmap, const unsigned char *dialogIcons[]) {
|
||||
|
|
@ -2207,12 +2112,9 @@ void Run(struct Application *app, int argc, char **argv) {
|
|||
parseTrayData(app);
|
||||
}
|
||||
|
||||
// Allocation the hashmaps we need
|
||||
allocateContextMenuHashMaps(app);
|
||||
|
||||
// If we have context menus, process them
|
||||
if( app->contextMenusAsJSON != NULL ) {
|
||||
parseContextMenus(app);
|
||||
if( app->contextMenuStore != NULL ) {
|
||||
ProcessContextMenus(app->contextMenuStore);
|
||||
}
|
||||
|
||||
// Process dialog icons
|
||||
|
|
|
|||
|
|
@ -119,7 +119,24 @@ func (a *Application) processPlatformSettings() error {
|
|||
// Process context menus
|
||||
contextMenus := options.GetContextMenus(a.config)
|
||||
if contextMenus != nil {
|
||||
contextMenusJSON, err := json.Marshal(contextMenus)
|
||||
|
||||
type ProcessedContextMenu struct {
|
||||
ID string
|
||||
ProcessedMenu *ProcessedMenu
|
||||
}
|
||||
|
||||
var processedContextMenus []*ProcessedContextMenu
|
||||
|
||||
// We need to iterate each context menu and pre-process it
|
||||
for contextMenuID, contextMenu := range contextMenus.Items {
|
||||
thisContextMenu := &ProcessedContextMenu{
|
||||
ID: contextMenuID,
|
||||
ProcessedMenu: NewProcessedMenu(contextMenu),
|
||||
}
|
||||
processedContextMenus = append(processedContextMenus, thisContextMenu )
|
||||
}
|
||||
|
||||
contextMenusJSON, err := json.Marshal(processedContextMenus)
|
||||
fmt.Printf("\n\nCONTEXT MENUS:\n %+v\n\n", string(contextMenusJSON))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -27,11 +27,6 @@
|
|||
#define GET_BOUNDS(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("bounds"))
|
||||
#define GET_BACKINGSCALEFACTOR(receiver) ((CGFloat(*)(id, SEL))msg)(receiver, s("backingScaleFactor"))
|
||||
|
||||
#define STREQ(a,b) strcmp(a, b) == 0
|
||||
#define STRCOPY(a) concat(a, "")
|
||||
#define STR_HAS_CHARS(input) input != NULL && strlen(input) > 0
|
||||
#define MEMFREE(input) free((void*)input); input = NULL;
|
||||
|
||||
#define ON_MAIN_THREAD(str) dispatch( ^{ str; } )
|
||||
#define MAIN_WINDOW_CALL(str) msg(app->mainWindow, s((str)))
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
#define MENU_DARWIN_H
|
||||
|
||||
#include "common.h"
|
||||
#include "contextmenustore_darwin.h"
|
||||
|
||||
enum MenuItemType {Text = 0, Checkbox = 1, Radio = 2};
|
||||
enum MenuType {ApplicationMenu = 0};
|
||||
enum MenuType {ApplicationMenuType = 0, ContextMenuType = 1};
|
||||
|
||||
extern void messageFromWindowCallback(const char *);
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ typedef struct {
|
|||
|
||||
/*** Internal ***/
|
||||
|
||||
const char *menuAsJSON;
|
||||
// The decoded version of the Menu JSON
|
||||
JsonNode *processedMenu;
|
||||
|
||||
struct hashmap_s menuItemMap;
|
||||
|
|
@ -30,6 +31,9 @@ typedef struct {
|
|||
// The NSMenu for this menu
|
||||
id menu;
|
||||
|
||||
// The parent data, eg ContextMenuStore or Tray
|
||||
void *parentData;
|
||||
|
||||
// The commands for the menu callbacks
|
||||
const char *callbackCommand;
|
||||
|
||||
|
|
@ -40,12 +44,11 @@ typedef struct {
|
|||
} Menu;
|
||||
|
||||
// NewMenu creates a new Menu struct, saving the given menu structure as JSON
|
||||
Menu* NewMenu(const char *menuAsJSON) {
|
||||
Menu* NewMenu(JsonNode *menuData) {
|
||||
|
||||
Menu *result = malloc(sizeof(Menu));
|
||||
|
||||
// menuAsJSON is allocated and freed by Go
|
||||
result->menuAsJSON = menuAsJSON;
|
||||
result->processedMenu = menuData;
|
||||
|
||||
// No title by default
|
||||
result->title = "";
|
||||
|
|
@ -66,8 +69,16 @@ Menu* NewMenu(const char *menuAsJSON) {
|
|||
}
|
||||
|
||||
Menu* NewApplicationMenu(const char *menuAsJSON) {
|
||||
Menu *result = NewMenu(menuAsJSON);
|
||||
result->menuType = ApplicationMenu;
|
||||
|
||||
// Parse the menu json
|
||||
JsonNode *processedMenu = json_decode(menuAsJSON);
|
||||
if( processedMenu == NULL ) {
|
||||
// Parse error!
|
||||
ABORT("Unable to parse Menu JSON: %s", menuAsJSON);
|
||||
}
|
||||
|
||||
Menu *result = NewMenu(processedMenu);
|
||||
result->menuType = ApplicationMenuType;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -121,31 +132,14 @@ void DeleteMenu(Menu *menu) {
|
|||
free(menu);
|
||||
}
|
||||
|
||||
const char* createTextMenuMessage(MenuItemCallbackData *callbackData) {
|
||||
|
||||
switch( callbackData->menu->menuType ) {
|
||||
case ApplicationMenu:
|
||||
return concat("MC", callbackData->menuID);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* createCheckBoxMenuMessage(MenuItemCallbackData *callbackData) {
|
||||
|
||||
switch( callbackData->menu->menuType ) {
|
||||
case ApplicationMenu:
|
||||
return concat("MC", callbackData->menuID);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* createRadioMenuMessage(MenuItemCallbackData *callbackData) {
|
||||
|
||||
switch( callbackData->menu->menuType ) {
|
||||
case ApplicationMenu:
|
||||
return concat("MC", callbackData->menuID);
|
||||
}
|
||||
return NULL;
|
||||
// Creates a JSON message for the given menuItemID and data
|
||||
const char* createContextMenuMessage(const char *menuItemID, const char *givenContextMenuData) {
|
||||
JsonNode *jsonObject = json_mkobject();
|
||||
json_append_member(jsonObject, "menuItemID", json_mkstring(menuItemID));
|
||||
json_append_member(jsonObject, "data", json_mkstring(givenContextMenuData));
|
||||
const char *result = json_encode(jsonObject);
|
||||
json_delete(jsonObject);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Callback for text menu items
|
||||
|
|
@ -182,8 +176,13 @@ void menuItemCallback(id self, SEL cmd, id sender) {
|
|||
}
|
||||
|
||||
// Generate message to send to backend
|
||||
if( callbackData->menu->menuType == ApplicationMenu ) {
|
||||
if( callbackData->menu->menuType == ApplicationMenuType ) {
|
||||
message = concat("MC", callbackData->menuID);
|
||||
} else if( callbackData->menu->menuType == ContextMenuType ) {
|
||||
// Get the context menu data from the menu
|
||||
ContextMenuStore* store = (ContextMenuStore*) callbackData->menu->parentData;
|
||||
const char *contextMenuMessage = createContextMenuMessage(callbackData->menuID, store->contextMenuData);
|
||||
message = concat("XC", contextMenuMessage);
|
||||
}
|
||||
|
||||
// TODO: Add other menu types here!
|
||||
|
|
@ -647,8 +646,6 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
|||
name = menuNameNode->string_;
|
||||
}
|
||||
|
||||
printf("\n\nProcessing submenu %s!!!\n\n", name);
|
||||
|
||||
id thisMenuItem = createMenuItemNoAutorelease(str(name), NULL, "");
|
||||
id thisMenu = createMenu(str(name));
|
||||
|
||||
|
|
@ -750,7 +747,7 @@ void processMenuData(Menu *menu, JsonNode *menuData) {
|
|||
JsonNode *items = json_find_member(menuData, "Items");
|
||||
if( items == NULL ) {
|
||||
// Parse error!
|
||||
ABORT("Unable to find 'Items' in menu JSON:", menu->menuAsJSON);
|
||||
ABORT("Unable to find 'Items' in menu JSON!");
|
||||
}
|
||||
|
||||
// Iterate items
|
||||
|
|
@ -797,27 +794,17 @@ void processRadioGroupJSON(Menu *menu, JsonNode *radioGroup) {
|
|||
|
||||
id GetMenu(Menu *menu) {
|
||||
|
||||
menu->menu = createMenu(str(""));
|
||||
|
||||
// Parse the menu json
|
||||
JsonNode *processedMenu = json_decode(menu->menuAsJSON);
|
||||
if( processedMenu == NULL ) {
|
||||
// Parse error!
|
||||
ABORT("Unable to parse Menu JSON: %s", menu->menuAsJSON);
|
||||
}
|
||||
|
||||
// Pull out the menu data
|
||||
JsonNode *menuData = json_find_member(processedMenu, "Menu");
|
||||
JsonNode *menuData = json_find_member(menu->processedMenu, "Menu");
|
||||
if( menuData == NULL ) {
|
||||
ABORT("Unable to find Menu data: %s", processedMenu);
|
||||
ABORT("Unable to find Menu data: %s", menu->processedMenu);
|
||||
}
|
||||
|
||||
menu->menu = createMenu(str(""));
|
||||
|
||||
// Process the menu data
|
||||
processMenuData(menu, menuData);
|
||||
|
||||
// Save the reference so we can delete it later
|
||||
menu->processedMenu = processedMenu;
|
||||
|
||||
// Create the radiogroup cache
|
||||
JsonNode *radioGroups = json_find_member(menu->processedMenu, "RadioGroups");
|
||||
if( radioGroups == NULL ) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ var messageParsers = map[byte]func(string) (*parsedMessage, error){
|
|||
// Parse will attempt to parse the given message
|
||||
func Parse(message string) (*parsedMessage, error) {
|
||||
|
||||
if len(message) == 0 {
|
||||
return nil, fmt.Errorf("MessageParser received blank message");
|
||||
}
|
||||
|
||||
parseMethod := messageParsers[message[0]]
|
||||
if parseMethod == nil {
|
||||
return nil, fmt.Errorf("message type '%c' invalid", message[0])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue