Skip to content

Instantly share code, notes, and snippets.

@sbarisic
Created June 10, 2019 15:26
Show Gist options
  • Save sbarisic/86a7702522983615640b4f84ebfbcede to your computer and use it in GitHub Desktop.
Save sbarisic/86a7702522983615640b4f84ebfbcede to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include <ui.h>
#pragma comment(lib, "libui.lib")
#define DEF_ARGS JNIEnv* Env, jobject This
#define CLASS_FUNC(Name) Java_com_sbarisic_LibUI ## _ ## Name
#define JNI_FUNC(RetType, Name) JNIEXPORT RetType JNICALL CLASS_FUNC(Name)
#define CREATE_POINTER(Ptr) Env->NewDirectByteBuffer((void*)Ptr, 0)
#define FETCH_POINTER(Buffer) Env->GetDirectBufferAddress(Buffer)
#define SET_FIELD(Name, Sig, Val) Env->SetObjectField(This, Env->GetFieldID(Env->GetObjectClass(This), Name, Sig), Val)
#define SET_POINTER(Name, Ptr) SET_FIELD(Name, "Ljava/nio/ByteBuffer;", CREATE_POINTER(Ptr))
#define GET_FIELD(Name, Sig) Env->GetObjectField(This, Env->GetFieldID(Env->GetObjectClass(This), Name, Sig))
#define GET_POINTER(Name) FETCH_POINTER(GET_FIELD(Name, "Ljava/nio/ByteBuffer;"))
typedef struct {
public:
uiInitOptions Opt;
} LibUIState;
typedef struct {
JNIEnv* Env;
jobject Func;
jmethodID MethodID;
} JavaDelegate;
int OnShouldQuit(void* Data) {
uiQuit();
return 1;
}
int OnClosing(uiWindow* W, void* Data) {
return OnShouldQuit(Data);
}
JavaDelegate* CreateDelegate(JNIEnv* Env, jobject Obj, const char* Name, const char* Sig) {
Obj = Env->NewGlobalRef(Obj);
JavaDelegate* Delegate = (JavaDelegate*)malloc(sizeof(JavaDelegate));
Delegate->Func = Obj;
Delegate->MethodID = Env->GetMethodID(Env->GetObjectClass(Obj), Name, Sig);
Delegate->Env = Env;
return Delegate;
}
void DestroyDelegate(JavaDelegate* Delegate) {
Delegate->Env->DeleteGlobalRef(Delegate->Func);
memset(Delegate, 0, sizeof(JavaDelegate));
free(Delegate);
}
void InvokeVoidDelegate(JavaDelegate* Delegate) {
Delegate->Env->CallVoidMethod(Delegate->Func, Delegate->MethodID);
}
void InvokePointerDelegate(JavaDelegate* Delegate, void* Ptr) {
JNIEnv* Env = Delegate->Env;
Env->CallVoidMethod(Delegate->Func, Delegate->MethodID, CREATE_POINTER(Ptr));
}
extern "C" {
JNI_FUNC(void, Init)(DEF_ARGS) {
LibUIState* State = (LibUIState*)malloc(sizeof(LibUIState));
memset(State, 0, sizeof(LibUIState));
if (uiInit(&State->Opt) != NULL)
abort();
SET_POINTER("StatePtr", State);
}
JNI_FUNC(void, RunMain)(DEF_ARGS) {
uiMain();
}
JNI_FUNC(jobject, NewWindow)(DEF_ARGS, jstring Title, jint Width, jint Height, jboolean HasMenuBar) {
uiMenu* wndMenu = uiNewMenu("File");
//item = uiMenuAppendItem(menu, "Save");
//uiMenuItemOnClicked(item, saveClicked, NULL);
uiMenuAppendQuitItem(wndMenu);
uiOnShouldQuit(OnShouldQuit, NULL);
const char* TitleStr = Env->GetStringUTFChars(Title, NULL);
uiWindow* W = uiNewWindow(TitleStr, Width, Height, HasMenuBar ? 1 : 0);
uiWindowOnClosing(W, OnClosing, NULL);
return CREATE_POINTER(W);
}
JNI_FUNC(jobject, NewMultilineEntry)(DEF_ARGS) {
return CREATE_POINTER(uiNewMultilineEntry());
}
JNI_FUNC(jobject, NewButton)(DEF_ARGS, jstring Text) {
const char* TextStr = Env->GetStringUTFChars(Text, NULL);
return CREATE_POINTER(uiNewButton(TextStr));
}
JNI_FUNC(jobject, NewVerticalBox)(DEF_ARGS) {
uiBox* Box = uiNewVerticalBox();
return CREATE_POINTER(Box);
}
JNI_FUNC(jobject, NewHorizontalBox)(DEF_ARGS) {
uiBox* Box = uiNewHorizontalBox();
return CREATE_POINTER(Box);
}
JNI_FUNC(jobject, NewEntry)(DEF_ARGS) {
return CREATE_POINTER(uiNewEntry());
}
JNI_FUNC(jobject, NewTab)(DEF_ARGS) {
return CREATE_POINTER(uiNewTab());
}
JNI_FUNC(void, MultilineEntrySetReadOnly)(DEF_ARGS, jobject Entry, jboolean ReadOnly) {
uiMultilineEntrySetReadOnly((uiMultilineEntry*)FETCH_POINTER(Entry), ReadOnly ? 1 : 0);
}
JNI_FUNC(void, BoxAppend)(DEF_ARGS, jobject Box, jobject Child, jboolean Stretchy) {
uiBox* BoxPtr = (uiBox*)FETCH_POINTER(Box);
uiControl* ChildPtr = uiControl(FETCH_POINTER(Child));
uiBoxAppend(BoxPtr, ChildPtr, Stretchy ? 1 : 0);
}
JNI_FUNC(void, ControlShow)(DEF_ARGS, jobject Ctrl) {
uiControlShow(uiControl(FETCH_POINTER(Ctrl)));
}
JNI_FUNC(void, WindowSetChild)(DEF_ARGS, jobject Window, jobject Child) {
uiWindowSetChild((uiWindow*)FETCH_POINTER(Window), uiControl(FETCH_POINTER(Child)));
}
JNI_FUNC(void, WindowSetMargined)(DEF_ARGS, jobject Window, jboolean Margined) {
uiWindowSetMargined((uiWindow*)FETCH_POINTER(Window), Margined ? 1 : 0);
}
JNI_FUNC(void, TabAppend)(DEF_ARGS, jobject Tab, jstring Name, jobject Ctrl) {
const char* NamePtr = Env->GetStringUTFChars(Name, NULL);
uiTabAppend((uiTab*)FETCH_POINTER(Tab), NamePtr, (uiControl*)FETCH_POINTER(Ctrl));
}
JNI_FUNC(void, BoxSetPadded)(DEF_ARGS, jobject Box, jboolean Padded) {
uiBoxSetPadded((uiBox*)FETCH_POINTER(Box), Padded ? 1 : 0);
}
void OnMultilineEntryChanged(uiMultilineEntry* Entry, void* Data) {
InvokePointerDelegate((JavaDelegate*)Data, (void*)Entry);
}
JNI_FUNC(void, MultilineEntryOnChanged)(DEF_ARGS, jobject Entry, jobject Func) {
uiMultilineEntryOnChanged((uiMultilineEntry*)FETCH_POINTER(Entry), OnMultilineEntryChanged, CreateDelegate(Env, Func, "Func", "(Ljava/nio/ByteBuffer;)V"));
}
JNI_FUNC(jstring, MultilineEntryText)(DEF_ARGS, jobject Entry) {
return Env->NewStringUTF(uiMultilineEntryText((uiMultilineEntry*)FETCH_POINTER(Entry)));
}
JNI_FUNC(void, MultilineEntrySetText)(DEF_ARGS, jobject Entry, jstring Text) {
const char* TextPtr = Env->GetStringUTFChars(Text, NULL);
uiMultilineEntrySetText((uiMultilineEntry*)FETCH_POINTER(Entry), TextPtr);
}
void OnButtonClicked(uiButton* Button, void* Data) {
InvokePointerDelegate((JavaDelegate*)Data, (void*)Data);
}
JNI_FUNC(void, ButtonOnClicked)(DEF_ARGS, jobject Button, jobject Func) {
uiButtonOnClicked((uiButton*)FETCH_POINTER(Button), OnButtonClicked, CreateDelegate(Env, Func, "Func", "(Ljava/nio/ByteBuffer;)V"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment