package org.solovyev.android.calculator.plot;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.AppComponent;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.RemovalConfirmationDialog;
import org.solovyev.android.calculator.functions.BaseFunctionFragment;
import org.solovyev.android.calculator.functions.CppFunction;
import org.solovyev.android.plotter.Color;
import org.solovyev.android.plotter.PlotFunction;
import org.solovyev.android.plotter.PlotIconView;
import org.solovyev.android.plotter.Plotter;
import org.solovyev.android.plotter.meshes.MeshSpec;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import butterknife.Bind;
import jscl.math.function.CustomFunction;
import uz.shift.colorpicker.LineColorPicker;
import uz.shift.colorpicker.OnColorChangedListener;
public class PlotEditFunctionFragment extends BaseFunctionFragment
implements SeekBar.OnSeekBarChangeListener {
@Inject
Plotter plotter;
@Bind(R.id.fn_meshspec_views)
View meshSpecViews;
@Bind(R.id.fn_color_label)
TextView colorLabel;
@Bind(R.id.fn_color_picker)
LineColorPicker colorPicker;
@Bind(R.id.fn_linewidth_label)
TextView lineWidthLabel;
@Bind(R.id.fn_linewidth_seekbar)
SeekBar lineWidthSeekBar;
@Bind(R.id.fn_iconview)
PlotIconView iconView;
private PlotFunction plotFunction;
public PlotEditFunctionFragment() {
super(R.layout.fragment_plot_function_edit);
}
public static void show(@Nullable PlotFunction function, @Nonnull FragmentManager fm) {
App.showDialog(create(function), "plot-function-editor", fm);
}
@NonNull
public static PlotEditFunctionFragment create(@Nullable PlotFunction pf) {
final PlotEditFunctionFragment fragment = new PlotEditFunctionFragment();
if (pf != null && pf.function instanceof ExpressionFunction) {
final Bundle args = new Bundle();
final ExpressionFunction ef = (ExpressionFunction) pf.function;
final List<String> parameters = new ArrayList<>(((CustomFunction) ef.function).getParameterNames());
args.putParcelable(ARG_FUNCTION, CppFunction
.builder(ef.function.getName(),
((CustomFunction) ef.function).getContent())
.withParameters(parameters)
.withId(pf.function.getId())
.build());
fragment.setArguments(args);
}
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (function != null) {
plotFunction = plotter.getPlotData().get(function.getId());
if (plotFunction == null) {
dismiss();
}
}
}
@Override
protected void inject(@NonNull AppComponent component) {
super.inject(component);
component.inject(this);
}
@NonNull
@Override
protected View onCreateDialogView(@NonNull Context context, @NonNull LayoutInflater inflater,
@Nullable Bundle savedInstanceState) {
final View view = super.onCreateDialogView(context, inflater, savedInstanceState);
colorPicker.setOnColorChangedListener(new OnColorChangedListener() {
@Override
public void onColorChanged(int c) {
iconView.setMeshSpec(applyMeshSpec());
}
});
lineWidthSeekBar.setMax(MeshSpec.MAX_WIDTH - MeshSpec.MIN_WIDTH);
lineWidthSeekBar.setOnSeekBarChangeListener(this);
final int[] colors = MeshSpec.LightColors.asIntArray();
colorPicker.setColors(colors);
paramsView.setMaxParams(2);
// no descriptions for functions in plotter
descriptionLabel.setVisibility(View.GONE);
if (savedInstanceState == null) {
if (plotFunction != null) {
setupViews(plotFunction.meshSpec);
} else {
setupViews();
}
}
return view;
}
private void setupViews(@NonNull MeshSpec meshSpec) {
final int color = meshSpec.color.toInt();
final int[] colors = colorPicker.getColors();
final int i = indexOf(colors, color);
colorPicker.setSelectedColorPosition(Math.max(0, i));
lineWidthSeekBar.setProgress(meshSpec.width - MeshSpec.MIN_WIDTH);
iconView.setMeshSpec(meshSpec);
}
private void setupViews() {
colorPicker.setSelectedColorPosition(0);
lineWidthSeekBar.setProgress(MeshSpec.defaultWidth(getActivity()) - MeshSpec.MIN_WIDTH);
iconView.setMeshSpec(applyMeshSpec());
}
private static int indexOf(int[] integers, int integer) {
for (int i = 0; i < integers.length; i++) {
if (integers[i] == integer) {
return i;
}
}
return -1;
}
@NonNull
protected MeshSpec applyMeshSpec() {
final Color color = Color.create(colorPicker.getColor());
final int width = MeshSpec.MIN_WIDTH + lineWidthSeekBar.getProgress();
final MeshSpec meshSpec = MeshSpec.create(color, width);
meshSpec.pointsCount = PlotActivity.POINTS_COUNT;
return meshSpec;
}
protected boolean applyData(@Nonnull CppFunction function) {
try {
final ExpressionFunction expressionFunction =
new ExpressionFunction(function.toJsclBuilder().create());
final PlotFunction plotFunction = PlotFunction.create(expressionFunction,
applyMeshSpec());
final int id = function.getId();
if (id != CppFunction.NO_ID) {
plotter.update(id, plotFunction);
} else {
plotter.add(plotFunction);
}
return true;
} catch (RuntimeException e) {
setError(bodyLabel, e.getLocalizedMessage());
}
return false;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
iconView.setMeshSpec(applyMeshSpec());
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
protected void showRemovalDialog(@NonNull final CppFunction function) {
Check.isNotNull(plotFunction);
final String functionName = plotFunction.function.getName();
Check.isNotNull(functionName);
RemovalConfirmationDialog.showForFunction(getActivity(), functionName,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Check.isTrue(which == DialogInterface.BUTTON_POSITIVE);
plotter.remove(plotFunction);
dismiss();
}
});
}
}