Include ColorPickerPreference as local library

This library has not been migrated to a newer repository, and is no longer available for use externally.
This commit is contained in:
Trevor Slocum 2024-10-08 21:04:54 -07:00
parent a29a483b3c
commit 980115a5bc
26 changed files with 2407 additions and 185 deletions

1
ColorPickerPreference/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) 2011 Sergey Margaritov & Daniel Nilsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View file

@ -0,0 +1,48 @@
apply plugin: 'com.android.library'
ext {
bintrayRepo = 'android-ColorPickerPreference'
bintrayName = 'android-colorpickerpreference'
publishedGroupId = 'net.margaritov.preference.colorpicker.ColorPickerPreference'
libraryName = 'ColorPickerPreference'
artifact = 'ColorPickerPreference'
libraryDescription = 'ColorPickerPreference for android to create color picker in preferences. Project created as Library'
siteUrl = 'https://github.com/attenzione/android-ColorPickerPreference'
gitUrl = 'https://github.com/attenzione/android-ColorPickerPreference.git'
libraryVersion = '1.0.0'
developerId = 'attenzione'
developerName = 'Sergey Margaritov'
developerEmail = 'github@semar.in'
licenseName = 'The Apache Software License, Version 2.0'
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
allLicenses = ["Apache-2.0"]
}
android {
compileSdkVersion 34
namespace 'net.margaritov.preference.colorpicker'
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation "androidx.preference:preference:1.1.0"
}

View file

@ -0,0 +1,34 @@
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

View file

@ -0,0 +1,13 @@
package net.margaritov.colorpickerpreference;
import android.app.Application;
import android.test.ApplicationTestCase;
/**
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.margaritov.preference.colorpicker">
<uses-sdk android:minSdkVersion="7" />
</manifest>

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2010 Daniel Nilsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.margaritov.preference.colorpicker;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
/**
* This drawable that draws a simple white and gray chessboard pattern.
* It's pattern you will often see as a background behind a
* partly transparent image in many applications.
*
* @author Daniel Nilsson
*/
public class AlphaPatternDrawable extends Drawable {
private int mRectangleSize = 10;
private Paint mPaint = new Paint();
private Paint mPaintWhite = new Paint();
private Paint mPaintGray = new Paint();
private int numRectanglesHorizontal;
private int numRectanglesVertical;
/**
* Bitmap in which the pattern will be cahched.
*/
private Bitmap mBitmap;
public AlphaPatternDrawable(int rectangleSize) {
mRectangleSize = rectangleSize;
mPaintWhite.setColor(0xffffffff);
mPaintGray.setColor(0xffcbcbcb);
}
@Override
public void draw(Canvas canvas) {
canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
}
@Override
public int getOpacity() {
return 0;
}
@Override
public void setAlpha(int alpha) {
throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
}
@Override
public void setColorFilter(ColorFilter cf) {
throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
int height = bounds.height();
int width = bounds.width();
numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
generatePatternBitmap();
}
/**
* This will generate a bitmap with the pattern
* as big as the rectangle we were allow to draw on.
* We do this to chache the bitmap so we don't need to
* recreate it each time draw() is called since it
* takes a few milliseconds.
*/
private void generatePatternBitmap() {
if (getBounds().width() <= 0 || getBounds().height() <= 0) {
return;
}
mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmap);
Rect r = new Rect();
boolean verticalStartWhite = true;
for (int i = 0; i <= numRectanglesVertical; i++) {
boolean isWhite = verticalStartWhite;
for (int j = 0; j <= numRectanglesHorizontal; j++) {
r.top = i * mRectangleSize;
r.left = j * mRectangleSize;
r.bottom = r.top + mRectangleSize;
r.right = r.left + mRectangleSize;
canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
isWhite = !isWhite;
}
verticalStartWhite = !verticalStartWhite;
}
}
}

View file

@ -0,0 +1,245 @@
/*
* Copyright (C) 2010 Daniel Nilsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.margaritov.preference.colorpicker;
import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.Locale;
public class ColorPickerDialog
extends
Dialog
implements
ColorPickerView.OnColorChangedListener,
View.OnClickListener, ViewTreeObserver.OnGlobalLayoutListener {
private ColorPickerView mColorPicker;
private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor;
private EditText mHexVal;
private boolean mHexValueEnabled = false;
private ColorStateList mHexDefaultTextColor;
private OnColorChangedListener mListener;
private int mOrientation;
private View mLayout;
@Override
public void onGlobalLayout() {
if (getContext().getResources().getConfiguration().orientation != mOrientation) {
final int oldcolor = mOldColor.getColor();
final int newcolor = mNewColor.getColor();
mLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
setUp(oldcolor);
mNewColor.setColor(newcolor);
mColorPicker.setColor(newcolor);
}
}
public interface OnColorChangedListener {
public void onColorChanged(int color);
}
public ColorPickerDialog(Context context, int initialColor) {
super(context);
init(initialColor);
}
private void init(int color) {
// To fight color banding.
getWindow().setFormat(PixelFormat.RGBA_8888);
setUp(color);
}
private void setUp(int color) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mLayout = inflater.inflate(R.layout.dialog_color_picker, null);
mLayout.getViewTreeObserver().addOnGlobalLayoutListener(this);
mOrientation = getContext().getResources().getConfiguration().orientation;
setContentView(mLayout);
setTitle(R.string.dialog_color_picker);
mColorPicker = (ColorPickerView) mLayout.findViewById(R.id.color_picker_view);
mOldColor = (ColorPickerPanelView) mLayout.findViewById(R.id.old_color_panel);
mNewColor = (ColorPickerPanelView) mLayout.findViewById(R.id.new_color_panel);
mHexVal = (EditText) mLayout.findViewById(R.id.hex_val);
mHexVal.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
mHexDefaultTextColor = mHexVal.getTextColors();
mHexVal.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
String s = mHexVal.getText().toString();
if (s.length() > 5 || s.length() < 10) {
try {
int c = ColorPickerPreference.convertToColorInt(s.toString());
mColorPicker.setColor(c, true);
mHexVal.setTextColor(mHexDefaultTextColor);
} catch (IllegalArgumentException e) {
mHexVal.setTextColor(Color.RED);
}
} else {
mHexVal.setTextColor(Color.RED);
}
return true;
}
return false;
}
});
((LinearLayout) mOldColor.getParent()).setPadding(
Math.round(mColorPicker.getDrawingOffset()),
0,
Math.round(mColorPicker.getDrawingOffset()),
0
);
mOldColor.setOnClickListener(this);
mNewColor.setOnClickListener(this);
mColorPicker.setOnColorChangedListener(this);
mOldColor.setColor(color);
mColorPicker.setColor(color, true);
}
@Override
public void onColorChanged(int color) {
mNewColor.setColor(color);
if (mHexValueEnabled)
updateHexValue(color);
/*
if (mListener != null) {
mListener.onColorChanged(color);
}
*/
}
public void setHexValueEnabled(boolean enable) {
mHexValueEnabled = enable;
if (enable) {
mHexVal.setVisibility(View.VISIBLE);
updateHexLengthFilter();
updateHexValue(getColor());
} else
mHexVal.setVisibility(View.GONE);
}
public boolean getHexValueEnabled() {
return mHexValueEnabled;
}
private void updateHexLengthFilter() {
if (getAlphaSliderVisible())
mHexVal.setFilters(new InputFilter[]{new InputFilter.LengthFilter(9)});
else
mHexVal.setFilters(new InputFilter[]{new InputFilter.LengthFilter(7)});
}
private void updateHexValue(int color) {
if (getAlphaSliderVisible()) {
mHexVal.setText(ColorPickerPreference.convertToARGB(color).toUpperCase(Locale.getDefault()));
} else {
mHexVal.setText(ColorPickerPreference.convertToRGB(color).toUpperCase(Locale.getDefault()));
}
mHexVal.setTextColor(mHexDefaultTextColor);
}
public void setAlphaSliderVisible(boolean visible) {
mColorPicker.setAlphaSliderVisible(visible);
if (mHexValueEnabled) {
updateHexLengthFilter();
updateHexValue(getColor());
}
}
public boolean getAlphaSliderVisible() {
return mColorPicker.getAlphaSliderVisible();
}
/**
* Set a OnColorChangedListener to get notified when the color
* selected by the user has changed.
*
* @param listener
*/
public void setOnColorChangedListener(OnColorChangedListener listener) {
mListener = listener;
}
public int getColor() {
return mColorPicker.getColor();
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.new_color_panel) {
if (mListener != null) {
mListener.onColorChanged(mNewColor.getColor());
}
}
dismiss();
}
@Override
public Bundle onSaveInstanceState() {
Bundle state = super.onSaveInstanceState();
state.putInt("old_color", mOldColor.getColor());
state.putInt("new_color", mNewColor.getColor());
return state;
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mOldColor.setColor(savedInstanceState.getInt("old_color"));
mColorPicker.setColor(savedInstanceState.getInt("new_color"), true);
}
}

View file

@ -0,0 +1,174 @@
/*
* Copyright (C) 2010 Daniel Nilsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.margaritov.preference.colorpicker;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* This class draws a panel which which will be filled with a color which can be set.
* It can be used to show the currently selected color which you will get from
* the {@link ColorPickerView}.
*
* @author Daniel Nilsson
*/
public class ColorPickerPanelView extends View {
/**
* The width in pixels of the border
* surrounding the color panel.
*/
private final static float BORDER_WIDTH_PX = 1;
private float mDensity = 1f;
private int mBorderColor = 0xff6E6E6E;
private int mColor = 0xff000000;
private Paint mBorderPaint;
private Paint mColorPaint;
private RectF mDrawingRect;
private RectF mColorRect;
private AlphaPatternDrawable mAlphaPattern;
public ColorPickerPanelView(Context context) {
this(context, null);
}
public ColorPickerPanelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorPickerPanelView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mBorderPaint = new Paint();
mColorPaint = new Paint();
mDensity = getContext().getResources().getDisplayMetrics().density;
}
@Override
protected void onDraw(Canvas canvas) {
final RectF rect = mColorRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(mDrawingRect, mBorderPaint);
}
if (mAlphaPattern != null) {
mAlphaPattern.draw(canvas);
}
mColorPaint.setColor(mColor);
canvas.drawRect(rect, mColorPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDrawingRect = new RectF();
mDrawingRect.left = getPaddingLeft();
mDrawingRect.right = w - getPaddingRight();
mDrawingRect.top = getPaddingTop();
mDrawingRect.bottom = h - getPaddingBottom();
setUpColorRect();
}
private void setUpColorRect() {
final RectF dRect = mDrawingRect;
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX;
float right = dRect.right - BORDER_WIDTH_PX;
mColorRect = new RectF(left, top, right, bottom);
mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
mAlphaPattern.setBounds(
Math.round(mColorRect.left),
Math.round(mColorRect.top),
Math.round(mColorRect.right),
Math.round(mColorRect.bottom)
);
}
/**
* Set the color that should be shown by this view.
*
* @param color
*/
public void setColor(int color) {
mColor = color;
invalidate();
}
/**
* Get the color currently show by this view.
*
* @return
*/
public int getColor() {
return mColor;
}
/**
* Set the color of the border surrounding the panel.
*
* @param color
*/
public void setBorderColor(int color) {
mBorderColor = color;
invalidate();
}
/**
* Get the color of the border surrounding the panel.
*/
public int getBorderColor() {
return mBorderColor;
}
}

View file

@ -0,0 +1,332 @@
/*
* Copyright (C) 2011 Sergey Margaritov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.margaritov.preference.colorpicker;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
/**
* A preference type that allows a user to choose a time
*
* @author Sergey Margaritov
*/
public class ColorPickerPreference
extends
Preference
implements
Preference.OnPreferenceClickListener,
ColorPickerDialog.OnColorChangedListener {
View mView;
ColorPickerDialog mDialog;
private int mValue = Color.BLACK;
private float mDensity = 0;
private boolean mAlphaSliderEnabled = false;
private boolean mHexValueEnabled = false;
public ColorPickerPreference(Context context) {
super(context);
init(context, null);
}
public ColorPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public ColorPickerPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
/**Method edited by
* @author Anna Berkovitch
* added functionality to accept hex string as defaultValue
* and to properly persist resources reference string, such as @color/someColor
* previously persisted 0*/
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
int colorInt;
String mHexDefaultValue = a.getString(index);
if (mHexDefaultValue != null && mHexDefaultValue.startsWith("#")) {
colorInt = convertToColorInt(mHexDefaultValue);
return colorInt;
} else {
return a.getColor(index, Color.BLACK);
}
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
onColorChanged(restoreValue ? getPersistedInt(mValue) : (Integer) defaultValue);
}
private void init(Context context, AttributeSet attrs) {
mDensity = getContext().getResources().getDisplayMetrics().density;
setOnPreferenceClickListener(this);
if (attrs != null) {
mAlphaSliderEnabled = attrs.getAttributeBooleanValue(null, "alphaSlider", false);
mHexValueEnabled = attrs.getAttributeBooleanValue(null, "hexValue", false);
}
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
mView = view;
setPreviewColor();
}
private void setPreviewColor() {
if (mView == null) return;
ImageView iView = new ImageView(getContext());
LinearLayout widgetFrameView = ((LinearLayout) mView.findViewById(android.R.id.widget_frame));
if (widgetFrameView == null) return;
widgetFrameView.setVisibility(View.VISIBLE);
widgetFrameView.setPadding(
widgetFrameView.getPaddingLeft(),
widgetFrameView.getPaddingTop(),
(int) (mDensity * 8),
widgetFrameView.getPaddingBottom()
);
// remove already create preview image
int count = widgetFrameView.getChildCount();
if (count > 0) {
widgetFrameView.removeViews(0, count);
}
widgetFrameView.addView(iView);
widgetFrameView.setMinimumWidth(0);
iView.setBackgroundDrawable(new AlphaPatternDrawable((int) (5 * mDensity)));
iView.setImageBitmap(getPreviewBitmap());
}
private Bitmap getPreviewBitmap() {
int d = (int) (mDensity * 31); //30dip
int color = mValue;
Bitmap bm = Bitmap.createBitmap(d, d, Config.ARGB_8888);
int w = bm.getWidth();
int h = bm.getHeight();
int c = color;
for (int i = 0; i < w; i++) {
for (int j = i; j < h; j++) {
c = (i <= 1 || j <= 1 || i >= w - 2 || j >= h - 2) ? Color.GRAY : color;
bm.setPixel(i, j, c);
if (i != j) {
bm.setPixel(j, i, c);
}
}
}
return bm;
}
@Override
public void onColorChanged(int color) {
if (isPersistent()) {
persistInt(color);
}
mValue = color;
setPreviewColor();
try {
getOnPreferenceChangeListener().onPreferenceChange(this, color);
} catch (NullPointerException e) {
}
}
public boolean onPreferenceClick(Preference preference) {
showDialog(null);
return false;
}
protected void showDialog(Bundle state) {
mDialog = new ColorPickerDialog(getContext(), mValue);
mDialog.setOnColorChangedListener(this);
if (mAlphaSliderEnabled) {
mDialog.setAlphaSliderVisible(true);
}
if (mHexValueEnabled) {
mDialog.setHexValueEnabled(true);
}
if (state != null) {
mDialog.onRestoreInstanceState(state);
}
mDialog.show();
}
/**
* Toggle Alpha Slider visibility (by default it's disabled)
*
* @param enable
*/
public void setAlphaSliderEnabled(boolean enable) {
mAlphaSliderEnabled = enable;
}
/**
* Toggle Hex Value visibility (by default it's disabled)
*
* @param enable
*/
public void setHexValueEnabled(boolean enable) {
mHexValueEnabled = enable;
}
/**
* For custom purposes. Not used by ColorPickerPreferrence
*
* @param color
* @author Unknown
*/
public static String convertToARGB(int color) {
String alpha = Integer.toHexString(Color.alpha(color));
String red = Integer.toHexString(Color.red(color));
String green = Integer.toHexString(Color.green(color));
String blue = Integer.toHexString(Color.blue(color));
if (alpha.length() == 1) {
alpha = "0" + alpha;
}
if (red.length() == 1) {
red = "0" + red;
}
if (green.length() == 1) {
green = "0" + green;
}
if (blue.length() == 1) {
blue = "0" + blue;
}
return "#" + alpha + red + green + blue;
}
/**
* Method currently used by onGetDefaultValue method to
* convert hex string provided in android:defaultValue to color integer.
*
* @param color
* @return A string representing the hex value of color,
* without the alpha value
* @author Charles Rosaaen
*/
public static String convertToRGB(int color) {
String red = Integer.toHexString(Color.red(color));
String green = Integer.toHexString(Color.green(color));
String blue = Integer.toHexString(Color.blue(color));
if (red.length() == 1) {
red = "0" + red;
}
if (green.length() == 1) {
green = "0" + green;
}
if (blue.length() == 1) {
blue = "0" + blue;
}
return "#" + red + green + blue;
}
/**
* For custom purposes. Not used by ColorPickerPreferrence
*
* @param argb
* @throws NumberFormatException
* @author Unknown
*/
public static int convertToColorInt(String argb) throws IllegalArgumentException {
if (!argb.startsWith("#")) {
argb = "#" + argb;
}
return Color.parseColor(argb);
}
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
if (mDialog == null || !mDialog.isShowing()) {
return superState;
}
final SavedState myState = new SavedState(superState);
myState.dialogBundle = mDialog.onSaveInstanceState();
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state == null || !(state instanceof SavedState)) {
// Didn't save state for us in onSaveInstanceState
super.onRestoreInstanceState(state);
return;
}
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
showDialog(myState.dialogBundle);
}
private static class SavedState extends BaseSavedState {
Bundle dialogBundle;
public SavedState(Parcel source) {
super(source);
dialogBundle = source.readBundle();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeBundle(dialogBundle);
}
public SavedState(Parcelable superState) {
super(superState);
}
@SuppressWarnings("unused")
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
}

View file

@ -0,0 +1,945 @@
/*
* Copyright (C) 2010 Daniel Nilsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.margaritov.preference.colorpicker;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Displays a color picker to the user and allow them
* to select a color. A slider for the alpha channel is
* also available. Enable it by setting
* setAlphaSliderVisible(boolean) to true.
*
* @author Daniel Nilsson
*/
public class ColorPickerView extends View {
private final static int PANEL_SAT_VAL = 0;
private final static int PANEL_HUE = 1;
private final static int PANEL_ALPHA = 2;
/**
* The width in pixels of the border
* surrounding all color panels.
*/
private final static float BORDER_WIDTH_PX = 1;
/**
* The width in dp of the hue panel.
*/
private float HUE_PANEL_WIDTH = 30f;
/**
* The height in dp of the alpha panel
*/
private float ALPHA_PANEL_HEIGHT = 20f;
/**
* The distance in dp between the different
* color panels.
*/
private float PANEL_SPACING = 10f;
/**
* The radius in dp of the color palette tracker circle.
*/
private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
/**
* The dp which the tracker of the hue or alpha panel
* will extend outside of its bounds.
*/
private float RECTANGLE_TRACKER_OFFSET = 2f;
private float mDensity = 1f;
private OnColorChangedListener mListener;
private Paint mSatValPaint;
private Paint mSatValTrackerPaint;
private Paint mHuePaint;
private Paint mHueTrackerPaint;
private Paint mAlphaPaint;
private Paint mAlphaTextPaint;
private Paint mBorderPaint;
private Shader mValShader;
private Shader mSatShader;
private Shader mHueShader;
private Shader mAlphaShader;
private int mAlpha = 0xff;
private float mHue = 360f;
private float mSat = 0f;
private float mVal = 0f;
private String mAlphaSliderText = "";
private int mSliderTrackerColor = 0xff1c1c1c;
private int mBorderColor = 0xff6E6E6E;
private boolean mShowAlphaPanel = false;
/*
* To remember which panel that has the "focus" when
* processing hardware button data.
*/
private int mLastTouchedPanel = PANEL_SAT_VAL;
/**
* Offset from the edge we must have or else
* the finger tracker will get clipped when
* it is drawn outside of the view.
*/
private float mDrawingOffset;
/*
* Distance form the edges of the view
* of where we are allowed to draw.
*/
private RectF mDrawingRect;
private RectF mSatValRect;
private RectF mHueRect;
private RectF mAlphaRect;
private AlphaPatternDrawable mAlphaPattern;
private Point mStartTouchPoint = null;
public interface OnColorChangedListener {
public void onColorChanged(int color);
}
public ColorPickerView(Context context) {
this(context, null);
}
public ColorPickerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mDensity = getContext().getResources().getDisplayMetrics().density;
PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
RECTANGLE_TRACKER_OFFSET *= mDensity;
HUE_PANEL_WIDTH *= mDensity;
ALPHA_PANEL_HEIGHT *= mDensity;
PANEL_SPACING = PANEL_SPACING * mDensity;
mDrawingOffset = calculateRequiredOffset();
initPaintTools();
//Needed for receiving trackball motion events.
setFocusable(true);
setFocusableInTouchMode(true);
}
private void initPaintTools() {
mSatValPaint = new Paint();
mSatValTrackerPaint = new Paint();
mHuePaint = new Paint();
mHueTrackerPaint = new Paint();
mAlphaPaint = new Paint();
mAlphaTextPaint = new Paint();
mBorderPaint = new Paint();
mSatValTrackerPaint.setStyle(Style.STROKE);
mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
mSatValTrackerPaint.setAntiAlias(true);
mHueTrackerPaint.setColor(mSliderTrackerColor);
mHueTrackerPaint.setStyle(Style.STROKE);
mHueTrackerPaint.setStrokeWidth(2f * mDensity);
mHueTrackerPaint.setAntiAlias(true);
mAlphaTextPaint.setColor(0xff1c1c1c);
mAlphaTextPaint.setTextSize(14f * mDensity);
mAlphaTextPaint.setAntiAlias(true);
mAlphaTextPaint.setTextAlign(Align.CENTER);
mAlphaTextPaint.setFakeBoldText(true);
}
private float calculateRequiredOffset() {
float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
return offset * 1.5f;
}
private int[] buildHueColorArray() {
int[] hue = new int[361];
int count = 0;
for (int i = hue.length - 1; i >= 0; i--, count++) {
hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f});
}
return hue;
}
@Override
protected void onDraw(Canvas canvas) {
if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return;
drawSatValPanel(canvas);
drawHuePanel(canvas);
drawAlphaPanel(canvas);
}
private void drawSatValPanel(Canvas canvas) {
final RectF rect = mSatValRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX, rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
}
if (mValShader == null) {
mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
0xffffffff, 0xff000000, TileMode.CLAMP);
}
int rgb = Color.HSVToColor(new float[]{mHue, 1f, 1f});
mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
0xffffffff, rgb, TileMode.CLAMP);
ComposeShader mShader = new ComposeShader(mValShader, mSatShader, PorterDuff.Mode.MULTIPLY);
mSatValPaint.setShader(mShader);
canvas.drawRect(rect, mSatValPaint);
Point p = satValToPoint(mSat, mVal);
mSatValTrackerPaint.setColor(0xff000000);
canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity, mSatValTrackerPaint);
mSatValTrackerPaint.setColor(0xffdddddd);
canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
}
private void drawHuePanel(Canvas canvas) {
final RectF rect = mHueRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
rect.top - BORDER_WIDTH_PX,
rect.right + BORDER_WIDTH_PX,
rect.bottom + BORDER_WIDTH_PX,
mBorderPaint);
}
if (mHueShader == null) {
mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom, buildHueColorArray(), null, TileMode.CLAMP);
mHuePaint.setShader(mHueShader);
}
canvas.drawRect(rect, mHuePaint);
float rectHeight = 4 * mDensity / 2;
Point p = hueToPoint(mHue);
RectF r = new RectF();
r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
r.top = p.y - rectHeight;
r.bottom = p.y + rectHeight;
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
}
private void drawAlphaPanel(Canvas canvas) {
if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) return;
final RectF rect = mAlphaRect;
if (BORDER_WIDTH_PX > 0) {
mBorderPaint.setColor(mBorderColor);
canvas.drawRect(rect.left - BORDER_WIDTH_PX,
rect.top - BORDER_WIDTH_PX,
rect.right + BORDER_WIDTH_PX,
rect.bottom + BORDER_WIDTH_PX,
mBorderPaint);
}
mAlphaPattern.draw(canvas);
float[] hsv = new float[]{mHue, mSat, mVal};
int color = Color.HSVToColor(hsv);
int acolor = Color.HSVToColor(0, hsv);
mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
color, acolor, TileMode.CLAMP);
mAlphaPaint.setShader(mAlphaShader);
canvas.drawRect(rect, mAlphaPaint);
if (mAlphaSliderText != null && mAlphaSliderText != "") {
canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity, mAlphaTextPaint);
}
float rectWidth = 4 * mDensity / 2;
Point p = alphaToPoint(mAlpha);
RectF r = new RectF();
r.left = p.x - rectWidth;
r.right = p.x + rectWidth;
r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
}
private Point hueToPoint(float hue) {
final RectF rect = mHueRect;
final float height = rect.height();
Point p = new Point();
p.y = (int) (height - (hue * height / 360f) + rect.top);
p.x = (int) rect.left;
return p;
}
private Point satValToPoint(float sat, float val) {
final RectF rect = mSatValRect;
final float height = rect.height();
final float width = rect.width();
Point p = new Point();
p.x = (int) (sat * width + rect.left);
p.y = (int) ((1f - val) * height + rect.top);
return p;
}
private Point alphaToPoint(int alpha) {
final RectF rect = mAlphaRect;
final float width = rect.width();
Point p = new Point();
p.x = (int) (width - (alpha * width / 0xff) + rect.left);
p.y = (int) rect.top;
return p;
}
private float[] pointToSatVal(float x, float y) {
final RectF rect = mSatValRect;
float[] result = new float[2];
float width = rect.width();
float height = rect.height();
if (x < rect.left) {
x = 0f;
} else if (x > rect.right) {
x = width;
} else {
x = x - rect.left;
}
if (y < rect.top) {
y = 0f;
} else if (y > rect.bottom) {
y = height;
} else {
y = y - rect.top;
}
result[0] = 1.f / width * x;
result[1] = 1.f - (1.f / height * y);
return result;
}
private float pointToHue(float y) {
final RectF rect = mHueRect;
float height = rect.height();
if (y < rect.top) {
y = 0f;
} else if (y > rect.bottom) {
y = height;
} else {
y = y - rect.top;
}
return 360f - (y * 360f / height);
}
private int pointToAlpha(int x) {
final RectF rect = mAlphaRect;
final int width = (int) rect.width();
if (x < rect.left) {
x = 0;
} else if (x > rect.right) {
x = width;
} else {
x = x - (int) rect.left;
}
return 0xff - (x * 0xff / width);
}
@Override
public boolean onTrackballEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean update = false;
if (event.getAction() == MotionEvent.ACTION_MOVE) {
switch (mLastTouchedPanel) {
case PANEL_SAT_VAL:
float sat, val;
sat = mSat + x / 50f;
val = mVal - y / 50f;
if (sat < 0f) {
sat = 0f;
} else if (sat > 1f) {
sat = 1f;
}
if (val < 0f) {
val = 0f;
} else if (val > 1f) {
val = 1f;
}
mSat = sat;
mVal = val;
update = true;
break;
case PANEL_HUE:
float hue = mHue - y * 10f;
if (hue < 0f) {
hue = 0f;
} else if (hue > 360f) {
hue = 360f;
}
mHue = hue;
update = true;
break;
case PANEL_ALPHA:
if (!mShowAlphaPanel || mAlphaRect == null) {
update = false;
} else {
int alpha = (int) (mAlpha - x * 10);
if (alpha < 0) {
alpha = 0;
} else if (alpha > 0xff) {
alpha = 0xff;
}
mAlpha = alpha;
update = true;
}
break;
}
}
if (update) {
if (mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
}
invalidate();
return true;
}
return super.onTrackballEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean update = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartTouchPoint = new Point((int) event.getX(), (int) event.getY());
update = moveTrackersIfNeeded(event);
break;
case MotionEvent.ACTION_MOVE:
update = moveTrackersIfNeeded(event);
break;
case MotionEvent.ACTION_UP:
mStartTouchPoint = null;
update = moveTrackersIfNeeded(event);
break;
}
if (update) {
if (mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
}
invalidate();
return true;
}
return super.onTouchEvent(event);
}
private boolean moveTrackersIfNeeded(MotionEvent event) {
if (mStartTouchPoint == null) return false;
boolean update = false;
int startX = mStartTouchPoint.x;
int startY = mStartTouchPoint.y;
if (mHueRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_HUE;
mHue = pointToHue(event.getY());
update = true;
} else if (mSatValRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_SAT_VAL;
float[] result = pointToSatVal(event.getX(), event.getY());
mSat = result[0];
mVal = result[1];
update = true;
} else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
mLastTouchedPanel = PANEL_ALPHA;
mAlpha = pointToAlpha((int) event.getX());
update = true;
}
return update;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = 0;
int height = 0;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
widthAllowed = chooseWidth(widthMode, widthAllowed);
heightAllowed = chooseHeight(heightMode, heightAllowed);
if (!mShowAlphaPanel) {
height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
//If calculated height (based on the width) is more than the allowed height.
if (height > heightAllowed || getTag().equals("landscape")) {
height = heightAllowed;
width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
} else {
width = widthAllowed;
}
} else {
width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
if (width > widthAllowed) {
width = widthAllowed;
height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
} else {
height = heightAllowed;
}
}
setMeasuredDimension(width, height);
}
private int chooseWidth(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPrefferedWidth();
}
}
private int chooseHeight(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPrefferedHeight();
}
}
private int getPrefferedWidth() {
int width = getPrefferedHeight();
if (mShowAlphaPanel) {
width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
}
return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
}
private int getPrefferedHeight() {
int height = (int) (200 * mDensity);
if (mShowAlphaPanel) {
height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
}
return height;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mDrawingRect = new RectF();
mDrawingRect.left = mDrawingOffset + getPaddingLeft();
mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
mDrawingRect.top = mDrawingOffset + getPaddingTop();
mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
setUpSatValRect();
setUpHueRect();
setUpAlphaRect();
}
private void setUpSatValRect() {
final RectF dRect = mDrawingRect;
float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
if (mShowAlphaPanel) {
panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
}
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = top + panelSide;
float right = left + panelSide;
mSatValRect = new RectF(left, top, right, bottom);
}
private void setUpHueRect() {
final RectF dRect = mDrawingRect;
float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
float top = dRect.top + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX - (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
float right = dRect.right - BORDER_WIDTH_PX;
mHueRect = new RectF(left, top, right, bottom);
}
private void setUpAlphaRect() {
if (!mShowAlphaPanel) return;
final RectF dRect = mDrawingRect;
float left = dRect.left + BORDER_WIDTH_PX;
float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
float bottom = dRect.bottom - BORDER_WIDTH_PX;
float right = dRect.right - BORDER_WIDTH_PX;
mAlphaRect = new RectF(left, top, right, bottom);
mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
mAlphaPattern.setBounds(
Math.round(mAlphaRect.left),
Math.round(mAlphaRect.top),
Math.round(mAlphaRect.right),
Math.round(mAlphaRect.bottom)
);
}
/**
* Set a OnColorChangedListener to get notified when the color
* selected by the user has changed.
*
* @param listener
*/
public void setOnColorChangedListener(OnColorChangedListener listener) {
mListener = listener;
}
/**
* Set the color of the border surrounding all panels.
*
* @param color
*/
public void setBorderColor(int color) {
mBorderColor = color;
invalidate();
}
/**
* Get the color of the border surrounding all panels.
*/
public int getBorderColor() {
return mBorderColor;
}
/**
* Get the current color this view is showing.
*
* @return the current color.
*/
public int getColor() {
return Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal});
}
/**
* Set the color the view should show.
*
* @param color The color that should be selected.
*/
public void setColor(int color) {
setColor(color, false);
}
/**
* Set the color this view should show.
*
* @param color The color that should be selected.
* @param callback If you want to get a callback to
* your OnColorChangedListener.
*/
public void setColor(int color, boolean callback) {
int alpha = Color.alpha(color);
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
mAlpha = alpha;
mHue = hsv[0];
mSat = hsv[1];
mVal = hsv[2];
if (callback && mListener != null) {
mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[]{mHue, mSat, mVal}));
}
invalidate();
}
/**
* Get the drawing offset of the color picker view.
* The drawing offset is the distance from the side of
* a panel to the side of the view minus the padding.
* Useful if you want to have your own panel below showing
* the currently selected color and want to align it perfectly.
*
* @return The offset in pixels.
*/
public float getDrawingOffset() {
return mDrawingOffset;
}
/**
* Set if the user is allowed to adjust the alpha panel. Default is false.
* If it is set to false no alpha will be set.
*
* @param visible
*/
public void setAlphaSliderVisible(boolean visible) {
if (mShowAlphaPanel != visible) {
mShowAlphaPanel = visible;
/*
* Reset all shader to force a recreation.
* Otherwise they will not look right after
* the size of the view has changed.
*/
mValShader = null;
mSatShader = null;
mHueShader = null;
mAlphaShader = null;
requestLayout();
}
}
public boolean getAlphaSliderVisible() {
return mShowAlphaPanel;
}
public void setSliderTrackerColor(int color) {
mSliderTrackerColor = color;
mHueTrackerPaint.setColor(mSliderTrackerColor);
invalidate();
}
public int getSliderTrackerColor() {
return mSliderTrackerColor;
}
/**
* Set the text that should be shown in the
* alpha slider. Set to null to disable text.
*
* @param res string resource id.
*/
public void setAlphaSliderText(int res) {
String text = getContext().getString(res);
setAlphaSliderText(text);
}
/**
* Set the text that should be shown in the
* alpha slider. Set to null to disable text.
*
* @param text Text that should be shown.
*/
public void setAlphaSliderText(String text) {
mAlphaSliderText = text;
invalidate();
}
/**
* Get the current value of the text
* that will be shown in the alpha
* slider.
*
* @return
*/
public String getAlphaSliderText() {
return mAlphaSliderText;
}
}

View file

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2010 Daniel Nilsson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="5dp"
android:paddingRight="5dp">
<net.margaritov.preference.colorpicker.ColorPickerView
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layerType="software"
android:tag="landscape" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<EditText
android:id="@+id/hex_val"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="HEX"
android:imeOptions="actionDone"
android:maxLength="7"
android:singleLine="true"
android:inputType="textCapCharacters"
android:visibility="gone"></EditText>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="6dp"
android:gravity="center"
android:text="@string/press_color_to_apply"
android:textAppearance="?android:attr/textAppearanceSmall" />
<net.margaritov.preference.colorpicker.ColorPickerPanelView
android:id="@+id/old_color_panel"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_weight="0.5" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:gravity="center"
android:text="↓"
android:textSize="20sp" />
<net.margaritov.preference.colorpicker.ColorPickerPanelView
android:id="@+id/new_color_panel"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_weight="0.5" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2010 Daniel Nilsson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="5dp"
android:paddingRight="5dp">
<net.margaritov.preference.colorpicker.ColorPickerView
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layerType="software"
android:tag="portrait" />
<LinearLayout
android:id="@+id/text_hex_wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:text="@string/press_color_to_apply"
android:textAppearance="?android:attr/textAppearanceSmall" />
<EditText
android:id="@+id/hex_val"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="HEX"
android:imeOptions="actionDone"
android:maxLength="7"
android:singleLine="true"
android:inputType="textCapCharacters"
android:visibility="gone"></EditText>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<net.margaritov.preference.colorpicker.ColorPickerPanelView
android:id="@+id/old_color_panel"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="0.5" />
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:gravity="center"
android:text="→"
android:textSize="20sp" />
<net.margaritov.preference.colorpicker.ColorPickerPanelView
android:id="@+id/new_color_panel"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="0.5" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Color Picker -->
<string name="dialog_color_picker">Color Picker</string>
<string name="press_color_to_apply">Press on Color to apply</string>
</resources>

View file

@ -1,12 +1,14 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 33
buildToolsVersion '33.0.2'
compileSdkVersion 34
buildToolsVersion '34.0.0'
namespace "sh.ftp.rocketninelabs.meditationassistant"
defaultConfig {
minSdkVersion 16
targetSdkVersion 33
minSdkVersion 21
targetSdkVersion 34
versionCode 167
versionName "1.6.7"
@ -35,6 +37,10 @@ android {
opensource.java.srcDirs = ['src/opensource/java']
}
buildFeatures {
buildConfig true
}
buildTypes {
release {
debuggable false
@ -75,18 +81,25 @@ android {
}
dependencies {
implementation 'androidx.core:core:1.9.0'
implementation project(':ColorPickerPreference') // https://github.com/attenzione/android-ColorPickerPreference
implementation 'androidx.core:core:1.13.1'
implementation 'androidx.legacy:legacy-support-core-utils:1.0.0'
implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
implementation 'androidx.media:media:1.6.0'
implementation 'androidx.media:media:1.7.0'
implementation 'com.android.support:multidex:1.0.3'
implementation 'androidx.fragment:fragment:1.5.6'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.fragment:fragment:1.8.4'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'com.google.android.material:material:1.12.0'
implementation 'net.openid:appauth:0.7.1'
implementation 'com.opencsv:opencsv:5.2'
implementation 'com.squareup.okio:okio:2.8.0'
implementation 'com.nononsenseapps:filepicker:4.2.1'
implementation 'com.github.amlcurran.showcaseview:library:5.4.3'
implementation 'net.margaritov.preference.colorpicker.ColorPickerPreference:ColorPickerPreference:1.0.0'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

View file

@ -92,8 +92,6 @@ public class AboutActivity extends Activity {
String shareURL;
if (BuildConfig.FLAVOR.equals("opensource")) {
shareURL = "https://f-droid.org/packages/" + getApplicationContext().getPackageName();
} else if (getMeditationAssistant().getMarketName().equals("google")) {
shareURL = "http://play.google.com/store/apps/details?id=" + getApplicationContext().getPackageName();
} else if (getMeditationAssistant().getMarketName().equals("amazon")) {
shareURL = "http://www.amazon.com/gp/mas/dl/android?p=" + getApplicationContext().getPackageName();
} else {

View file

@ -483,7 +483,7 @@ public class MainActivity extends Activity implements OnShowcaseEventListener {
.setIcon(getResources().getDrawable(getTheme().obtainStyledAttributes(getMeditationAssistant().getMATheme(), new int[]{R.attr.actionIconInfo}).getResourceId(0, 0)))
.setTitle(getString(R.string.whatIsMediNET))
.setMessage(getString(R.string.whatIsMediNETHelp))
.setPositiveButton(R.string.ok, null)
.setPositiveButton(android.R.string.ok, null)
.show();
} else if (item.getItemId() == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);

View file

@ -285,10 +285,7 @@ public class MeditationAssistant extends Application {
} else if (BuildConfig.FLAVOR.equals("opensource")) {
marketName = "fdroid";
} else { // To be uncommented based upon target market
marketName = "google";
//marketName = "amazon";
//marketName = "getjar";
//marketName = "slideme";
marketName = "amazon";
}
}
@ -351,8 +348,6 @@ public class MeditationAssistant extends Application {
public void rateApp() {
if (getMarketName().equals("bb")) {
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("https://appworld.blackberry.com/webstore/content/" + (BuildConfig.FLAVOR.equals("free") ? "59939924" : "59939922") + "/")), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} else if (getMarketName().equals("google")) {
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + getApplicationContext().getPackageName())), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} else if (getMarketName().equals("amazon")) {
startActivity(Intent.createChooser(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.amazon.com/gp/mas/dl/android?p=" + getApplicationContext().getPackageName())), getString(R.string.openWith)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}

View file

@ -1,4 +1,5 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ListPreference
android:defaultValue="dark"

View file

@ -3,7 +3,6 @@
[![Donate](https://img.shields.io/liberapay/receives/rocketnine.space.svg?logo=liberapay)](https://liberapay.com/rocketnine.space)
<a href="https://f-droid.org/packages/sh.ftp.rocketninelabs.meditationassistant.opensource/"><img width="121" height="36" alt="F-Droid" border="0" src="https://rocketnine.space/static/badge_fdroid_36.png"></a>
&nbsp; <a href="https://play.google.com/store/apps/details?id=sh.ftp.rocketninelabs.meditationassistant"><img width="121" height="36" alt="Google Play" border="0" src="https://rocketnine.space/static/badge_google_36.png"></a>
This application assists with both timed (via duration or ending at a specific time) and
untimed sessions, with numerous customizations, including start/interval/end sounds and

View file

@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.2'
classpath 'com.android.tools.build:gradle:8.7.0'
}
}
@ -18,6 +18,6 @@ tasks.whenTaskAdded { task ->
allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

Binary file not shown.

View file

@ -1,6 +1,7 @@
#Thu Nov 12 12:35:55 PST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip

324
gradlew vendored
View file

@ -1,79 +1,130 @@
#!/usr/bin/env bash
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Attempt to set APP_HOME
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn ( ) {
warn () {
echo "$*"
}
} >&2
die ( ) {
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -82,83 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

88
gradlew.bat vendored
View file

@ -1,4 +1,22 @@
@if "%DEBUG%" == "" @echo off
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -8,26 +26,30 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@ -35,54 +57,36 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View file

@ -1 +1,5 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}
include ':ColorPickerPreference'
include ':MeditationAssistant'