Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 200 additions & 4 deletions jni_bindings/src/main/java/git/mojo/sdl/SDLActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,37 @@

import static android.content.Context.UI_MODE_SERVICE;

import static git.mojo.sdl.SDL.mContext;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.UiModeManager;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.ParcelFileDescriptor;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Surface;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

Expand All @@ -35,8 +45,6 @@ public class SDLActivity {
private static Runnable initCallback;

protected static Surface mSurface;
protected static Activity mContext;

private static SDLClipboard mClipboard;

public static void initialize() {
Expand Down Expand Up @@ -430,4 +438,192 @@ public static String formatLocale(Locale locale) {
}
return result;
}

/** Result of current messagebox. Also used for blocking the calling thread. */
protected static final int[] messageboxSelection = new int[1];

/**
* Shows the messagebox from UI thread and block calling thread.
* buttonFlags, buttonIds and buttonTexts must have same length.
* @param buttonFlags array containing flags for every button.
* @param buttonIds array containing id for every button.
* @param buttonTexts array containing text for every button.
* @param colors null for default or array of length 5 containing colors.
* @return button id or -1.
*/
public static int showMessageBox(
final int flags,
final String title,
final String message,
final int[] buttonFlags,
final int[] buttonIds,
final String[] buttonTexts,
final int[] colors) {

messageboxSelection[0] = -1;

// sanity checks

if ((buttonFlags.length != buttonIds.length) && (buttonIds.length != buttonTexts.length)) {
return -1; // implementation broken
}

// collect arguments for Dialog

final Bundle args = new Bundle();
args.putInt("flags", flags);
args.putString("title", title);
args.putString("message", message);
args.putIntArray("buttonFlags", buttonFlags);
args.putIntArray("buttonIds", buttonIds);
args.putStringArray("buttonTexts", buttonTexts);
args.putIntArray("colors", colors);

// trigger Dialog creation on UI thread

runOnUiThread(() -> createMessageBox(args));

// block the calling thread

synchronized (messageboxSelection) {
try {
messageboxSelection.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
return -1;
}
}

// return selected value

return messageboxSelection[0];
}

private static void runOnUiThread(Runnable runnable) {
mContext.runOnUiThread(runnable);
}

private static void createMessageBox(Bundle args) {

// TODO set values from "flags" to messagebox dialog

// get colors

int[] colors = args.getIntArray("colors");
int backgroundColor;
int textColor;
int buttonBorderColor;
int buttonBackgroundColor;
int buttonSelectedColor;
if (colors != null) {
int i = -1;
backgroundColor = colors[++i];
textColor = colors[++i];
buttonBorderColor = colors[++i];
buttonBackgroundColor = colors[++i];
buttonSelectedColor = colors[++i];
} else {
backgroundColor = Color.TRANSPARENT;
textColor = Color.TRANSPARENT;
buttonBorderColor = Color.TRANSPARENT;
buttonBackgroundColor = Color.TRANSPARENT;
buttonSelectedColor = Color.TRANSPARENT;
}

// create dialog with title and a listener to wake up calling thread

final AlertDialog dialog = new AlertDialog.Builder(mContext).create();
dialog.setTitle(args.getString("title"));
dialog.setCancelable(false);
dialog.setOnDismissListener(unused -> {
synchronized (messageboxSelection) {
messageboxSelection.notify();
}
});

// create text

TextView message = new TextView(mContext);
message.setGravity(Gravity.CENTER);
message.setText(args.getString("message"));
if (textColor != Color.TRANSPARENT) {
message.setTextColor(textColor);
}

// create buttons

int[] buttonFlags = args.getIntArray("buttonFlags");
int[] buttonIds = args.getIntArray("buttonIds");
String[] buttonTexts = args.getStringArray("buttonTexts");

final SparseArray<Button> mapping = new SparseArray<Button>();

LinearLayout buttons = new LinearLayout(mContext);
buttons.setOrientation(LinearLayout.HORIZONTAL);
buttons.setGravity(Gravity.CENTER);
for (int i = 0; i < buttonTexts.length; ++i) {
Button button = new Button(mContext);
final int id = buttonIds[i];
button.setOnClickListener(v -> {
messageboxSelection[0] = id;
dialog.dismiss();
});
if (buttonFlags[i] != 0) {
// see SDL_messagebox.h
if ((buttonFlags[i] & 0x00000001) != 0) {
mapping.put(KeyEvent.KEYCODE_ENTER, button);
}
if ((buttonFlags[i] & 0x00000002) != 0) {
mapping.put(KeyEvent.KEYCODE_ESCAPE, button); /* API 11 */
}
}
button.setText(buttonTexts[i]);
if (textColor != Color.TRANSPARENT) {
button.setTextColor(textColor);
}
if (buttonBorderColor != Color.TRANSPARENT) {
// TODO set color for border of messagebox button
}
if (buttonBackgroundColor != Color.TRANSPARENT) {
Drawable drawable = button.getBackground();
if (drawable == null) {
// setting the color this way removes the style
button.setBackgroundColor(buttonBackgroundColor);
} else {
// setting the color this way keeps the style (gradient, padding, etc.)
drawable.setColorFilter(buttonBackgroundColor, PorterDuff.Mode.MULTIPLY);
}
}
if (buttonSelectedColor != Color.TRANSPARENT) {
// TODO set color for selected messagebox button
}
buttons.addView(button);
}

// create content

LinearLayout content = new LinearLayout(mContext);
content.setOrientation(LinearLayout.VERTICAL);
content.addView(message);
content.addView(buttons);
if (backgroundColor != Color.TRANSPARENT) {
content.setBackgroundColor(backgroundColor);
}

// add content to dialog and return

dialog.setView(content);
dialog.setOnKeyListener((d, keyCode, event) -> {
Button button = mapping.get(keyCode);
if (button != null) {
if (event.getAction() == KeyEvent.ACTION_UP) {
button.performClick();
}
return true; // also for ignored actions
}
return false;
});

dialog.show();
}
}
18 changes: 4 additions & 14 deletions src/core/android/SDL_android.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static jmethodID midSendMessage;
static jmethodID midNotifyInit;
static jmethodID midOpenFileDescriptor;
static jmethodID midManualBackButton;
static jmethodID midShowMessageBox;
#ifndef SDL_DIALOG_DISABLED
static jmethodID midShowFileDialog;
#endif // !SDL_DIALOG_DISABLED
Expand Down Expand Up @@ -674,6 +675,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
midNotifyInit = (*env)->GetStaticMethodID(env, mActivityClass, "onSDLInit", "()V");
midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I");
midManualBackButton = (*env)->GetStaticMethodID(env, mActivityClass, "manualBackButton", "()V");
midShowMessageBox = (*env)->GetStaticMethodID(env, mActivityClass, "showMessageBox", "(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
#ifndef SDL_DIALOG_DISABLED
midShowFileDialog = (*env)->GetStaticMethodID(env, mActivityClass, "showFileDialog", "([Ljava/lang/String;ZILjava/lang/String;I)Z");
#endif // !SDL_DIALOG_DISABLED
Expand All @@ -692,6 +694,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
!midSendMessage ||
!midOpenFileDescriptor ||
!midManualBackButton ||
!midShowMessageBox ||
#ifndef SDL_DIALOG_DISABLED
!midShowFileDialog ||
#endif
Expand Down Expand Up @@ -3082,16 +3085,7 @@ bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *b
colors = NULL;
}

(*env)->DeleteLocalRef(env, clazz);

// context = SDLActivity.getContext();
context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext);

clazz = (*env)->GetObjectClass(env, context);

mid = (*env)->GetMethodID(env, clazz,
"messageboxShowMessageBox", "(ILjava/lang/String;Ljava/lang/String;[I[I[Ljava/lang/String;[I)I");
*buttonID = (*env)->CallIntMethod(env, context, mid,
*buttonID = (*env)->CallStaticIntMethod(env, mActivityClass, midShowMessageBox,
(jint)messageboxdata->flags,
title,
message,
Expand All @@ -3100,11 +3094,7 @@ bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *b
button_texts,
colors);

(*env)->DeleteLocalRef(env, context);
(*env)->DeleteLocalRef(env, clazz);

// delete parameters

(*env)->DeleteLocalRef(env, title);
(*env)->DeleteLocalRef(env, message);
(*env)->DeleteLocalRef(env, button_flags);
Expand Down
Loading