diff --git a/contrib/mobile/Android/res/layout/control_bar.xml b/contrib/mobile/Android/res/layout/control_bar.xml new file mode 100644 index 0000000000000000000000000000000000000000..89bc5c543d55b4409f06ee9adb75cf918fa34c37 --- /dev/null +++ b/contrib/mobile/Android/res/layout/control_bar.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + android:background="@android:color/black" + android:alpha=".50" + android:gravity="center" > + + <ImageButton + android:id="@+id/controlPrev" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@android:drawable/ic_media_previous" + android:contentDescription="previous" /> + + <ImageButton + android:id="@+id/controlPlay" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@android:drawable/ic_media_play" + android:contentDescription="play" /> + + <ImageButton + android:id="@+id/controlNext" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@android:drawable/ic_media_next" + android:contentDescription="next" /> + +</LinearLayout> \ No newline at end of file diff --git a/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java index 9800649e93bc761756464fac07561511be1b70e4..00d4d8e66d6150ef1fb11a6380110279a0c9cf63 100644 --- a/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java +++ b/contrib/mobile/Android/src/org/geuz/onelab/Gmsh.java @@ -13,7 +13,6 @@ public class Gmsh implements Parcelable { System.loadLibrary("Gmsh"); System.loadLibrary("GetDP"); System.loadLibrary("Onelab"); - } private native long init(String name); // Init Gmsh private native void loadFile(long ptr, String name); // load a file(OpenProjet) @@ -33,6 +32,7 @@ public class Gmsh implements Parcelable { public native int onelabCB(String action); // Call onelab public native void animationNext(); + public native void animationPrev(); /** Java CLASS **/ private long ptr; diff --git a/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java index 89b384b594ff53d220acf617c2bf5f699a73651f..c49fe250625cb22821e44fb34b2fe34b7ee4b7fb 100644 --- a/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java +++ b/contrib/mobile/Android/src/org/geuz/onelab/MainActivity.java @@ -4,8 +4,6 @@ import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.Timer; -import java.util.TimerTask; import android.app.ActionBar; import android.app.Activity; @@ -40,7 +38,6 @@ public class MainActivity extends Activity{ private OptionsFragment _optionsFragment; private ArrayList<String> _errors = new ArrayList<String>(); private Dialog _errorDialog; - private Timer _animation; public MainActivity() { } @@ -87,6 +84,7 @@ public class MainActivity extends Activity{ @Override protected void onSaveInstanceState(Bundle outState) { + outState.putBoolean("Compute", _compute); super.onSaveInstanceState(outState); } @@ -101,11 +99,14 @@ public class MainActivity extends Activity{ _runStopMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); MenuItem shareMenuItem = menu.add(R.string.menu_share); shareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - MenuItem playPauseMenuItem = menu.add("Play animation"); - playPauseMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); return true; } @Override + public boolean onMenuOpened(int featureId, Menu menu) { + _modelFragment.postDelay(); + return super.onMenuOpened(featureId, menu); + } + @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if (item.getTitle().equals(getString(R.string.menu_parameters))) { Intent intent = new Intent(this, OptionsActivity.class); @@ -115,6 +116,7 @@ public class MainActivity extends Activity{ _modelFragment.requestRender(); } else if(item.getTitle().equals(getString(R.string.menu_run))){ + if(_modelFragment != null) _modelFragment.hideControlBar(); new Run().execute(); } else if(item.getTitle().equals(getString(R.string.menu_stop))){ @@ -144,33 +146,6 @@ public class MainActivity extends Activity{ shareIntent.setType("image/jpeg"); startActivity(Intent.createChooser(shareIntent, getString(R.string.title_share))); } - } - else if(item.getTitle().equals("Play animation")) { - if(this._compute) { - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); - _errorDialog = dialogBuilder.setTitle("Can't start animation") - .setMessage("The computing have to be finished before you can play animation.") - .setPositiveButton("OK", new DialogInterface.OnClickListener() { - - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }) - .show(); - } - else { - item.setTitle("Stop animation"); - _animation = new Timer(); - _animation.schedule(new TimerTask() { - public void run() { - _gmsh.animationNext(); - _modelFragment.requestRender(); - } }, 2000, 1); - } - } - else if(item.getTitle().equals("Stop animation")) { - item.setTitle("Play animation"); - _animation.cancel(); } else if(item.getItemId() == android.R.id.home) { if(this._compute) { @@ -275,6 +250,7 @@ public class MainActivity extends Activity{ @Override public void onLowMemory() { + if(!_compute) return; _gmsh.onelabCB("stop"); Toast.makeText(this, "Low memory !!! computing is going to stop", Toast.LENGTH_LONG).show(); super.onLowMemory(); @@ -282,9 +258,14 @@ public class MainActivity extends Activity{ @Override public void onTrimMemory(int level) { + if(!_compute) return; if(level == Activity.TRIM_MEMORY_COMPLETE){ _gmsh.onelabCB("stop"); notifyInterruptComputing(); + _notify = false; + } + else if(level == Activity.TRIM_MEMORY_COMPLETE) { + // TODO } super.onTrimMemory(level); } diff --git a/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java b/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java index 77fe46fc31a7618febfc511555c5f3efb485b1f6..826ea9dbad6fd0accb43c0a8b37590247ca5a19d 100644 --- a/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java +++ b/contrib/mobile/Android/src/org/geuz/onelab/ModelFragment.java @@ -3,15 +3,24 @@ package org.geuz.onelab; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.util.Timer; +import java.util.TimerTask; import android.app.Fragment; import android.graphics.Bitmap; import android.opengl.GLSurfaceView; import android.os.Bundle; +import android.os.Handler; +import android.view.GestureDetector; +import android.view.GestureDetector.OnGestureListener; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; @@ -19,10 +28,16 @@ import android.widget.TextView; public class ModelFragment extends Fragment{ - Gmsh _gmsh; - mGLSurfaceView _glView; - TextView _progress; - LinearLayout _progressLayout; + private Gmsh _gmsh; + private mGLSurfaceView _glView; + private TextView _progress; + private LinearLayout _progressLayout; + private LinearLayout _controlBarLayout; + private GestureDetector _gestureListener; + private Timer _animation; + private Handler _hideDelay; + + final Runnable hideControlsRunnable = new Runnable() {public void run() {hideControlBar();}}; public static ModelFragment newInstance(Gmsh g) { ModelFragment fragment = new ModelFragment(); @@ -52,6 +67,50 @@ public class ModelFragment extends Fragment{ _glView.setRenderer(renderer); _glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); _glView.requestRender(); + _hideDelay = new Handler(); + this.postDelay(); + _gestureListener = new GestureDetector(getActivity(), new OnGestureListener() { + public boolean onSingleTapUp(MotionEvent e) { + if(View.VISIBLE == _controlBarLayout.getVisibility()) + hideControlBar(); + else + showControlBar(); + return true; + } + + public void onShowPress(MotionEvent e) { + // TODO Auto-generated method stub + + } + + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + // TODO Auto-generated method stub + return false; + } + + public void onLongPress(MotionEvent e) { + // TODO Auto-generated method stub + + } + + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, + float velocityY) { + // TODO Auto-generated method stub + return false; + } + + public boolean onDown(MotionEvent e) { + // TODO Auto-generated method stub + return false; + } + }); + _glView.setOnTouchListener(new View.OnTouchListener() { + + public boolean onTouch(View v, MotionEvent event) { + return _gestureListener.onTouchEvent(event); + } + }); glViewLayout.addView(_glView); _progressLayout = new LinearLayout(container.getContext()); ProgressBar bar = new ProgressBar(container.getContext()); @@ -70,8 +129,74 @@ public class ModelFragment extends Fragment{ RelativeLayout.LayoutParams.WRAP_CONTENT); layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); glViewLayout.addView(_progressLayout, layoutParams); + _controlBarLayout = (LinearLayout) getActivity().getLayoutInflater().inflate(R.layout.control_bar, null); + ImageButton playPauseButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPlay); + playPauseButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + postDelay(); + if(((ImageButton)v).getContentDescription().equals("play")) { + ((ImageButton)v).setContentDescription("pause"); + ((ImageButton)v).setImageResource(android.R.drawable.ic_media_pause); + _animation = new Timer(); + _animation.schedule(new TimerTask() { + public void run() { + _gmsh.animationNext(); + requestRender(); + } }, 0, 500); + } + else { + ((ImageButton)v).setContentDescription("play"); + ((ImageButton)v).setImageResource(android.R.drawable.ic_media_play); + _animation.cancel(); + } + } + }); + ImageButton nextButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlNext); + nextButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + postDelay(); + _gmsh.animationNext(); + requestRender(); + } + }); + ImageButton prevButton = (ImageButton)_controlBarLayout.findViewById(R.id.controlPrev); + prevButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + postDelay(); + _gmsh.animationPrev(); + requestRender(); + } + }); + layoutParams = new RelativeLayout.LayoutParams( + RelativeLayout.LayoutParams.MATCH_PARENT, + RelativeLayout.LayoutParams.WRAP_CONTENT); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); + glViewLayout.addView(_controlBarLayout, layoutParams); return rootView; } + public void postDelay(int delay) { + _hideDelay.removeCallbacks(hideControlsRunnable); + _hideDelay.postDelayed(hideControlsRunnable, delay); + } + public void postDelay() { + this.postDelay(6000); + } + public void showControlBar() { + if(getActivity() == null) return; + this.postDelay(); + getActivity().getActionBar().show(); + Animation bottomUp = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in); + _controlBarLayout.setVisibility(View.VISIBLE); + _controlBarLayout.startAnimation(bottomUp); + } + public void hideControlBar() { + if(getActivity() == null) return; + _hideDelay.removeCallbacks(hideControlsRunnable); + getActivity().getActionBar().hide(); + Animation bottomDown = AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out); + _controlBarLayout.startAnimation(bottomDown); + _controlBarLayout.setVisibility(View.INVISIBLE); + } public void showProgress(String progress) { _progressLayout.setAlpha(1); _progress.setText(progress); diff --git a/contrib/mobile/androidGModel.cpp b/contrib/mobile/androidGModel.cpp index 2d8e3de46ab013644473d8e98e0ff71d689b623d..606626e84096eda1bb1b3bee54b9e5213b76efba 100644 --- a/contrib/mobile/androidGModel.cpp +++ b/contrib/mobile/androidGModel.cpp @@ -309,4 +309,9 @@ JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationNext { animation_next(); } +JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationPrev + (JNIEnv *, jobject) +{ + animation_prev(); +} } diff --git a/contrib/mobile/androidGModel.h b/contrib/mobile/androidGModel.h index 7497acd9288d7b370f251d7ba85ca61f571acf8f..043816e97112d3ba65f6faf89cff61ac3df3108a 100644 --- a/contrib/mobile/androidGModel.h +++ b/contrib/mobile/androidGModel.h @@ -145,6 +145,14 @@ JNIEXPORT jint JNICALL Java_org_geuz_onelab_Gmsh_onelabCB JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationNext (JNIEnv *, jobject); +/* + * Class: org_geuz_onelab_Gmsh + * Method: animationPrev + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_animationPrev + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif diff --git a/contrib/mobile/drawContext.cpp b/contrib/mobile/drawContext.cpp index a9e361165079da1ec4e1454ae4bce320c097c878..58eea35343783a6debbcf09732cb05f1c97e903c 100644 --- a/contrib/mobile/drawContext.cpp +++ b/contrib/mobile/drawContext.cpp @@ -693,7 +693,24 @@ void animation_next() { if(step < 0) step = numSteps - 1; if(step > numSteps - 1) step = 0; } - Msg::Info("animation: step%d nextstep%d totalstep%d", p->getOptions()->timeStep, step, p->getData()->getNumTimeSteps()); + p->getOptions()->timeStep = step; + p->setChanged(true); + } + } +} +void animation_prev() { + for(unsigned int i = 0; i < PView::list.size(); i++){ + PView * p = PView::list[i]; + if(p->getOptions()->visible){ + // skip empty steps + int step = (int)p->getOptions()->timeStep - 1; + int numSteps = (int)p->getData()->getNumTimeSteps(); + for(int j = 0; j < numSteps; j++){ + if(p->getData()->hasTimeStep(step)) break; + else step -= 1; + if(step < 0) step = numSteps - 1; + if(step > numSteps - 1) step = 0; + } p->getOptions()->timeStep = step; p->setChanged(true); } diff --git a/contrib/mobile/drawContext.h b/contrib/mobile/drawContext.h index befc96db43d4b67a365db7bf48d4bd8b59d5bcd8..e69035fb0a942a188334e752f726a6cea44c67fe 100644 --- a/contrib/mobile/drawContext.h +++ b/contrib/mobile/drawContext.h @@ -22,6 +22,7 @@ void drawArray(VertexArray *va, int type, bool useColorArray=false, bool useNormalArray=false); int onelab_cb(std::string); void animation_next(); +void animation_prev(); class drawContext{ private: