/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2016 HydroloGIS (www.hydrologis.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.library.core.dialogs;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;
import eu.geopaparazzi.library.R;
import eu.geopaparazzi.library.style.ColorStrokeObject;
import eu.geopaparazzi.library.style.ColorUtilities;
import eu.geopaparazzi.library.util.Compat;
/**
* Class to set color and stroke for shapes.
*
* @author Andrea Antonello
*/
public class ColorStrokeDialogFragment extends DialogFragment {
/**
* A simple interface to use to notify color and stroke changes.
*/
public interface IColorStrokePropertiesChangeListener {
/**
* Called when there is the need to notify that a change occurred.
*/
void onPropertiesChanged(ColorStrokeObject newColorStrokeObject);
}
private final static String PREFS_KEY_COLORPROPERTIES = "PREFS_KEY_COLORPROPERTIES";
private ImageView mWidthImageView;
private ColorStrokeObject mCurrentColorStrokeObject;
private TextView mWidthTextView;
private IColorStrokePropertiesChangeListener colorStrokePropertiesChangeListener;
private SeekBar mWidthSeekBar;
private boolean handlingFillColor;
private SeekBar mAlphaSeekBar;
private SeekBar mRedSeekBar;
private SeekBar mGreenSeekBar;
private SeekBar mBlueSeekBar;
private View mColorView;
// private ImageView mShapeSizeImageView;
private TextView mShapeSizeTextView;
private SeekBar mShapeSizeSeekBar;
private Spinner mShapeSpinner;
/**
* Create a dialog instance.
*
* @param colorStrokeObject object holding color and stroke info.
* @return the instance.
*/
public static ColorStrokeDialogFragment newInstance(ColorStrokeObject colorStrokeObject) {
ColorStrokeDialogFragment f = new ColorStrokeDialogFragment();
Bundle args = new Bundle();
args.putSerializable(PREFS_KEY_COLORPROPERTIES, colorStrokeObject);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ColorStrokeObject mInitialColorStrokeObject = (ColorStrokeObject) getArguments().getSerializable(PREFS_KEY_COLORPROPERTIES);
if (mInitialColorStrokeObject != null) {
mCurrentColorStrokeObject = mInitialColorStrokeObject.duplicate();
}
}
// create an AlertDialog and return it
@Override
public Dialog onCreateDialog(Bundle bundle) {
// create the dialog
AlertDialog.Builder builder =
new AlertDialog.Builder(getActivity());
View colorStrokeDialogView =
getActivity().getLayoutInflater().inflate(
R.layout.fragment_dialog_color_stroke, null);
builder.setView(colorStrokeDialogView); // add GUI to dialog
/*
* the shape size image
*/
if (!mCurrentColorStrokeObject.hasShape) {
View shapeSizeView = colorStrokeDialogView.findViewById(R.id.shapeSizeDialogGridLayout);
shapeSizeView.setVisibility(View.GONE);
} else {
// mShapeSizeImageView = (ImageView) colorStrokeDialogView.findViewById(R.id.shapeSizeImageView);
mShapeSizeTextView = (TextView) colorStrokeDialogView.findViewById(R.id.shapeSizeTextView);
mShapeSizeSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.shapeSizeSeekBar);
mShapeSizeSeekBar.setOnSeekBarChangeListener(shapeSizeChanged);
mShapeSizeSeekBar.setProgress(mCurrentColorStrokeObject.shapeSize);
mShapeSizeTextView.setText(String.valueOf(mCurrentColorStrokeObject.shapeSize));
mShapeSpinner = (Spinner) colorStrokeDialogView.findViewById(R.id.shape_spinner);
int count = mShapeSpinner.getCount();
for (int i = 0; i < count; i++) {
if (mShapeSpinner.getItemAtPosition(i).equals(mCurrentColorStrokeObject.shapeWKT)) {
mShapeSpinner.setSelection(i);
break;
}
}
mShapeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Object selectedItem = mShapeSpinner.getSelectedItem();
String shapeStr = selectedItem.toString();
mCurrentColorStrokeObject.shapeWKT = shapeStr;
}
public void onNothingSelected(AdapterView<?> arg0) {
// ignore
}
});
}
/*
* the stroke width image
*/
if (!mCurrentColorStrokeObject.hasStrokeWidth) {
View lineWidthView = colorStrokeDialogView.findViewById(R.id.lineWidthDialogGridLayout);
lineWidthView.setVisibility(View.GONE);
} else {
mWidthImageView = (ImageView) colorStrokeDialogView.findViewById(R.id.widthImageView);
mWidthTextView = (TextView) colorStrokeDialogView.findViewById(R.id.widthTextView);
mWidthSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.widthSeekBar);
mWidthSeekBar.setOnSeekBarChangeListener(lineWidthChanged);
mWidthSeekBar.setProgress(mCurrentColorStrokeObject.strokeWidth);
mWidthTextView.setText(String.valueOf(mCurrentColorStrokeObject.strokeWidth));
}
RadioButton fillRadioButton = (RadioButton) colorStrokeDialogView.findViewById(R.id.doFillRadioButton);
fillRadioButton.setChecked(true);
RadioGroup radioGroup = (RadioGroup) colorStrokeDialogView.findViewById(R.id.radioDo);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
onRadioButtonClicked(checkedId);
}
});
/*
* The fill/stroke color picker part
*/
TextView title2 = (TextView) colorStrokeDialogView.findViewById(R.id.title2);
if (!mCurrentColorStrokeObject.hasFill && !mCurrentColorStrokeObject.hasStroke) {
View colorView = colorStrokeDialogView.findViewById(R.id.colorDialogGridLayout);
colorView.setVisibility(View.GONE);
} else {
if (!mCurrentColorStrokeObject.hasFill || !mCurrentColorStrokeObject.hasStroke) {
View radioView = colorStrokeDialogView.findViewById(R.id.radioDoLayout);
radioView.setVisibility(View.GONE);
}
handlingFillColor = mCurrentColorStrokeObject.hasFill;
String title = "";
if (mCurrentColorStrokeObject.hasFill && mCurrentColorStrokeObject.hasStroke) {
title = getActivity().getString(R.string.fill_and_stroke_color_title);
} else if (mCurrentColorStrokeObject.hasFill) {
title = getActivity().getString(R.string.fill_color_title);
} else {
title = getActivity().getString(R.string.stroke_color_title);
}
title2.setText(title);
// get the color SeekBars and set their onChange listeners
mAlphaSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.alphaSeekBar);
mRedSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.redSeekBar);
mGreenSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.greenSeekBar);
mBlueSeekBar = (SeekBar) colorStrokeDialogView.findViewById(R.id.blueSeekBar);
mColorView = colorStrokeDialogView.findViewById(R.id.colorView);
// register SeekBar event listeners
mAlphaSeekBar.setOnSeekBarChangeListener(colorChangedListener);
mRedSeekBar.setOnSeekBarChangeListener(colorChangedListener);
mGreenSeekBar.setOnSeekBarChangeListener(colorChangedListener);
mBlueSeekBar.setOnSeekBarChangeListener(colorChangedListener);
int color = 0;
int alpha = 0;
if (handlingFillColor) {
color = mCurrentColorStrokeObject.fillColor;
alpha = mCurrentColorStrokeObject.fillAlpha;
} else {
color = mCurrentColorStrokeObject.strokeColor;
alpha = mCurrentColorStrokeObject.strokeAlpha;
}
// use current drawing color to set SeekBar values
mAlphaSeekBar.setProgress(alpha);
mRedSeekBar.setProgress(Color.red(color));
mGreenSeekBar.setProgress(Color.green(color));
mBlueSeekBar.setProgress(Color.blue(color));
final ColorUtilities[] availableColors = ColorUtilities.values();
GridView gridview = (GridView) colorStrokeDialogView.findViewById(R.id.availableColors);
ArrayAdapter<ColorUtilities> colorsAdapter = new ArrayAdapter<ColorUtilities>(getActivity(), android.R.layout.simple_list_item_1, availableColors) {
class ViewHolder {
Button button;
}
@Override
public View getView(final int position, View cView, ViewGroup parent) {
ViewHolder holder;
View rowView = cView;
if (rowView == null) {
LayoutInflater inflater = getActivity().getLayoutInflater();
rowView = inflater.inflate(R.layout.fragment_dialog_color_stroke_row, parent, false);
holder = new ViewHolder();
holder.button = (Button) rowView.findViewById(R.id.button);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
String hex = availableColors[position].getHex();
int color = ColorUtilities.toColor(hex);
holder.button.setBackgroundColor(color);
final Button b = holder.button;
holder.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int color = Color.TRANSPARENT;
Drawable background = b.getBackground();
if (background instanceof ColorDrawable)
color = ((ColorDrawable) background).getColor();
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
int argb = Color.argb(red, green, blue, mAlphaSeekBar.getProgress());
mColorView.setBackgroundColor(argb);
mRedSeekBar.setProgress(red);
mGreenSeekBar.setProgress(green);
mBlueSeekBar.setProgress(blue);
if (handlingFillColor) {
mCurrentColorStrokeObject.fillColor = Color.rgb(mRedSeekBar.getProgress(), mGreenSeekBar.getProgress(),
mBlueSeekBar.getProgress());
mCurrentColorStrokeObject.fillAlpha = mAlphaSeekBar.getProgress();
} else {
mCurrentColorStrokeObject.strokeColor = Color.rgb(mRedSeekBar.getProgress(), mGreenSeekBar.getProgress(),
mBlueSeekBar.getProgress());
mCurrentColorStrokeObject.strokeAlpha = mAlphaSeekBar.getProgress();
}
}
});
return rowView;
}
};
gridview.setAdapter(colorsAdapter);
}
// add Set Line Width Button
builder.setPositiveButton(R.string.set_properties,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (colorStrokePropertiesChangeListener != null) {
colorStrokePropertiesChangeListener.onPropertiesChanged(mCurrentColorStrokeObject);
}
}
}
);
builder.setNegativeButton(getString(android.R.string.cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
}
);
return builder.create(); // return dialog
}
public void onRadioButtonClicked(int id) {
// Check which radio button was clicked
if (id == R.id.doFillRadioButton) {
handlingFillColor = true;
} else {
handlingFillColor = false;
}
int fill;
int alpha;
if (handlingFillColor) {
fill = mCurrentColorStrokeObject.fillColor;
alpha = mCurrentColorStrokeObject.fillAlpha;
} else {
fill = mCurrentColorStrokeObject.strokeColor;
alpha = mCurrentColorStrokeObject.strokeAlpha;
}
int red = Color.red(fill);
int green = Color.green(fill);
int blue = Color.blue(fill);
int argb = Color.argb(red, green, blue, alpha);
mColorView.setBackgroundColor(argb);
mAlphaSeekBar.setProgress(alpha);
mRedSeekBar.setProgress(red);
mGreenSeekBar.setProgress(green);
mBlueSeekBar.setProgress(blue);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof IColorStrokePropertiesChangeListener) {
colorStrokePropertiesChangeListener = (IColorStrokePropertiesChangeListener) activity;
}
}
@Override
public void onDetach() {
super.onDetach();
colorStrokePropertiesChangeListener = null;
}
private final OnSeekBarChangeListener lineWidthChanged =
new OnSeekBarChangeListener() {
final Bitmap bitmap = Bitmap.createBitmap(
400, 100, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap); // draws into bitmap
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (progress == 0) progress = 1;
mCurrentColorStrokeObject.strokeWidth = progress;
int tmpColor = Color.BLACK;
// if (mCurrentColorStrokeObject.hasStroke)
// tmpColor = mCurrentColorStrokeObject.strokeColor;
// configure a Paint object for the current SeekBar value
Paint p = new Paint();
p.setColor(tmpColor);
p.setStrokeCap(Paint.Cap.ROUND);
p.setStrokeWidth(progress);
// erase the bitmap and redraw the line
bitmap.eraseColor(Compat.getColor(getContext(), android.R.color.transparent));
canvas.drawLine(30, 50, 370, 50, p);
mWidthImageView.setImageBitmap(bitmap);
mWidthTextView.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
} // required
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
} // required
};
private final OnSeekBarChangeListener shapeSizeChanged =
new OnSeekBarChangeListener() {
// int centerX = 200;
// int centerY = 50;
// final Bitmap bitmap = Bitmap.createBitmap(centerX * 2, centerY * 2, Bitmap.Config.ARGB_8888);
// final Canvas canvas = new Canvas(bitmap); // draws into bitmap
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (progress == 0) progress = 1;
mCurrentColorStrokeObject.shapeSize = progress;
// Paint p = new Paint();
// p.setColor(Color.BLACK);
// p.setStrokeCap(Paint.Cap.ROUND);
// p.setStrokeWidth(1);
//
// int delta = progress / 2;
// if (delta == 0) delta = 1;
//
// // erase the bitmap and redraw the line
// bitmap.eraseColor(Compat.getColor(getContext(),android.R.color.transparent, getContext().getTheme()));
// canvas.drawOval(centerX - delta, centerY + delta, centerX + delta, centerY - delta, p);
// mShapeSizeImageView.setImageBitmap(bitmap);
mShapeSizeTextView.setText(String.valueOf(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
} // required
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
} // required
};
private final OnSeekBarChangeListener colorChangedListener =
new OnSeekBarChangeListener() {
// display the updated color
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// if (fromUser) {// user, not program, changed SeekBar progress
int color = Color.argb(mAlphaSeekBar.getProgress(),
mRedSeekBar.getProgress(), mGreenSeekBar.getProgress(),
mBlueSeekBar.getProgress());
mColorView.setBackgroundColor(color);
if (handlingFillColor) {
mCurrentColorStrokeObject.fillColor = Color.rgb(mRedSeekBar.getProgress(), mGreenSeekBar.getProgress(),
mBlueSeekBar.getProgress());
mCurrentColorStrokeObject.fillAlpha = mAlphaSeekBar.getProgress();
} else {
mCurrentColorStrokeObject.strokeColor = Color.rgb(mRedSeekBar.getProgress(), mGreenSeekBar.getProgress(),
mBlueSeekBar.getProgress());
mCurrentColorStrokeObject.strokeAlpha = mAlphaSeekBar.getProgress();
}
// }
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
} // required
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
} // required
};
}