[Android] Draw notification messages instead of using toaster
This commit is contained in:
parent
49dcce96e9
commit
9b1587992e
|
@ -1,20 +1,27 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project 64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
* *
|
||||
* Project 64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
package emu.project64.game;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import emu.project64.input.TouchController;
|
||||
import emu.project64.input.map.VisibleTouchMap;
|
||||
import emu.project64.util.DeviceUtil;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
|
@ -24,35 +31,84 @@ public class GameOverlay extends View implements TouchController.OnStateChangedL
|
|||
private boolean mDrawingEnabled = true;
|
||||
private int mHatRefreshPeriod = 0;
|
||||
private int mHatRefreshCount = 0;
|
||||
|
||||
public GameOverlay( Context context, AttributeSet attribs )
|
||||
private Paint mPaint = new Paint();
|
||||
private Rect mRectangle = new Rect();
|
||||
private String mDisplayMessage = "";
|
||||
private String mDisplayMessage2 = "";
|
||||
private int mDisplayMessageDuration = 0;
|
||||
private Timer mTimer = null;
|
||||
|
||||
public GameOverlay(Context context, AttributeSet attribs)
|
||||
{
|
||||
super( context, attribs );
|
||||
super(context, attribs);
|
||||
requestFocus();
|
||||
}
|
||||
|
||||
|
||||
public void initialize( VisibleTouchMap touchMap, boolean drawingEnabled, boolean fpsEnabled, boolean joystickAnimated )
|
||||
{
|
||||
mTouchMap = touchMap;
|
||||
mDrawingEnabled = drawingEnabled;
|
||||
mHatRefreshPeriod = joystickAnimated ? 3 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnalogChanged( float axisFractionX, float axisFractionY )
|
||||
|
||||
public void SetDisplayMessage(String Message, int Duratation)
|
||||
{
|
||||
if( mHatRefreshPeriod > 0 && mDrawingEnabled )
|
||||
if (Duratation >= mDisplayMessageDuration)
|
||||
{
|
||||
mDisplayMessage = Message;
|
||||
mDisplayMessageDuration = Duratation;
|
||||
if (mTimer != null)
|
||||
{
|
||||
mTimer.cancel();
|
||||
mTimer.purge();
|
||||
}
|
||||
if (Duratation == 0)
|
||||
{
|
||||
Duratation = 10;
|
||||
}
|
||||
TimerTask task = new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mDisplayMessage = "";
|
||||
mDisplayMessageDuration = 0;
|
||||
Timer CurrentTimer = mTimer;
|
||||
mTimer = null;
|
||||
CurrentTimer.cancel();
|
||||
CurrentTimer.purge();
|
||||
}
|
||||
|
||||
};
|
||||
mTimer = new Timer();
|
||||
mTimer.schedule(task, Duratation * 1000);
|
||||
}
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
public void SetDisplayMessage2(String Message)
|
||||
{
|
||||
mDisplayMessage2 = Message;
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnalogChanged(float axisFractionX, float axisFractionY)
|
||||
{
|
||||
if (mHatRefreshPeriod > 0 && mDrawingEnabled)
|
||||
{
|
||||
// Increment the count since last refresh
|
||||
mHatRefreshCount++;
|
||||
|
||||
|
||||
// If stick re-centered, always refresh
|
||||
if( axisFractionX == 0 && axisFractionY == 0 )
|
||||
if (axisFractionX == 0 && axisFractionY == 0)
|
||||
{
|
||||
mHatRefreshCount = 0;
|
||||
|
||||
}
|
||||
|
||||
// Update the analog stick assets and redraw if required
|
||||
if( mHatRefreshCount % mHatRefreshPeriod == 0 && mTouchMap != null
|
||||
&& mTouchMap.updateAnalog( axisFractionX, axisFractionY ) )
|
||||
if (mHatRefreshCount % mHatRefreshPeriod == 0 && mTouchMap != null
|
||||
&& mTouchMap.updateAnalog(axisFractionX, axisFractionY))
|
||||
{
|
||||
postInvalidate();
|
||||
}
|
||||
|
@ -60,40 +116,64 @@ public class GameOverlay extends View implements TouchController.OnStateChangedL
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onAutoHold( boolean autoHold, int index )
|
||||
public void onAutoHold(boolean autoHold, int index)
|
||||
{
|
||||
// Update the AutoHold mask, and redraw if required
|
||||
if( mTouchMap != null && mTouchMap.updateAutoHold( autoHold , index) )
|
||||
if (mTouchMap != null && mTouchMap.updateAutoHold(autoHold, index))
|
||||
{
|
||||
postInvalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged( int w, int h, int oldw, int oldh )
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh)
|
||||
{
|
||||
// Recompute skin layout geometry
|
||||
if( mTouchMap != null )
|
||||
mTouchMap.resize( w, h, DeviceUtil.getDisplayMetrics( this ) );
|
||||
super.onSizeChanged( w, h, oldw, oldh );
|
||||
if (mTouchMap != null)
|
||||
{
|
||||
mTouchMap.resize(w, h, DeviceUtil.getDisplayMetrics(this));
|
||||
}
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw( Canvas canvas )
|
||||
protected void onDraw(Canvas canvas)
|
||||
{
|
||||
if(canvas == null )
|
||||
if (canvas == null)
|
||||
{
|
||||
return;
|
||||
|
||||
if( mTouchMap != null && mDrawingEnabled )
|
||||
}
|
||||
|
||||
if (mTouchMap != null && mDrawingEnabled)
|
||||
{
|
||||
// Redraw the static buttons
|
||||
mTouchMap.drawButtons( canvas );
|
||||
|
||||
mTouchMap.drawButtons(canvas);
|
||||
|
||||
// Redraw the dynamic analog stick
|
||||
mTouchMap.drawAnalog( canvas );
|
||||
|
||||
mTouchMap.drawAnalog(canvas);
|
||||
|
||||
// Redraw the autoHold mask
|
||||
mTouchMap.drawAutoHold( canvas );
|
||||
mTouchMap.drawAutoHold(canvas);
|
||||
}
|
||||
|
||||
String txt = mDisplayMessage;
|
||||
if (txt.length() > 0 && mDisplayMessage2.length() > 0)
|
||||
{
|
||||
txt += " - ";
|
||||
}
|
||||
txt += mDisplayMessage2;
|
||||
if (txt.length() > 0)
|
||||
{
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setColor(Color.parseColor("#DDDDDD"));
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setTextSize(25);
|
||||
mPaint.setTextAlign(Paint.Align.CENTER);
|
||||
Typeface typeface = Typeface.create(Typeface.SANS_SERIF,
|
||||
Typeface.BOLD_ITALIC);
|
||||
mPaint.setTypeface(typeface);
|
||||
mPaint.getTextBounds(txt, 0, txt.length(), mRectangle);
|
||||
canvas.drawText(txt, Math.abs(canvas.getWidth() / 2), Math.abs((int) (canvas.getHeight() * 0.95)) - Math.abs(mRectangle.height()), mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,20 +10,18 @@
|
|||
****************************************************************************/
|
||||
package emu.project64.util;
|
||||
|
||||
import emu.project64.game.GameOverlay;
|
||||
import emu.project64.R;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* A small class to encapsulate the notification process for Mupen64PlusAE.
|
||||
*/
|
||||
public final class Notifier
|
||||
{
|
||||
private static Toast sToast = null;
|
||||
private static Runnable sToastMessager = null;
|
||||
private static Runnable sDisplayMessager = null;
|
||||
|
||||
/**
|
||||
|
@ -80,50 +78,27 @@ public final class Notifier
|
|||
Log.d("DisplayError", "Done");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop up a temporary message on the device.
|
||||
*
|
||||
* @param activity The activity to display from
|
||||
* @param message The message string to display.
|
||||
*/
|
||||
public static void showToast( Activity activity, String message )
|
||||
public static void showMessage( Activity activity, String message, int Duratation )
|
||||
{
|
||||
if( activity == null )
|
||||
return;
|
||||
|
||||
// Create a messaging task if it doesn't already exist
|
||||
if( sToastMessager == null )
|
||||
{
|
||||
final String ToastMessage = new String(message);
|
||||
final Activity ToastActivity = activity;
|
||||
|
||||
sToastMessager = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
// Just show the toast message
|
||||
if( sToast != null )
|
||||
sToast.show();
|
||||
|
||||
if( sToast != null )
|
||||
{
|
||||
// Toast exists, just change the text
|
||||
Notifier.sToast.setText( ToastMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Message short in duration, and at the bottom of the screen
|
||||
sToast = Toast.makeText( ToastActivity, ToastMessage, Toast.LENGTH_SHORT );
|
||||
sToast.setGravity( Gravity.BOTTOM, 0, 0 );
|
||||
}
|
||||
sToastMessager = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
activity.runOnUiThread( sToastMessager );
|
||||
GameOverlay overlay = (GameOverlay) activity.findViewById(R.id.gameOverlay);
|
||||
if (overlay == null)
|
||||
return;
|
||||
|
||||
overlay.SetDisplayMessage(message, Duratation);
|
||||
}
|
||||
|
||||
public static void showMessage2( Activity activity, String message )
|
||||
{
|
||||
if( activity == null )
|
||||
return;
|
||||
|
||||
GameOverlay overlay = (GameOverlay) activity.findViewById(R.id.gameOverlay);
|
||||
overlay.SetDisplayMessage2(message);
|
||||
}
|
||||
|
||||
private static Runnable runEmulationStopped = null;
|
||||
public static void EmulationStopped (Activity activity)
|
||||
{
|
||||
|
|
|
@ -122,14 +122,26 @@ void JavaBridge::DisplayError(const char * Message)
|
|||
}
|
||||
}
|
||||
|
||||
void JavaBridge::DisplayMessage(const char * Message)
|
||||
void JavaBridge::DisplayMessage(const char * Message, int DisplayTime)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
if (env)
|
||||
{
|
||||
jstring j_Message = env->NewStringUTF(Message);
|
||||
jmethodID midShowToast = env->GetStaticMethodID(m_NotifierClass, "showToast", "(Landroid/app/Activity;Ljava/lang/String;)V");
|
||||
env->CallStaticVoidMethod(m_NotifierClass, midShowToast,g_Activity,j_Message);
|
||||
jmethodID midshowMessage = env->GetStaticMethodID(m_NotifierClass, "showMessage", "(Landroid/app/Activity;Ljava/lang/String;I)V");
|
||||
env->CallStaticVoidMethod(m_NotifierClass, midshowMessage,g_Activity,j_Message,DisplayTime);
|
||||
env->DeleteLocalRef(j_Message);
|
||||
}
|
||||
}
|
||||
|
||||
void JavaBridge::DisplayMessage2(const char * Message)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
if (env)
|
||||
{
|
||||
jstring j_Message = env->NewStringUTF(Message);
|
||||
jmethodID midshowMessage2 = env->GetStaticMethodID(m_NotifierClass, "showMessage2", "(Landroid/app/Activity;Ljava/lang/String;)V");
|
||||
env->CallStaticVoidMethod(m_NotifierClass, midshowMessage2,g_Activity,j_Message);
|
||||
env->DeleteLocalRef(j_Message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,8 @@ public:
|
|||
|
||||
//Notification
|
||||
void DisplayError(const char * Message);
|
||||
void DisplayMessage(const char * Message);
|
||||
void DisplayMessage(const char * Message, int DisplayTime);
|
||||
void DisplayMessage2(const char * Message);
|
||||
void EmulationStopped(void);
|
||||
|
||||
private:
|
||||
|
|
|
@ -28,7 +28,7 @@ CNotificationImp & Notify(void)
|
|||
}
|
||||
|
||||
CNotificationImp::CNotificationImp() :
|
||||
m_NextMsg(0)
|
||||
m_NextMsg(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -81,26 +81,7 @@ void CNotificationImp::DisplayMessage(int DisplayTime, const char * Message) con
|
|||
{
|
||||
#ifdef ANDROID
|
||||
if (g_JavaBridge == NULL) { return; }
|
||||
|
||||
if (m_NextMsg > 0 || DisplayTime > 0)
|
||||
{
|
||||
time_t Now = time(NULL);
|
||||
if (DisplayTime == 0 && Now < m_NextMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (DisplayTime > 0)
|
||||
{
|
||||
m_NextMsg = Now + DisplayTime;
|
||||
}
|
||||
if (m_NextMsg == 0)
|
||||
{
|
||||
m_NextMsg = 0;
|
||||
}
|
||||
}
|
||||
m_Message[0] = Message;
|
||||
UpdateMessage();
|
||||
|
||||
g_JavaBridge->DisplayMessage(Message, DisplayTime);
|
||||
#else
|
||||
// ignore warning usage
|
||||
DisplayTime = DisplayTime;
|
||||
|
@ -112,9 +93,8 @@ void CNotificationImp::DisplayMessage2(const char * Message) const
|
|||
{
|
||||
#ifdef ANDROID
|
||||
if (g_JavaBridge == NULL) { return; }
|
||||
m_Message[1] = Message;
|
||||
|
||||
UpdateMessage();
|
||||
g_JavaBridge->DisplayMessage2(Message);
|
||||
#else
|
||||
// ignore warning usage
|
||||
Message = Message;
|
||||
|
@ -151,19 +131,3 @@ bool CNotificationImp::ProcessGuiMessages(void) const
|
|||
void CNotificationImp::ChangeFullScreen(void) const
|
||||
{
|
||||
}
|
||||
|
||||
void CNotificationImp::UpdateMessage(void) const
|
||||
{
|
||||
#ifdef ANDROID
|
||||
std::string message = m_Message[0];
|
||||
if (message.length() > 0 && m_Message[1].length())
|
||||
{
|
||||
message += " ";
|
||||
}
|
||||
message += m_Message[1];
|
||||
if (message.length() > 0)
|
||||
{
|
||||
g_JavaBridge->DisplayMessage(message.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -17,7 +17,7 @@ class CNotificationImp :
|
|||
{
|
||||
public:
|
||||
CNotificationImp(void);
|
||||
virtual ~CNotificationImp();
|
||||
virtual ~CNotificationImp();
|
||||
|
||||
//Error Messages
|
||||
void DisplayError(const char * Message) const;
|
||||
|
@ -44,10 +44,7 @@ private:
|
|||
CNotificationImp(const CNotificationImp&); // Disable copy constructor
|
||||
CNotificationImp& operator=(const CNotificationImp&); // Disable assignment
|
||||
|
||||
void UpdateMessage(void) const;
|
||||
|
||||
mutable time_t m_NextMsg;
|
||||
mutable std::string m_Message[2];
|
||||
};
|
||||
|
||||
CNotificationImp & Notify(void);
|
Loading…
Reference in New Issue