Merge pull request #920 from andreasb242/scripting

Scripting
presentation
andreasb242 7 years ago committed by GitHub
commit 739f9bddb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .settings/.gitignore
  2. 15
      .settings/language.settings.xml
  3. 5
      plugins/Example/main.lua
  4. 27
      src/plugin/Plugin.cpp
  5. 11
      src/plugin/Plugin.h
  6. 2
      src/plugin/PluginController.cpp
  7. 86
      src/plugin/luapi_application.h
  8. 18
      src/util/XojMsgBox.cpp
  9. 11
      src/util/XojMsgBox.h

@ -0,0 +1 @@
/language.settings.xml

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="0.1190743019" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.autotools.core.LibtoolGCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="587297783307056298" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>

@ -6,7 +6,7 @@ var_dump = require "var_dump"
function initUi()
print("Hello from Example: Plugin initUi called\n");
ref = app.registerUi({["menu"] = "Test123", ["callback"] = "exampleCallback"});
ref = app.registerUi({["menu"] = "Test123", ["callback"] = "exampleCallback", ["accelerator"] = "<Control>t"});
print("Menu reference:");
var_dump(ref);
@ -15,5 +15,6 @@ end
-- Callback if the menu item is executed
function exampleCallback()
app.msgbox("Test123", "yes,no");
result = app.msgbox("Test123", {[1] = "Yes", [2] = "No"});
print("result = " .. result)
end

@ -1,6 +1,7 @@
#include "Plugin.h"
#include <config.h>
#include <i18n.h>
#ifdef ENABLE_PLUGINS
@ -118,7 +119,7 @@ void Plugin::registerToolbar()
/**
* Register all menu entries to the menu
*/
void Plugin::registerMenu(GtkWidget* menu)
void Plugin::registerMenu(GtkWindow* mainWindow, GtkWidget* menu)
{
XOJ_CHECK_TYPE(Plugin);
@ -130,12 +131,23 @@ void Plugin::registerMenu(GtkWidget* menu)
gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
GtkAccelGroup* accelGroup = gtk_accel_group_new();
for (MenuEntry* m : menuEntries)
{
GtkWidget* mi = gtk_menu_item_new_with_label(m->menu.c_str());
m->widget = mi;
gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
if (m->accelerator != "")
{
guint acceleratorKey = 0;
GdkModifierType mods = (GdkModifierType)0;
gtk_accelerator_parse(m->accelerator.c_str(), &acceleratorKey, &mods);
gtk_widget_add_accelerator(mi, "activate", accelGroup, acceleratorKey, mods, GTK_ACCEL_VISIBLE);
}
g_signal_connect(mi, "activate", G_CALLBACK(
+[](GtkWidget* bt, MenuEntry* me)
{
@ -143,6 +155,8 @@ void Plugin::registerMenu(GtkWidget* menu)
me->plugin->executeMenuEntry(me);
}), m);
}
gtk_window_add_accel_group(GTK_WINDOW(mainWindow), accelGroup);
}
/**
@ -180,11 +194,12 @@ bool Plugin::isInInitUi()
*
* @return Internal ID, can e.g. be used to disable the menu
*/
int Plugin::registerMenu(string menu, string callback)
int Plugin::registerMenu(string menu, string callback, string accelerator)
{
MenuEntry* m = new MenuEntry(this);
m->menu = menu;
m->callback = callback;
m->accelerator = accelerator;
menuEntries.push_back(m);
return menuEntries.size() - 1;
@ -315,7 +330,9 @@ void Plugin::loadScript()
if (lua_pcall(lua, 0, 0, 0) != LUA_OK)
{
const char* errMsg = lua_tostring(lua, -1);
XojMsgBox::showPluginMessage(name, errMsg, MSG_BT_OK, true);
map<int, string> button;
button.insert(std::pair<int, string>(0, _("OK")));
XojMsgBox::showPluginMessage(name, errMsg, button, true);
g_warning("Could not run plugin Lua file: «%s», error: «%s»", luafile.c_str(), errMsg);
this->valid = false;
@ -334,7 +351,9 @@ bool Plugin::callFunction(string fnc)
if (lua_pcall(lua, 0, 0, 0))
{
const char* errMsg = lua_tostring(lua, -1);
XojMsgBox::showPluginMessage(name, errMsg, MSG_BT_OK, true);
map<int, string> button;
button.insert(std::pair<int, string>(0, _("OK")));
XojMsgBox::showPluginMessage(name, errMsg, button, true);
g_warning("Error in Plugin: «%s», error: «%s»", name.c_str(), errMsg);
return false;

@ -58,6 +58,13 @@ public:
* Callback function name
*/
string callback;
/**
* Accelerator key
*
* See https://developer.gnome.org/gtk3/stable/gtk3-Keyboard-Accelerators.html#gtk-accelerator-parse
*/
string accelerator;
};
class Plugin
@ -80,7 +87,7 @@ public:
/**
* Register all menu entries to the menu
*/
void registerMenu(GtkWidget* menu);
void registerMenu(GtkWindow* mainWindow, GtkWidget* menu);
/**
* Execute menu entry
@ -102,7 +109,7 @@ public:
*
* @return Internal ID, can e.g. be used to disable the menu
*/
int registerMenu(string menu, string callback);
int registerMenu(string menu, string callback, string accelerator);
private:
/**

@ -109,7 +109,7 @@ void PluginController::registerMenu()
GtkWidget* menuPlugin = control->getWindow()->get("menuPlugin");
for (Plugin* p : this->plugins)
{
p->registerMenu(menuPlugin);
p->registerMenu(control->getGtkWindow(), menuPlugin);
}
gtk_widget_show_all(menuPlugin);

@ -12,43 +12,38 @@
#include <XojMsgBox.h>
#include <StringUtils.h>
#include <map>
using std::map;
/**
* Example:
* app.msgbox("Test123", "yes,no")
* app.msgbox("Test123", {[1] = "Yes", [2] = "No"})
* Return 1 for yes, 2 for no in this example
*/
static int applib_msgbox(lua_State* L)
{
const char* msg = luaL_checkstring(L, 1);
const char* flags = luaL_checkstring(L, 2);
int type = 0;
for (string element : StringUtils::split(flags, ','))
// discard any extra arguments passed in
lua_settop(L, 2);
luaL_checktype(L, 2, LUA_TTABLE);
lua_pushnil(L);
map<int, string> button;
while (lua_next(L, 2) != 0)
{
if (element == "ok")
{
type |= MSG_BT_OK;
}
else if (element == "yes")
{
type |= MSG_BT_YES;
}
else if (element == "no")
{
type |= MSG_BT_NO;
}
else if (element == "cancel")
{
type |= MSG_BT_CANCEL;
}
else
{
g_warning("Plugin: Unsupported button type for app.msgbox «%s»", element.c_str());
}
int index = lua_tointeger(L, -2);
const char* buttonText = luaL_checkstring(L, -1);
lua_pop(L, 1);
button.insert(button.begin(), std::pair<int, string>(index, buttonText));
}
Plugin* plugin = Plugin::getPluginFromLua(L);
int result = XojMsgBox::showPluginMessage(plugin->getName(), msg, type);
int result = XojMsgBox::showPluginMessage(plugin->getName(), msg, button);
lua_pushinteger(L, result);
return 1;
}
@ -73,30 +68,41 @@ static int applib_registerUi(lua_State* L)
// 'unpack' the table by putting the values onto
// the stack first. Then convert those stack values
// into an appropriate C type.
lua_getfield(L, 1, "accelerator");
lua_getfield(L, 1, "menu");
lua_getfield(L, 1, "callback");
// stack now has following:
// 1 = {"menu"="MenuName", callback="functionName"}
// 1 = {"menu"="MenuName", callback="functionName", accelerator="<Control>a"}
// -3 = "<Control>a"
// -2 = "MenuName"
// -1 = "functionName"
const char* accelerator = luaL_optstring(L, -3, NULL);
const char* menu = luaL_optstring(L, -2, NULL);
const char* callback = luaL_optstring(L, -1, NULL);
if (callback == NULL)
{
luaL_error(L, "Missing callback function!");
}
if (menu == NULL)
{
menu = "";
}
if (accelerator == NULL)
{
accelerator = "";
}
int menuId = -1;
int toolbarId = -1;
if (menu)
{
menuId = plugin->registerMenu(menu, callback);
menuId = plugin->registerMenu(menu, callback, accelerator);
}
// Make sure to remove all vars which are put to the stack before!
lua_pop(L, 2);
lua_pop(L, 3);
// Add return value to the Stack
lua_createtable(L, 0, 2);
@ -119,10 +125,10 @@ static const luaL_Reg applib[] = {
{ "registerUi", applib_registerUi },
// Placeholder
{"MSG_BT_OK", NULL},
{"MSG_BT_YES", NULL},
{"MSG_BT_NO", NULL},
{"MSG_BT_CANCEL", NULL},
// {"MSG_BT_OK", NULL},
// {"MSG_BT_YES", NULL},
// {"MSG_BT_NO", NULL},
// {"MSG_BT_CANCEL", NULL},
{NULL, NULL}
};
@ -133,14 +139,14 @@ static const luaL_Reg applib[] = {
LUAMOD_API int luaopen_app(lua_State* L)
{
luaL_newlib(L, applib);
lua_pushnumber(L, MSG_BT_OK);
lua_setfield(L, -2, "MSG_BT_OK");
lua_pushnumber(L, MSG_BT_YES);
lua_setfield(L, -2, "MSG_BT_YES");
lua_pushnumber(L, MSG_BT_NO);
lua_setfield(L, -2, "MSG_BT_NO");
lua_pushnumber(L, MSG_BT_CANCEL);
lua_setfield(L, -2, "MSG_BT_CANCEL");
// lua_pushnumber(L, MSG_BT_OK);
// lua_setfield(L, -2, "MSG_BT_OK");
// lua_pushnumber(L, MSG_BT_YES);
// lua_setfield(L, -2, "MSG_BT_YES");
// lua_pushnumber(L, MSG_BT_NO);
// lua_setfield(L, -2, "MSG_BT_NO");
// lua_pushnumber(L, MSG_BT_CANCEL);
// lua_setfield(L, -2, "MSG_BT_CANCEL");
return 1;
}

@ -30,7 +30,7 @@ void XojMsgBox::showErrorToUser(GtkWindow* win, string msg)
gtk_widget_destroy(dialog);
}
int XojMsgBox::showPluginMessage(string pluginName, string msg, int type, bool error)
int XojMsgBox::showPluginMessage(string pluginName, string msg, map<int, string> button, bool error)
{
string header = string("Xournal++ Plugin «") + pluginName + "»";
@ -52,21 +52,9 @@ int XojMsgBox::showPluginMessage(string pluginName, string msg, int type, bool e
g_object_set_property(G_OBJECT(dialog), "secondary-text", &val);
g_value_unset(&val);
if (MSG_BT_OK & type)
for (auto& kv : button)
{
gtk_dialog_add_button(GTK_DIALOG(dialog), _("OK"), MSG_BT_OK);
}
if (MSG_BT_YES & type)
{
gtk_dialog_add_button(GTK_DIALOG(dialog), _("Yes"), MSG_BT_YES);
}
if (MSG_BT_NO & type)
{
gtk_dialog_add_button(GTK_DIALOG(dialog), _("No"), MSG_BT_NO);
}
if (MSG_BT_CANCEL & type)
{
gtk_dialog_add_button(GTK_DIALOG(dialog), _("Cancel"), MSG_BT_CANCEL);
gtk_dialog_add_button(GTK_DIALOG(dialog), kv.second.c_str(), kv.first);
}
int res = gtk_dialog_run(GTK_DIALOG(dialog));

@ -15,13 +15,8 @@
#include <string>
using std::string;
enum MsgBoxButtonType {
MSG_BT_OK = 1 << 0,
MSG_BT_YES = 1 << 1,
MSG_BT_NO = 1 << 2,
MSG_BT_CANCEL = 1 << 3
};
#include <map>
using std::map;
class XojMsgBox
{
@ -36,7 +31,7 @@ public:
static void setDefaultWindow(GtkWindow* win);
static void showErrorToUser(GtkWindow* win, string msg);
static int showPluginMessage(string pluginName, string msg, int type, bool error = false);
static int showPluginMessage(string pluginName, string msg, map<int, string> button, bool error = false);
static int replaceFileQuestion(GtkWindow* win, string msg);
static void showHelp(GtkWindow* win);
};

Loading…
Cancel
Save