Migrate to androidx.

Add Drawer and Settings UIs.
This commit is contained in:
dgis 2018-12-07 22:57:35 +00:00
parent 2fadb7d2d7
commit 05e9e448b5
29 changed files with 928 additions and 77 deletions

21
ReadMe.txt Normal file
View file

@ -0,0 +1,21 @@
ABOUT
This project ports the Windows application Emu48 written in C to Android.
It uses the Android NDK. The former Emu48 source code remains untouch because a thin win32 emulation layer above Linux/NDK!
This win32 layer will allow to update easily from the original source code.
NOT WORKING
- Sound
- Disassembler
- Debugger
- Macro
- Infrared Printer
- Serial Ports (Wire or Ir)
TODO
- Bitmap corruption when touching the buttons
- Android UI Settings
- Sound
DONE
- Bug Red and Blue seems inverted.
- Multitouch

View file

@ -8,7 +8,7 @@ android {
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
@ -30,9 +30,9 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
implementation 'com.google.android.material:material:1.1.0-alpha01'
// testImplementation 'junit:junit:4.12'
// androidTestImplementation 'com.android.support.test:runner:1.0.2'
// androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

View file

@ -10,10 +10,12 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:resizeableActivity="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -21,6 +23,24 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:label="@string/title_activity_settings"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.regis.cosnier.emu48.MainActivity"/>
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>

View file

@ -2,7 +2,7 @@
// PCH.H
//
#define DEBUG_DISPLAY 1
//#define DEBUG_DISPLAY 1
#define _WIN32_IE 0x0200
#define _CRT_SECURE_NO_DEPRECATE

View file

@ -821,8 +821,6 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc
int destinationHeight = androidBitmapInfo.height;
//https://softwareengineering.stackexchange.com/questions/148123/what-is-the-algorithm-to-copy-a-region-of-one-bitmap-into-a-region-in-another
// float src_dx = wDest / wSrc;
// float src_dy = hDest / hSrc;
float src_dx = (float)wSrc / (float)wDest;
float src_dy = (float)hSrc / (float)hDest;
float src_maxx = xSrc + wSrc;
@ -855,9 +853,9 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc
case 1:
if(palPalEntry) {
BYTE colorIndex = sourcePixel[0];
destinationPixel[0] = palPalEntry[colorIndex].peRed;
destinationPixel[0] = palPalEntry[colorIndex].peBlue;
destinationPixel[1] = palPalEntry[colorIndex].peGreen;
destinationPixel[2] = palPalEntry[colorIndex].peBlue;
destinationPixel[2] = palPalEntry[colorIndex].peRed;
destinationPixel[3] = 255;
} else {
destinationPixel[0] = sourcePixel[0];
@ -867,9 +865,9 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc
}
break;
case 3:
destinationPixel[0] = sourcePixel[0];
destinationPixel[0] = sourcePixel[2];
destinationPixel[1] = sourcePixel[1];
destinationPixel[2] = sourcePixel[2];
destinationPixel[2] = sourcePixel[0];
destinationPixel[3] = 255;
break;
case 4:

View file

@ -0,0 +1,110 @@
package com.regis.cosnier.emu48;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
/**
* A {@link PreferenceActivity} which implements and proxies the necessary calls
* to be used with AppCompat.
*/
public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate;
@Override
protected void onCreate(Bundle savedInstanceState) {
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getDelegate().onPostCreate(savedInstanceState);
}
public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}
public void setSupportActionBar(@Nullable Toolbar toolbar) {
getDelegate().setSupportActionBar(toolbar);
}
@Override
public MenuInflater getMenuInflater() {
return getDelegate().getMenuInflater();
}
@Override
public void setContentView(@LayoutRes int layoutResID) {
getDelegate().setContentView(layoutResID);
}
@Override
public void setContentView(View view) {
getDelegate().setContentView(view);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().setContentView(view, params);
}
@Override
public void addContentView(View view, ViewGroup.LayoutParams params) {
getDelegate().addContentView(view, params);
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
protected void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
protected void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
public void invalidateOptionsMenu() {
getDelegate().invalidateOptionsMenu();
}
private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}
}

View file

@ -1,20 +1,26 @@
package com.regis.cosnier.emu48;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.ViewGroup;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private static final int INTENT_SETTINGS = 1;
private MainScreenView mainScreenView;
@Override
@ -33,11 +39,32 @@ public class MainActivity extends AppCompatActivity {
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
mainScreenView = new MainScreenView(this); //, currentProject);
ViewGroup mainScreenContainer = (ViewGroup)findViewById(R.id.main_screen_container);
mainScreenContainer.addView(mainScreenView, 0);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
@ -54,12 +81,38 @@ public class MainActivity extends AppCompatActivity {
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
startActivityForResult(new Intent(this, SettingsActivity.class), INTENT_SETTINGS);
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
protected void onDestroy() {

View file

@ -7,22 +7,15 @@ import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewCompat;
import androidx.core.view.ViewCompat;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.SurfaceView;
import android.view.View;
import android.widget.OverScroller;
import java.util.HashMap;
import java.util.Map;
public class MainScreenView extends SurfaceView {
@ -140,33 +133,29 @@ public class MainScreenView extends SurfaceView {
@SuppressLint("ClickableViewAccessibility")
public boolean onTouchEvent(MotionEvent event) {
// Let the ScaleGestureDetector inspect all events.
// boolean retValScaleDetector = mScaleDetector.onTouchEvent(event);
// boolean retValGestureDetector = mGestureDetector.onTouchEvent(event);
boolean retVal = false; //retValGestureDetector || retValScaleDetector;
int touchCount = event.getPointerCount();
if(touchCount == 1) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//Log.d(TAG, "ACTION_DOWN count: " + touchCount + ", PanPrevious: " + mPanPrevious.toString());
NativeLib.buttonDown((int)((event.getX(0) - screenOffsetX) / screenScale), (int)((event.getY(0) - screenOffsetY) / screenScale));
break;
int actionIndex = event.getActionIndex();
int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
//Log.d(TAG, "ACTION_DOWN/ACTION_POINTER_DOWN count: " + touchCount + ", actionIndex: " + actionIndex);
NativeLib.buttonDown((int)((event.getX(actionIndex) - screenOffsetX) / screenScale), (int)((event.getY(actionIndex) - screenOffsetY) / screenScale));
break;
// case MotionEvent.ACTION_MOVE:
// break;
case MotionEvent.ACTION_UP:
NativeLib.buttonUp((int)((event.getX(0) - screenOffsetX) / screenScale), (int)((event.getY(0) - screenOffsetY) / screenScale));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
//Log.d(TAG, "ACTION_UP/ACTION_POINTER_UP count: " + touchCount + ", actionIndex: " + actionIndex);
NativeLib.buttonUp((int)((event.getX(actionIndex) - screenOffsetX) / screenScale), (int)((event.getY(actionIndex) - screenOffsetY) / screenScale));
break;
// case MotionEvent.ACTION_CANCEL:
// break;
// case MotionEvent.ACTION_OUTSIDE:
// break;
default:
}
return true;
default:
}
return retVal || super.onTouchEvent(event);
return true;
}
// @Override
@ -216,7 +205,7 @@ public class MainScreenView extends SurfaceView {
float imageSizeY = bitmapMainScreen.getHeight();
if(imageSizeX > 0 && imageSizeY > 0 && viewWidth > 0.0f && viewHeight > 0.0f) {
// Find the scale factor and the translate offset to fit and to center the vectors in the view bounds.
// Find the scale factor and the translate offset to fit and to center the image in the view bounds.
float translateX, translateY, scale;
float viewRatio = (float)viewHeight / (float)viewWidth;
float imageRatio = imageSizeY / imageSizeX;
@ -235,13 +224,12 @@ public class MainScreenView extends SurfaceView {
screenOffsetY = translateY;
}
NativeLib.resize(viewWidth, viewHeight);
//NativeLib.resize(viewWidth, viewHeight);
}
@Override
protected void onDraw(Canvas canvas) {
//Log.d(TAG, "onDraw() mIsScaling: " + mIsScaling + ", mIsPanning: " + mIsPanning + ", mIsFlinging: " + mIsFlinging);
//NativeLib.draw();
canvas.save();
canvas.translate(screenOffsetX, screenOffsetY);
canvas.scale(screenScale, screenScale);

View file

@ -12,7 +12,7 @@ public class NativeLib {
public static native void start(AssetManager mgr, Bitmap bitmapMainScreen, MainScreenView view);
public static native void stop();
public static native void resize(int width, int height);
//public static native void resize(int width, int height);
public static native void draw();
public static native void buttonDown(int x, int y);
public static native void buttonUp(int x, int y);

View file

@ -0,0 +1,167 @@
package com.regis.cosnier.emu48;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener
{
private static final String androidns="http://schemas.android.com/apk/res/android";
private static final String appdns="http://schemas.android.com/apk/res-auto";
private SeekBar mSeekBar;
private TextView mSplashText,mValueText;
private Context mContext;
private String mDialogMessage, mSuffix, mSuffixes;
private int mDefault, mMin, mMax, mValue = 0;
private float mDisplayScale = 1.0f;
private String mDisplayFormat;
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context,attrs);
mContext = context;
mDialogMessage = getAttributeValue(attrs, androidns, "dialogMessage");
mValue = mDefault = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
mDisplayScale = attrs.getAttributeFloatValue(appdns, "displayScale", 1.0f);
mSuffix = getAttributeValue(attrs, appdns, "suffix");
mSuffixes = getAttributeValue(attrs, appdns, "suffixes");
mDisplayFormat = attrs.getAttributeValue(appdns, "displayFormat");
mMin = attrs.getAttributeIntValue(appdns, "min", 0);
mMax = attrs.getAttributeIntValue(androidns, "max", 100);
}
private String getAttributeValue(AttributeSet attrs, String namespace, String name) {
String attributeValue = attrs.getAttributeValue(namespace, name);
String result = attributeValue;
if(attributeValue != null && attributeValue.length() > 1 && attributeValue.charAt(0) == '@') {
try {
int id = Integer.parseInt(attributeValue.substring(1));
result = mContext.getString(id);
} catch (NumberFormatException e) {}
}
return result;
}
@Override
protected View onCreateDialogView() {
LinearLayout layout = new LinearLayout(mContext);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setPadding(6, 6, 6, 6);
mSplashText = new TextView(mContext);
if (mDialogMessage != null)
mSplashText.setText(mDialogMessage);
layout.addView(mSplashText);
mValueText = new TextView(mContext);
mValueText.setGravity(Gravity.CENTER_HORIZONTAL);
mValueText.setTextSize(32);
layout.addView(mValueText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
mSeekBar = new SeekBar(mContext);
mSeekBar.setOnSeekBarChangeListener(this);
layout.addView(mSeekBar, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
if (shouldPersist())
mValue = getPersistedInt(mDefault);
mSeekBar.setMax(mMax - mMin);
mSeekBar.setProgress(mValue - mMin);
return layout;
}
@Override
protected void onBindDialogView(View v) {
super.onBindDialogView(v);
mSeekBar.setMax(mMax - mMin);
mSeekBar.setProgress(mValue - mMin);
}
@Override
protected void onSetInitialValue(boolean restore, Object defaultValue)
{
super.onSetInitialValue(restore, defaultValue);
if (restore)
mValue = shouldPersist() ? getPersistedInt(mDefault) : 0;
else
mValue = (Integer)defaultValue;
}
public void setValueSummary()
{
setSummary(getValueSummary());
}
public String getValueSummary()
{
return getValueSummary(mValue);
}
public String getValueSummary(int value)
{
String textValue;
if(mDisplayFormat != null)
textValue = String.format(mDisplayFormat, value * mDisplayScale);
else if(mDisplayScale != 1.0f)
textValue = String.valueOf(value * mDisplayScale);
else
textValue = String.valueOf(value);
if(value * mDisplayScale > 1.0f) {
if(mSuffixes != null)
textValue += " " + mSuffixes;
else if(mSuffix != null)
textValue += " " + mSuffix;
} else if(mSuffix != null)
textValue += " " + mSuffix;
return textValue;
}
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch)
{
int theValue = mMin + value;
String textValue = getValueSummary(theValue);
mValueText.setText(textValue);
if (shouldPersist())
persistInt(theValue);
//mValue = theValue;
//callChangeListener(Integer.valueOf(mMin + value));
}
public void onStartTrackingTouch(SeekBar seek) {}
public void onStopTrackingTouch(SeekBar seek) {}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
// save your new password here
mValue = mMin + mSeekBar.getProgress();
callChangeListener(Integer.valueOf(mValue));
break;
default:
// do something else...
break;
}
}
public void setMin(int min) { mMin = min; }
public int getMin() { return mMin; }
public void setMax(int max) { mMax = max; }
public int getMax() { return mMax; }
public void setProgress(int progress) {
mValue = progress;
if (mSeekBar != null)
mSeekBar.setProgress(progress - mMin);
}
public int getProgress() { return mValue; }
}

View file

@ -0,0 +1,203 @@
package com.regis.cosnier.emu48;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.MenuItem;
import androidx.appcompat.app.ActionBar;
import androidx.core.app.NavUtils;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
* settings are split by category, with category headers shown to the left of
* the list of settings.
* <p>
* See <a href="http://developer.android.com/design/patterns/settings.html">
* Android Design: Settings</a> for design guidelines and the <a
* href="http://developer.android.com/guide/topics/ui/settings.html">Settings
* API Guide</a> for more information on developing a Settings UI.
*/
public class SettingsActivity extends AppCompatPreferenceActivity {
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference.setSummary(
index >= 0
? listPreference.getEntries()[index]
: null);
} else {
// For all other preferences, set the summary to the value's
// simple string representation.
preference.setSummary(stringValue);
}
return true;
}
};
/**
* Helper method to determine if the device has an extra-large screen. For
* example, 10" tablets are extra-large.
*/
private static boolean isXLargeTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToStringValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(preference.getContext());
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, sharedPreferences.getString(preference.getKey(), ""));
}
/**
* Binds a preference's summary to its value. More specifically, when the
* preference's value is changed, its summary (line of text below the
* preference title) is updated to reflect the value. The summary is also
* immediately updated upon calling this method. The exact display format is
* dependent on the type of preference.
*
* @see #sBindPreferenceSummaryToValueListener
*/
private static void bindPreferenceSummaryToIntValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(preference.getContext());
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, sharedPreferences.getInt(preference.getKey(), 0));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
// Show the Up button in the action bar.
actionBar.setDisplayHomeAsUpEnabled(true);
}
getFragmentManager().beginTransaction().replace(android.R.id.content, new GeneralPreferenceFragment()).commit();
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
if (!super.onMenuItemSelected(featureId, item)) {
NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onMenuItemSelected(featureId, item);
}
/**
* {@inheritDoc}
*/
@Override
public boolean onIsMultiPane() {
return isXLargeTablet(this);
}
// /**
// * {@inheritDoc}
// */
// @Override
// @TargetApi(Build.VERSION_CODES.HONEYCOMB)
// public void onBuildHeaders(List<Header> target) {
// loadHeadersFromResource(R.xml.pref_headers, target);
// }
/**
* This method stops fragment injection in malicious applications.
* Make sure to deny any unknown fragments here.
*/
protected boolean isValidFragment(String fragmentName) {
return PreferenceFragment.class.getName().equals(fragmentName)
|| GeneralPreferenceFragment.class.getName().equals(fragmentName)
// || DataSyncPreferenceFragment.class.getName().equals(fragmentName)
// || NotificationPreferenceFragment.class.getName().equals(fragmentName)
;
}
/**
* This fragment shows general preferences only. It is used when the
* activity is showing a two-pane settings UI.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
// updated to reflect the new value, per the Android Design
// guidelines.
// bindPreferenceSummaryToStringValue(findPreference("settings_input"));
// bindPreferenceSummaryToIntValue(findPreference("settings_audio_input"));
// bindPreferenceSummaryToStringValue(findPreference("settings_sample_rate"));
// bindPreferenceSummaryToStringValue(findPreference("settings_fft_size"));
// bindPreferenceSummaryToIntValue(findPreference("settings_volume_scale"));
bindPreferenceSummaryToIntValue(findPreference("settings_tempo"));
// bindPreferenceSummaryToIntValue(findPreference("settings_intensity_minimum"));
// bindPreferenceSummaryToIntValue(findPreference("settings_translation"));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
startActivity(new Intent(getActivity(), SettingsActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
}

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z" />
</vector>

View file

@ -0,0 +1,9 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="135"
android:centerColor="#009688"
android:endColor="#00695C"
android:startColor="#4DB6AC"
android:type="linear" />
</shape>

View file

@ -1,34 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
tools:context=".MainActivity"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<android.support.design.widget.AppBarLayout
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
android:layout_height="match_parent" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:visibility="gone"
app:srcCompat="@android:drawable/ic_dialog_email" />
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</android.support.design.widget.CoordinatorLayout>
</androidx.drawerlayout.widget.DrawerLayout>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:visibility="gone"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_screen_container"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
@ -10,4 +10,4 @@
tools:showIn="@layout/activity_main">
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:gravity="bottom"
android:orientation="vertical"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/nav_header_desc"
android:paddingTop="@dimen/nav_header_vertical_spacing"
app:srcCompat="@mipmap/ic_launcher_round" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@string/nav_header_title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nav_header_subtitle" />
</LinearLayout>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_camera"
android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</group>
<item android:title="Communicate">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="Send" />
</menu>
</item>
</menu>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- http://stackoverflow.com/questions/3441396/defining-custom-attrs -->
<declare-styleable name="SeekBarPreference">
<attr name="min" format="integer" />
<attr name="displayScale" format="float" />
<attr name="displayFormat" format="string" />
<attr name="suffix" format="string" />
<attr name="suffixes" format="string" />
</declare-styleable>
</resources>

View file

@ -1,3 +1,8 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>

View file

@ -1,4 +1,10 @@
<resources>
<string name="app_name">Emu48</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="nav_header_title">Android Studio</string>
<string name="nav_header_subtitle">android.studio@android.com</string>
<string name="nav_header_desc">Navigation header</string>
<string name="action_settings">Settings</string>
<string name="title_activity_settings">Settings</string>
</resources>

View file

@ -0,0 +1,95 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:asp="http://schemas.android.com/apk/res-auto">
<!--<ListPreference-->
<!--android:key="settings_input"-->
<!--android:defaultValue="0"-->
<!--android:title="@string/settings_input_title"-->
<!--android:entries="@array/settings_input_list_titles"-->
<!--android:entryValues="@array/settings_input_list_values"-->
<!--android:negativeButtonText="@null"-->
<!--android:positiveButtonText="@null"-->
<!--/>-->
<!--<ListPreference-->
<!--android:key="settings_audio_engine"-->
<!--android:defaultValue="0"-->
<!--android:title="@string/settings_audio_engine_title"-->
<!--android:entries="@array/settings_audio_engine_list_titles"-->
<!--android:entryValues="@array/settings_audio_engine_list_values"-->
<!--android:negativeButtonText="@null"-->
<!--android:positiveButtonText="@null"-->
<!--/>-->
<!--<com.regis.cosnier.emu48.AudioDeviceSpinnerPreference-->
<!--android:key="settings_audio_input"-->
<!--android:defaultValue="0"-->
<!--android:title="@string/settings_audio_input_title"-->
<!--android:dialogMessage="@string/settings_audio_input_title_dialog"-->
<!--/>-->
<!--<ListPreference-->
<!--android:key="settings_sample_rate"-->
<!--android:defaultValue="48000"-->
<!--android:title="@string/settings_sample_rate_title"-->
<!--android:entries="@array/settings_sample_rate_list_titles"-->
<!--android:entryValues="@array/settings_sample_rate_list_values"-->
<!--android:negativeButtonText="@null"-->
<!--android:positiveButtonText="@null"-->
<!--/>-->
<!--<ListPreference-->
<!--android:key="settings_fft_size"-->
<!--android:defaultValue="1024"-->
<!--android:title="@string/settings_fft_size_title"-->
<!--android:entries="@array/settings_fft_size_list_titles"-->
<!--android:entryValues="@array/settings_fft_size_list_values"-->
<!--android:negativeButtonText="@null"-->
<!--android:positiveButtonText="@null"-->
<!--/>-->
<!--<com.regis.cosnier.emu48.SeekBarPreference-->
<!--android:key="settings_volume_scale"-->
<!--android:title="@string/settings_volume_scale_title"-->
<!--android:dialogMessage="@string/settings_volume_scale_title"-->
<!--android:defaultValue="0"-->
<!--app:suffix="@string/settings_volume_scale_suffix"-->
<!--app:suffixes="@string/settings_volume_scale_suffixes"-->
<!--app:min="-1000"-->
<!--android:max="1000"-->
<!--/>-->
<SwitchPreference
android:key="settings_frequency_logarithmic_scale"
android:title="settings_frequency_logarithmic_scale_title"
android:defaultValue="true" />
<com.regis.cosnier.emu48.SeekBarPreference
android:key="settings_tempo"
android:title="settings_tempo_title"
android:dialogMessage="settings_tempo_title"
android:defaultValue="96"
app:min="20"
android:max="200"
/>
<!--<com.regis.cosnier.emu48.SeekBarPreference-->
<!--android:key="settings_intensity_minimum"-->
<!--android:title="@string/settings_intensity_minimum_title"-->
<!--android:dialogMessage="@string/settings_intensity_minimum_title"-->
<!--android:defaultValue="20"-->
<!--app:min="1"-->
<!--android:max="90"-->
<!--/>-->
<!--<com.regis.cosnier.emu48.SeekBarPreference-->
<!--android:key="settings_translation"-->
<!--android:title="@string/settings_translation_title"-->
<!--android:dialogMessage="@string/settings_translation_title"-->
<!--android:defaultValue="0"-->
<!--app:min="-60"-->
<!--android:max="60"-->
<!--/>-->
</PreferenceScreen>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>

View file

@ -6,6 +6,8 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit