Browse Source

Added alarm notification LED colour including costumizable colour setting (issue 384).

(Also some small crash fixes.)
pull/11/head
Eric Kok 13 years ago
parent
commit
4c25c1038f
  1. 3
      README
  2. 76
      android/res/layout-land/dialog_color_picker.xml
  3. 77
      android/res/layout/dialog_color_picker.xml
  4. 5
      android/res/values/strings.xml
  5. 128
      android/src/net/margaritov/preference/colorpicker/AlphaPatternDrawable.java
  6. 129
      android/src/net/margaritov/preference/colorpicker/ColorPickerDialog.java
  7. 171
      android/src/net/margaritov/preference/colorpicker/ColorPickerPanelView.java
  8. 246
      android/src/net/margaritov/preference/colorpicker/ColorPickerPreference.java
  9. 952
      android/src/net/margaritov/preference/colorpicker/ColorPickerView.java
  10. 5
      android/src/org/transdroid/gui/DetailsFragment.java
  11. 5
      android/src/org/transdroid/gui/TaskResultHandler.java
  12. 8
      android/src/org/transdroid/gui/TorrentsFragment.java
  13. 12
      android/src/org/transdroid/preferences/Preferences.java
  14. 19
      android/src/org/transdroid/preferences/PreferencesAlarm.java
  15. 11
      android/src/org/transdroid/service/AlarmService.java
  16. 8
      android/src/org/transdroid/service/AlarmSettings.java
  17. 2
      lib/.classpath
  18. 2
      lib/src/org/transdroid/daemon/IDaemonCallback.java
  19. 8
      lib/src/org/transdroid/daemon/TaskQueue.java

3
README

@ -34,4 +34,7 @@ Some code/libraries are used in the project:
android-xmlrpc android-xmlrpc
pskink et al. (Apache License, Version 2.0) pskink et al. (Apache License, Version 2.0)
http://code.google.com/p/android-xmlrpc/ http://code.google.com/p/android-xmlrpc/
android-ColorPickerPreference
Daniel Nilsson and Sergey Margaritov (Apache License, Version 2.0)
https://github.com/attenzione/android-ColorPickerPreference

76
android/res/layout-land/dialog_color_picker.xml

@ -0,0 +1,76 @@
<?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:paddingLeft="5dp"
android:paddingRight="5dp"
android:orientation="horizontal">
<net.margaritov.preference.colorpicker.ColorPickerView
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="landscape"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/press_color_to_apply"
android:gravity="center"
android:layout_marginTop="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="5dp"
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:text="↓"
android:textSize="20sp"
android:gravity="center"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
/>
<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>

77
android/res/layout/dialog_color_picker.xml

@ -0,0 +1,77 @@
<?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:paddingLeft="5dp"
android:paddingRight="5dp"
android:orientation="vertical">
<net.margaritov.preference.colorpicker.ColorPickerView
android:id="@+id/color_picker_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:tag="portrait"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/press_color_to_apply"
android:gravity="left"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="5dp"
android:textAppearance="?android:attr/textAppearanceSmall"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_below="@id/color_picker_view"
android:layout_marginBottom="10dp">
<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:text="→"
android:textSize="20sp"
android:gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
/>
<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>

5
android/res/values/strings.xml

@ -216,6 +216,8 @@
<string name="pref_alarmsounduri_info">Notification sound to play with alarm</string> <string name="pref_alarmsounduri_info">Notification sound to play with alarm</string>
<string name="pref_alarmvibrate">Enable vibration</string> <string name="pref_alarmvibrate">Enable vibration</string>
<string name="pref_alarmvibrate_info">Vibrate on alarm</string> <string name="pref_alarmvibrate_info">Vibrate on alarm</string>
<string name="pref_alarmcolour">Notification LED colour</string>
<string name="pref_alarmcolour_info">If supported by your device</string>
<string name="pref_checkrssfeeds">Check RSS feeds</string> <string name="pref_checkrssfeeds">Check RSS feeds</string>
<string name="pref_checkrssfeeds_info">Alarm when new torrents are available</string> <string name="pref_checkrssfeeds_info">Alarm when new torrents are available</string>
<string name="pref_adwnotify">Enable ADW notifications</string> <string name="pref_adwnotify">Enable ADW notifications</string>
@ -324,6 +326,9 @@
<string name="rss_loading_feed">Loading RSS feed</string> <string name="rss_loading_feed">Loading RSS feed</string>
<string name="rss_no_items">Connected, but the RSS feed is empty</string> <string name="rss_no_items">Connected, but the RSS feed is empty</string>
<string name="dialog_color_picker">Color Picker</string>
<string name="press_color_to_apply">Press on Color to apply</string>
<string name="error_httperror">Error during communication with server</string> <string name="error_httperror">Error during communication with server</string>
<string name="error_jsonrequesterror">Error building request</string> <string name="error_jsonrequesterror">Error building request</string>
<string name="error_jsonresponseerror">Error parsing of server response (please check your settings)</string> <string name="error_jsonresponseerror">Error parsing of server response (please check your settings)</string>

128
android/src/net/margaritov/preference/colorpicker/AlphaPatternDrawable.java

@ -0,0 +1,128 @@
/*
* 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;
}
}
}

129
android/src/net/margaritov/preference/colorpicker/ColorPickerDialog.java

@ -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 org.transdroid.R;
import android.app.Dialog;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class ColorPickerDialog
extends
Dialog
implements
ColorPickerView.OnColorChangedListener,
View.OnClickListener {
private ColorPickerView mColorPicker;
private ColorPickerPanelView mOldColor;
private ColorPickerPanelView mNewColor;
private OnColorChangedListener mListener;
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 branding.
getWindow().setFormat(PixelFormat.RGBA_8888);
setUp(color);
}
private void setUp(int color) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.dialog_color_picker, null);
setContentView(layout);
setTitle(R.string.dialog_color_picker);
mColorPicker = (ColorPickerView) layout.findViewById(R.id.color_picker_view);
mOldColor = (ColorPickerPanelView) layout.findViewById(R.id.old_color_panel);
mNewColor = (ColorPickerPanelView) layout.findViewById(R.id.new_color_panel);
((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 (mListener != null) {
mListener.onColorChanged(color);
}
*/
}
public void setAlphaSliderVisible(boolean visible) {
mColorPicker.setAlphaSliderVisible(visible);
}
/**
* 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();
}
}

171
android/src/net/margaritov/preference/colorpicker/ColorPickerPanelView.java

@ -0,0 +1,171 @@
/*
* 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;
}
}

246
android/src/net/margaritov/preference/colorpicker/ColorPickerPreference.java

@ -0,0 +1,246 @@
/*
* 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.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Bitmap.Config;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
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;
int mDefaultValue = Color.BLACK;
private int mValue = Color.BLACK;
private float mDensity = 0;
private boolean mAlphaSliderEnabled = false;
private static final String androidns = "http://schemas.android.com/apk/res/android";
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);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
onColorChanged(restoreValue ? getValue() : (Integer) defaultValue);
}
private void init(Context context, AttributeSet attrs) {
mDensity = getContext().getResources().getDisplayMetrics().density;
setOnPreferenceClickListener(this);
if (attrs != null) {
String defaultValue = attrs.getAttributeValue(androidns, "defaultValue");
if (defaultValue.startsWith("#")) {
try {
mDefaultValue = convertToColorInt(defaultValue);
} catch (NumberFormatException e) {
Log.e("ColorPickerPreference", "Wrong color: " + defaultValue);
mDefaultValue = convertToColorInt("#FF000000");
}
} else {
int resourceId = attrs.getAttributeResourceValue(androidns, "defaultValue", 0);
if (resourceId != 0) {
mDefaultValue = context.getResources().getInteger(resourceId);
}
}
mAlphaSliderEnabled = attrs.getAttributeBooleanValue(null, "alphaSlider", false);
}
mValue = mDefaultValue;
}
@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);
iView.setBackgroundDrawable(new AlphaPatternDrawable((int)(5 * mDensity)));
iView.setImageBitmap(getPreviewBitmap());
}
private Bitmap getPreviewBitmap() {
int d = (int) (mDensity * 31); //30dip
int color = getValue();
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;
}
public int getValue() {
try {
if (isPersistent()) {
mValue = getPersistedInt(mDefaultValue);
}
} catch (ClassCastException e) {
mValue = mDefaultValue;
}
return mValue;
}
@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) {
ColorPickerDialog picker = new ColorPickerDialog(getContext(), getValue());
picker.setOnColorChangedListener(this);
if (mAlphaSliderEnabled) {
picker.setAlphaSliderVisible(true);
}
picker.show();
return false;
}
/**
* Toggle Alpha Slider visibility (by default it's disabled)
* @param enable
*/
public void setAlphaSliderEnabled(boolean enable) {
mAlphaSliderEnabled = 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;
}
/**
* For custom purposes. Not used by ColorPickerPreferrence
* @param argb
* @throws NumberFormatException
* @author Unknown
*/
public static int convertToColorInt(String argb) throws NumberFormatException {
if (argb.startsWith("#")) {
argb = argb.replace("#", "");
}
int alpha = -1, red = -1, green = -1, blue = -1;
if (argb.length() == 8) {
alpha = Integer.parseInt(argb.substring(0, 2), 16);
red = Integer.parseInt(argb.substring(2, 4), 16);
green = Integer.parseInt(argb.substring(4, 6), 16);
blue = Integer.parseInt(argb.substring(6, 8), 16);
}
else if (argb.length() == 6) {
alpha = 255;
red = Integer.parseInt(argb.substring(0, 2), 16);
green = Integer.parseInt(argb.substring(2, 4), 16);
blue = Integer.parseInt(argb.substring(4, 6), 16);
}
return Color.argb(alpha, red, green, blue);
}
}

952
android/src/net/margaritov/preference/colorpicker/ColorPickerView.java

@ -0,0 +1,952 @@
/*
* 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.Point;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
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);
int red = Color.red(color);
int blue = Color.blue(color);
int green = Color.green(color);
float[] hsv = new float[3];
Color.RGBToHSV(red, green, blue, 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 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;
}
}

5
android/src/org/transdroid/gui/DetailsFragment.java

@ -529,6 +529,11 @@ public class DetailsFragment extends Fragment implements IDaemonCallback, OnSele
* } } * } }
*/ */
@Override
public boolean isAttached() {
return getActivity() != null;
}
@Override @Override
public void onQueueEmpty() { public void onQueueEmpty() {
// No active task: turn off status indicator // No active task: turn off status indicator

5
android/src/org/transdroid/gui/TaskResultHandler.java

@ -91,4 +91,9 @@ public class TaskResultHandler extends Handler implements IDaemonCallback {
sendMessage(msg); sendMessage(msg);
} }
@Override
public boolean isAttached() {
return callback.isAttached();
}
} }

8
android/src/org/transdroid/gui/TorrentsFragment.java

@ -1593,6 +1593,11 @@ public class TorrentsFragment extends Fragment implements IDaemonCallback, OnTou
return ""; return "";
} }
@Override
public boolean isAttached() {
return getActivity() != null;
}
@Override @Override
public void onTaskFailure(DaemonTaskFailureResult result) { public void onTaskFailure(DaemonTaskFailureResult result) {
@ -1970,7 +1975,8 @@ public class TorrentsFragment extends Fragment implements IDaemonCallback, OnTou
private void setProgressBar(boolean b) { private void setProgressBar(boolean b) {
inProgress = b; inProgress = b;
getSupportActivity().invalidateOptionsMenu(); if (getSupportActivity() != null)
getSupportActivity().invalidateOptionsMenu();
} }
protected View findViewById(int id) { protected View findViewById(int id) {

12
android/src/org/transdroid/preferences/Preferences.java

@ -127,12 +127,13 @@ public class Preferences {
public static final String KEY_PREF_ALARMPLAYSOUND = "transdroid_alarm_playsound"; public static final String KEY_PREF_ALARMPLAYSOUND = "transdroid_alarm_playsound";
public static final String KEY_PREF_ALARMSOUNDURI = "transdroid_alarm_sounduri"; public static final String KEY_PREF_ALARMSOUNDURI = "transdroid_alarm_sounduri";
public static final String KEY_PREF_ALARMVIBRATE = "transdroid_alarm_vibrate"; public static final String KEY_PREF_ALARMVIBRATE = "transdroid_alarm_vibrate";
public static final String KEY_PREF_ADWNOTIFY = "transdroid_alarm_adwnotify"; public static final String KEY_PREF_ALARMCOLOUR = "transdroid_alarm_colour";
public static final String KEY_PREF_ADWONLYDL = "transdroid_alarm_adwonlydl"; public static final String KEY_PREF_ADWNOTIFY = "transdroid_alarm_adwnotify";
public static final String KEY_PREF_ADWONLYDL = "transdroid_alarm_adwonlydl";
public static final String KEY_WIDGET_DAEMON = "transdroid_widget_daemon"; public static final String KEY_WIDGET_DAEMON = "transdroid_widget_daemon";
public static final String KEY_WIDGET_REFRESH = "transdroid_widget_refresh"; public static final String KEY_WIDGET_REFRESH = "transdroid_widget_refresh";
public static final String KEY_WIDGET_LAYOUT = "transdroid_widget_layout"; public static final String KEY_WIDGET_LAYOUT = "transdroid_widget_layout";
/** /**
* Determines the order number of the last used daemon settings object * Determines the order number of the last used daemon settings object
@ -918,6 +919,7 @@ public class Preferences {
prefs.getBoolean(KEY_PREF_ALARMPLAYSOUND, false), prefs.getBoolean(KEY_PREF_ALARMPLAYSOUND, false),
prefs.getString(KEY_PREF_ALARMSOUNDURI, null), prefs.getString(KEY_PREF_ALARMSOUNDURI, null),
prefs.getBoolean(KEY_PREF_ALARMVIBRATE, false), prefs.getBoolean(KEY_PREF_ALARMVIBRATE, false),
prefs.getInt(KEY_PREF_ALARMCOLOUR, 0xff7dbb21),
prefs.getBoolean(KEY_PREF_ADWNOTIFY, false), prefs.getBoolean(KEY_PREF_ADWNOTIFY, false),
prefs.getBoolean(KEY_PREF_ADWONLYDL, false)); prefs.getBoolean(KEY_PREF_ADWONLYDL, false));
} }

19
android/src/org/transdroid/preferences/PreferencesAlarm.java

@ -17,6 +17,8 @@
*/ */
package org.transdroid.preferences; package org.transdroid.preferences;
import net.margaritov.preference.colorpicker.ColorPickerPreference;
import org.transdroid.R; import org.transdroid.R;
import org.transdroid.service.BootReceiver; import org.transdroid.service.BootReceiver;
@ -39,6 +41,7 @@ public class PreferencesAlarm extends PreferenceActivity {
private TransdroidCheckBoxPreference alarmPlaySound; private TransdroidCheckBoxPreference alarmPlaySound;
private TransdroidNotificationListPreference alarmSoundURI; private TransdroidNotificationListPreference alarmSoundURI;
private TransdroidCheckBoxPreference alarmVibrate; private TransdroidCheckBoxPreference alarmVibrate;
private ColorPickerPreference alarmColour;
private TransdroidCheckBoxPreference adwNotify; private TransdroidCheckBoxPreference adwNotify;
private TransdroidCheckBoxPreference adwOnlyDl; private TransdroidCheckBoxPreference adwOnlyDl;
@ -78,14 +81,14 @@ public class PreferencesAlarm extends PreferenceActivity {
checkRssFeeds.setKey(Preferences.KEY_PREF_CHECKRSSFEEDS); checkRssFeeds.setKey(Preferences.KEY_PREF_CHECKRSSFEEDS);
checkRssFeeds.setEnabled(isEnabled); checkRssFeeds.setEnabled(isEnabled);
getPreferenceScreen().addItemFromInflater(checkRssFeeds); getPreferenceScreen().addItemFromInflater(checkRssFeeds);
// alarm play sound // Alarm play sound
alarmPlaySound = new TransdroidCheckBoxPreference(this); alarmPlaySound = new TransdroidCheckBoxPreference(this);
alarmPlaySound.setTitle(R.string.pref_alarmplaysound); alarmPlaySound.setTitle(R.string.pref_alarmplaysound);
alarmPlaySound.setSummary(R.string.pref_alarmplaysound_info); alarmPlaySound.setSummary(R.string.pref_alarmplaysound_info);
alarmPlaySound.setKey(Preferences.KEY_PREF_ALARMPLAYSOUND); alarmPlaySound.setKey(Preferences.KEY_PREF_ALARMPLAYSOUND);
alarmPlaySound.setEnabled(isEnabled); alarmPlaySound.setEnabled(isEnabled);
getPreferenceScreen().addItemFromInflater(alarmPlaySound); getPreferenceScreen().addItemFromInflater(alarmPlaySound);
// alarm sound URI // Alarm sound URI
alarmSoundURI = new TransdroidNotificationListPreference(this); alarmSoundURI = new TransdroidNotificationListPreference(this);
alarmSoundURI.setTitle(R.string.pref_alarmsounduri); alarmSoundURI.setTitle(R.string.pref_alarmsounduri);
alarmSoundURI.setSummary(R.string.pref_alarmsounduri_info); alarmSoundURI.setSummary(R.string.pref_alarmsounduri_info);
@ -95,13 +98,22 @@ public class PreferencesAlarm extends PreferenceActivity {
alarmSoundURI.setShowSilent(false); alarmSoundURI.setShowSilent(false);
alarmSoundURI.setEnabled(isEnabled); alarmSoundURI.setEnabled(isEnabled);
getPreferenceScreen().addItemFromInflater(alarmSoundURI); getPreferenceScreen().addItemFromInflater(alarmSoundURI);
// vibrate // Vibrate
alarmVibrate = new TransdroidCheckBoxPreference(this); alarmVibrate = new TransdroidCheckBoxPreference(this);
alarmVibrate.setTitle(R.string.pref_alarmvibrate); alarmVibrate.setTitle(R.string.pref_alarmvibrate);
alarmVibrate.setSummary(R.string.pref_alarmvibrate_info); alarmVibrate.setSummary(R.string.pref_alarmvibrate_info);
alarmVibrate.setKey(Preferences.KEY_PREF_ALARMVIBRATE); alarmVibrate.setKey(Preferences.KEY_PREF_ALARMVIBRATE);
alarmVibrate.setEnabled(isEnabled); alarmVibrate.setEnabled(isEnabled);
getPreferenceScreen().addItemFromInflater(alarmVibrate); getPreferenceScreen().addItemFromInflater(alarmVibrate);
// Notification LED colour
alarmColour = new ColorPickerPreference(this);
alarmColour.setTitle(R.string.pref_alarmcolour);
alarmColour.setSummary(R.string.pref_alarmcolour_info);
alarmColour.setKey(Preferences.KEY_PREF_ALARMCOLOUR);
alarmColour.setAlphaSliderEnabled(false);
alarmColour.setDefaultValue(0xff7dbb21);
alarmColour.setEnabled(isEnabled);
getPreferenceScreen().addItemFromInflater(alarmColour);
// Enable ADW notifications // Enable ADW notifications
adwNotify = new TransdroidCheckBoxPreference(this); adwNotify = new TransdroidCheckBoxPreference(this);
adwNotify.setTitle(R.string.pref_adwnotify); adwNotify.setTitle(R.string.pref_adwnotify);
@ -153,6 +165,7 @@ public class PreferencesAlarm extends PreferenceActivity {
alarmPlaySound.setEnabled(isEnabled); alarmPlaySound.setEnabled(isEnabled);
alarmSoundURI.setEnabled(isEnabled); alarmSoundURI.setEnabled(isEnabled);
alarmVibrate.setEnabled(isEnabled); alarmVibrate.setEnabled(isEnabled);
alarmColour.setEnabled(isEnabled);
adwNotify.setEnabled(isEnabled); adwNotify.setEnabled(isEnabled);
adwOnlyDl.setEnabled(isEnabled && isAdwEnabled); adwOnlyDl.setEnabled(isEnabled && isAdwEnabled);
} }

11
android/src/org/transdroid/service/AlarmService.java

@ -314,15 +314,22 @@ public class AlarmService extends IntentService {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
} }
//if sound enabled add to notification // If sound enabled add to notification
if (settings.getAlarmPlaySound() && settings.getAlarmSoundURI() != null) { if (settings.getAlarmPlaySound() && settings.getAlarmSoundURI() != null) {
newNotification.sound = Uri.parse(settings.getAlarmSoundURI()); newNotification.sound = Uri.parse(settings.getAlarmSoundURI());
} }
//if vibration enabled add to notification // If vibration enabled add to notification
if (settings.getAlarmVibrate()) { if (settings.getAlarmVibrate()) {
newNotification.defaults = Notification.DEFAULT_VIBRATE; newNotification.defaults = Notification.DEFAULT_VIBRATE;
} }
// Add coloured light; defaults to 0xff7dbb21
newNotification.ledARGB = settings.getAlarmColour();
newNotification.ledOnMS = 600;
newNotification.ledOffMS = 1000;
newNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
// Send notification // Send notification
notificationManager.notify(notifyID, newNotification); notificationManager.notify(notifyID, newNotification);

8
android/src/org/transdroid/service/AlarmSettings.java

@ -31,16 +31,18 @@ public class AlarmSettings{
private boolean alarmPlaySound; private boolean alarmPlaySound;
private String alarmSoundURI; private String alarmSoundURI;
private boolean alarmVibrate; private boolean alarmVibrate;
private int alarmColour;
private boolean adwNotify; private boolean adwNotify;
private boolean adwOnlyDl; private boolean adwOnlyDl;
public AlarmSettings(boolean enableAlarm, int alarmInterval, boolean checkRssFeeds, boolean alarmPlaySound, String alarmSoundURI, boolean alarmVibrate, boolean adwNotify, boolean adwOnlyDl) { public AlarmSettings(boolean enableAlarm, int alarmInterval, boolean checkRssFeeds, boolean alarmPlaySound, String alarmSoundURI, boolean alarmVibrate, int alarmColour, boolean adwNotify, boolean adwOnlyDl) {
this.enableAlarm = enableAlarm; this.enableAlarm = enableAlarm;
this.alarmInterval = alarmInterval; this.alarmInterval = alarmInterval;
this.checkRssFeeds = checkRssFeeds; this.checkRssFeeds = checkRssFeeds;
this.alarmPlaySound = alarmPlaySound; this.alarmPlaySound = alarmPlaySound;
this.alarmSoundURI = alarmSoundURI; this.alarmSoundURI = alarmSoundURI;
this.alarmVibrate = alarmVibrate; this.alarmVibrate = alarmVibrate;
this.alarmColour = alarmColour;
this.adwNotify = adwNotify; this.adwNotify = adwNotify;
this.adwOnlyDl = adwOnlyDl; this.adwOnlyDl = adwOnlyDl;
} }
@ -73,6 +75,10 @@ public class AlarmSettings{
return alarmVibrate; return alarmVibrate;
} }
public int getAlarmColour() {
return alarmColour;
}
public boolean showAdwNotifications() { public boolean showAdwNotifications() {
return adwNotify; return adwNotify;
} }

2
lib/.classpath

@ -2,6 +2,6 @@
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="lib" path="/home/eric/Dev/android-sdk/platforms/android-13/android.jar"/> <classpathentry kind="lib" path="/var/data/Dev/android-sdk/platforms/android-13/android.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

2
lib/src/org/transdroid/daemon/IDaemonCallback.java

@ -39,4 +39,6 @@ public interface IDaemonCallback {
void onTaskSuccess(DaemonTaskSuccessResult result); void onTaskSuccess(DaemonTaskSuccessResult result);
boolean isAttached();
} }

8
lib/src/org/transdroid/daemon/TaskQueue.java

@ -156,17 +156,19 @@ public class TaskQueue implements Runnable {
return; return;
} }
callback.onQueuedTaskStarted(task); if (callback.isAttached())
callback.onQueuedTaskStarted(task);
// Ask the daemon adapter to perform the task (which does it synchronously) // Ask the daemon adapter to perform the task (which does it synchronously)
DLog.d(LOG_NAME, "Starting task: " + task.toString()); DLog.d(LOG_NAME, "Starting task: " + task.toString());
DaemonTaskResult result = task.execute(); DaemonTaskResult result = task.execute();
callback.onQueuedTaskFinished(task); if (callback.isAttached())
callback.onQueuedTaskFinished(task);
// Return the result (to the UI thread) // Return the result (to the UI thread)
DLog.d(LOG_NAME, "Task result: " + (result == null? "null": result.toString())); DLog.d(LOG_NAME, "Task result: " + (result == null? "null": result.toString()));
if (result != null && !this.paused) { if (result != null && !this.paused && callback.isAttached()) {
if (result.wasSuccessful()) { if (result.wasSuccessful()) {
callback.onTaskSuccess((DaemonTaskSuccessResult) result); callback.onTaskSuccess((DaemonTaskSuccessResult) result);
} else { } else {

Loading…
Cancel
Save