new plotter
This commit is contained in:
parent
6af5239c6e
commit
05e9026048
@ -132,8 +132,6 @@ public final class CalculatorPreferences {
|
|||||||
|
|
||||||
public static class Graph {
|
public static class Graph {
|
||||||
public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true);
|
public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true);
|
||||||
public static final Preference<PlotLineColor> lineColorReal = StringPreference.newInstance("graph_line_color_real", PlotLineColor.white, PlotLineColor.class);
|
|
||||||
public static final Preference<PlotLineColor> lineColorImag = StringPreference.newInstance("graph_line_color_imag", PlotLineColor.blue, PlotLineColor.class);
|
|
||||||
public static final Preference<Boolean> plotImag = new BooleanPreference("graph_plot_imag", false);
|
public static final Preference<Boolean> plotImag = new BooleanPreference("graph_plot_imag", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,8 +187,6 @@ public final class CalculatorPreferences {
|
|||||||
applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits);
|
applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits);
|
||||||
|
|
||||||
applyDefaultPreference(preferences, Graph.interpolate);
|
applyDefaultPreference(preferences, Graph.interpolate);
|
||||||
applyDefaultPreference(preferences, Graph.lineColorImag);
|
|
||||||
applyDefaultPreference(preferences, Graph.lineColorReal);
|
|
||||||
applyDefaultPreference(preferences, Graph.plotImag);
|
applyDefaultPreference(preferences, Graph.plotImag);
|
||||||
applyDefaultPreference(preferences, History.showIntermediateCalculations);
|
applyDefaultPreference(preferences, History.showIntermediateCalculations);
|
||||||
applyDefaultPreference(preferences, Calculations.calculateOnFly);
|
applyDefaultPreference(preferences, Calculations.calculateOnFly);
|
||||||
|
@ -28,8 +28,6 @@ public class AndroidCalculatorPlotter implements CalculatorPlotter, SharedPrefer
|
|||||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.plotImag.getKey());
|
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.plotImag.getKey());
|
||||||
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.lineColorReal.getKey());
|
|
||||||
onSharedPreferenceChanged(preferences, CalculatorPreferences.Graph.lineColorImag.getKey());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -165,21 +163,5 @@ public class AndroidCalculatorPlotter implements CalculatorPlotter, SharedPrefer
|
|||||||
if (CalculatorPreferences.Graph.plotImag.getKey().equals(key)) {
|
if (CalculatorPreferences.Graph.plotImag.getKey().equals(key)) {
|
||||||
setPlotImag(CalculatorPreferences.Graph.plotImag.getPreference(preferences));
|
setPlotImag(CalculatorPreferences.Graph.plotImag.getPreference(preferences));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CalculatorPreferences.Graph.lineColorReal.getKey().equals(key)) {
|
|
||||||
setRealLineColor(CalculatorPreferences.Graph.lineColorReal.getPreference(preferences));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CalculatorPreferences.Graph.lineColorImag.getKey().equals(key)) {
|
|
||||||
setImagLineColor(CalculatorPreferences.Graph.lineColorImag.getPreference(preferences));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImagLineColor(@NotNull PlotLineColor imagLineColor) {
|
|
||||||
plotter.setImagLineColor(imagLineColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRealLineColor(@NotNull PlotLineColor realLineColor) {
|
|
||||||
plotter.setRealLineColor(realLineColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,6 @@
|
|||||||
a:title="@string/cpp_prefs_graph_plot_imag_title"
|
a:title="@string/cpp_prefs_graph_plot_imag_title"
|
||||||
a:summary="@string/cpp_prefs_graph_plot_imag_summary"/>
|
a:summary="@string/cpp_prefs_graph_plot_imag_summary"/>
|
||||||
|
|
||||||
<ListPreference a:key="graph_line_color_real"
|
|
||||||
a:title="@string/prefs_graph_real_color_title"
|
|
||||||
a:summary="@string/prefs_graph_real_color_summary"
|
|
||||||
a:entries="@array/cpp_plot_line_color_names"
|
|
||||||
a:entryValues="@array/cpp_plot_line_color_values"/>
|
|
||||||
|
|
||||||
<ListPreference a:key="graph_line_color_imag"
|
|
||||||
a:title="@string/prefs_graph_imag_color_title"
|
|
||||||
a:summary="@string/prefs_graph_imag_color_summary"
|
|
||||||
a:entries="@array/cpp_plot_line_color_names"
|
|
||||||
a:entryValues="@array/cpp_plot_line_color_values"/>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -34,7 +34,7 @@ public abstract class AbstractGraphCalculator implements GraphCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float yMin = graphsData.getLastYMin();
|
float yMin = graphsData.getLastYMin();
|
||||||
float yMax = graphsData.getLastYMin();
|
float yMax = graphsData.getLastYMax();
|
||||||
|
|
||||||
// prepare graph
|
// prepare graph
|
||||||
if (!graph.empty()) {
|
if (!graph.empty()) {
|
||||||
|
@ -154,11 +154,10 @@ public class CalculatorGraph2dView extends View implements GraphView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateGraphs() {
|
public void invalidateGraphs() {
|
||||||
|
graphsData.clear();
|
||||||
|
|
||||||
if (mDrawn) {
|
if (mDrawn) {
|
||||||
mDrawn = false;
|
mDrawn = false;
|
||||||
|
|
||||||
graphsData.clear();
|
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// Copyright (C) 2009 Mihai Preda
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -18,7 +16,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Graph3dView extends GLView implements GraphView {
|
public class CalculatorGraph3dView extends GLView implements GraphView {
|
||||||
|
|
||||||
private boolean useHighQuality3d = Build.VERSION.SDK_INT >= 5;
|
private boolean useHighQuality3d = Build.VERSION.SDK_INT >= 5;
|
||||||
|
|
||||||
@ -37,12 +35,12 @@ public class Graph3dView extends GLView implements GraphView {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private GraphViewHelper graphViewHelper = GraphViewHelper.newDefaultInstance();
|
private GraphViewHelper graphViewHelper = GraphViewHelper.newDefaultInstance();
|
||||||
|
|
||||||
public Graph3dView(Context context, AttributeSet attrs) {
|
public CalculatorGraph3dView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Graph3dView(Context context) {
|
public CalculatorGraph3dView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
touchHandler = new TouchHandler(this);
|
touchHandler = new TouchHandler(this);
|
||||||
init();
|
init();
|
@ -39,16 +39,20 @@ public class CalculatorPlotFragment extends AbstractCalculatorPlotFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( plotData.isPlot3d() ) {
|
if ( plotData.isPlot3d() ) {
|
||||||
graphView = new Graph3dView(getActivity());
|
graphView = new CalculatorGraph3dView(getActivity());
|
||||||
} else {
|
} else {
|
||||||
graphView = new CalculatorGraph2dView(getActivity());
|
graphView = new CalculatorGraph2dView(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo serso: investigate (after switching from 3d to 2d - blank screen)
|
||||||
|
|
||||||
graphView.init(PlotViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
|
graphView.init(PlotViewDef.newInstance(Color.WHITE, Color.WHITE, Color.DKGRAY, getBgColor()));
|
||||||
//graphView.setXRange((float)plotBoundaries.getXMin(), (float)plotBoundaries.getXMax());
|
//graphView.setXRange((float)plotBoundaries.getXMin(), (float)plotBoundaries.getXMax());
|
||||||
graphView.setPlotFunctions(plotData.getFunctions());
|
graphView.setPlotFunctions(plotData.getFunctions());
|
||||||
|
|
||||||
graphContainer.addView((View) graphView);
|
if (graphView instanceof View) {
|
||||||
|
graphContainer.addView((View) graphView);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,8 +62,4 @@ public interface CalculatorPlotter {
|
|||||||
void removeAllUnpinned();
|
void removeAllUnpinned();
|
||||||
|
|
||||||
void setPlotImag(boolean plotImag);
|
void setPlotImag(boolean plotImag);
|
||||||
|
|
||||||
void setRealLineColor(@NotNull PlotLineColor realLineColor);
|
|
||||||
|
|
||||||
void setImagLineColor(@NotNull PlotLineColor imagLineColor);
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final Calculator calculator;
|
private final Calculator calculator;
|
||||||
|
|
||||||
private final PlotResourceManager plotResourceManager = new PlotResourceManager();
|
private final PlotResourceManager resourceManager = new MapPlotResourceManager();
|
||||||
|
|
||||||
private boolean plot3d = false;
|
private boolean plot3d = false;
|
||||||
|
|
||||||
@ -35,12 +35,6 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
|
|
||||||
private int arity = 0;
|
private int arity = 0;
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private PlotLineColor realLineColor;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private PlotLineColor imagLineColor;
|
|
||||||
|
|
||||||
public CalculatorPlotterImpl(@NotNull Calculator calculator) {
|
public CalculatorPlotterImpl(@NotNull Calculator calculator) {
|
||||||
this.calculator = calculator;
|
this.calculator = calculator;
|
||||||
}
|
}
|
||||||
@ -84,13 +78,14 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private PlotFunction newPlotFunction(@NotNull XyFunction xyFunction) {
|
private PlotFunction newPlotFunction(@NotNull XyFunction xyFunction) {
|
||||||
return new PlotFunction(xyFunction);
|
return new PlotFunction(xyFunction, resourceManager.generateAndRegister());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addFunction(@NotNull PlotFunction plotFunction) {
|
public boolean addFunction(@NotNull PlotFunction plotFunction) {
|
||||||
synchronized (functions) {
|
synchronized (functions) {
|
||||||
if (!functions.contains(plotFunction)) {
|
if (!functions.contains(plotFunction)) {
|
||||||
|
resourceManager.register(plotFunction.getPlotLineDef());
|
||||||
functions.add(plotFunction);
|
functions.add(plotFunction);
|
||||||
onFunctionsChanged();
|
onFunctionsChanged();
|
||||||
return true;
|
return true;
|
||||||
@ -115,6 +110,8 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resourceManager.unregister(function.getPlotLineDef());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -137,7 +134,13 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
|
boolean changed = Iterables.removeIf(functions, new Predicate<PlotFunction>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@Nullable PlotFunction function) {
|
public boolean apply(@Nullable PlotFunction function) {
|
||||||
return function != null && !function.isPinned();
|
boolean removed = function != null && !function.isPinned();
|
||||||
|
|
||||||
|
if ( removed ) {
|
||||||
|
resourceManager.unregister(function.getPlotLineDef());
|
||||||
|
}
|
||||||
|
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -152,6 +155,7 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
synchronized (functions) {
|
synchronized (functions) {
|
||||||
boolean changed = functions.remove(plotFunction);
|
boolean changed = functions.remove(plotFunction);
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
resourceManager.unregister(plotFunction.getPlotLineDef());
|
||||||
onFunctionsChanged();
|
onFunctionsChanged();
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
@ -191,6 +195,10 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
for (int i = 0; i < functions.size(); i++) {
|
for (int i = 0; i < functions.size(); i++) {
|
||||||
final PlotFunction plotFunction = functions.get(i);
|
final PlotFunction plotFunction = functions.get(i);
|
||||||
if (plotFunction.equals(newFunction)) {
|
if (plotFunction.equals(newFunction)) {
|
||||||
|
|
||||||
|
resourceManager.unregister(plotFunction.getPlotLineDef());
|
||||||
|
resourceManager.register(newFunction.getPlotLineDef());
|
||||||
|
|
||||||
// update old function
|
// update old function
|
||||||
functions.set(i, newFunction);
|
functions.set(i, newFunction);
|
||||||
changed = true;
|
changed = true;
|
||||||
@ -246,6 +254,7 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
@Override
|
@Override
|
||||||
public void clearAllFunctions() {
|
public void clearAllFunctions() {
|
||||||
synchronized (functions) {
|
synchronized (functions) {
|
||||||
|
resourceManager.unregisterAll();
|
||||||
functions.clear();
|
functions.clear();
|
||||||
onFunctionsChanged();
|
onFunctionsChanged();
|
||||||
}
|
}
|
||||||
@ -357,16 +366,6 @@ public class CalculatorPlotterImpl implements CalculatorPlotter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRealLineColor(@NotNull PlotLineColor realLineColor) {
|
|
||||||
this.realLineColor = realLineColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setImagLineColor(@NotNull PlotLineColor imagLineColor) {
|
|
||||||
this.imagLineColor = imagLineColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean toggleImagFunctions(boolean show) {
|
private boolean toggleImagFunctions(boolean show) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 1/19/13
|
||||||
|
* Time: 12:48 AM
|
||||||
|
*/
|
||||||
|
public class MapPlotResourceManager implements PlotResourceManager {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Map<PlotLineDef, Integer> counters = new HashMap<PlotLineDef, Integer>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final List<PlotLineDef> preparedLineDefs = new ArrayList<PlotLineDef>(PlotLineStyle.values().length * PlotLineColor.values().length);
|
||||||
|
|
||||||
|
public MapPlotResourceManager() {
|
||||||
|
for (PlotLineStyle plotLineStyle : PlotLineStyle.values()) {
|
||||||
|
for (PlotLineColor plotLineColor : PlotLineColor.values()) {
|
||||||
|
preparedLineDefs.add(PlotLineDef.newInstance(plotLineColor.getColor(), plotLineStyle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PlotLineDef generateAndRegister() {
|
||||||
|
synchronized (this) {
|
||||||
|
for (PlotLineDef lineDef : preparedLineDefs) {
|
||||||
|
final Integer counter = counters.get(lineDef);
|
||||||
|
if ( counter == null || counter.equals(0) ) {
|
||||||
|
register0(lineDef);
|
||||||
|
return lineDef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return preparedLineDefs.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void increaseCounter(@NotNull PlotLineDef lineDef) {
|
||||||
|
assert Thread.holdsLock(this);
|
||||||
|
|
||||||
|
Integer counter = counters.get(lineDef);
|
||||||
|
if ( counter == null ) {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
counters.put(lineDef, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decreaseCounter(@NotNull PlotLineDef lineDef) {
|
||||||
|
assert Thread.holdsLock(this);
|
||||||
|
|
||||||
|
Integer counter = counters.get(lineDef);
|
||||||
|
if (counter != null) {
|
||||||
|
counter--;
|
||||||
|
counters.put(lineDef, Math.max(counter, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(@NotNull PlotLineDef lineDef) {
|
||||||
|
synchronized (this) {
|
||||||
|
// we should check if specified line def is not ours, i.e. created by this class
|
||||||
|
for (PlotLineDef preparedLineDef : preparedLineDefs) {
|
||||||
|
if ( preparedLineDef == lineDef ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register0(lineDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register0(@NotNull PlotLineDef lineDef) {
|
||||||
|
increaseCounter(lineDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregister(@NotNull PlotLineDef lineDef) {
|
||||||
|
synchronized (this) {
|
||||||
|
decreaseCounter(lineDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterAll() {
|
||||||
|
synchronized (this) {
|
||||||
|
counters.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -32,9 +32,8 @@ public class PlotFunction {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private PlotFunction copy() {
|
private PlotFunction copy() {
|
||||||
final PlotFunction copy = new PlotFunction(this.xyFunction);
|
final PlotFunction copy = new PlotFunction(this.xyFunction, this.plotLineDef);
|
||||||
|
|
||||||
copy.plotLineDef = this.plotLineDef;
|
|
||||||
copy.pinned = this.pinned;
|
copy.pinned = this.pinned;
|
||||||
copy.visible = this.visible;
|
copy.visible = this.visible;
|
||||||
|
|
||||||
|
@ -141,4 +141,28 @@ public class PlotLineDef {
|
|||||||
public PlotLineColorType getLineColorType() {
|
public PlotLineColorType getLineColorType() {
|
||||||
return lineColorType;
|
return lineColorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof PlotLineDef)) return false;
|
||||||
|
|
||||||
|
PlotLineDef that = (PlotLineDef) o;
|
||||||
|
|
||||||
|
if (lineColor != that.lineColor) return false;
|
||||||
|
if (Float.compare(that.lineWidth, lineWidth) != 0) return false;
|
||||||
|
if (lineColorType != that.lineColorType) return false;
|
||||||
|
if (lineStyle != that.lineStyle) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = lineColorType.hashCode();
|
||||||
|
result = 31 * result + lineColor;
|
||||||
|
result = 31 * result + lineStyle.hashCode();
|
||||||
|
result = 31 * result + (lineWidth != +0.0f ? Float.floatToIntBits(lineWidth) : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
package org.solovyev.android.calculator.plot;
|
package org.solovyev.android.calculator.plot;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 1/13/13
|
* Date: 1/13/13
|
||||||
* Time: 8:19 PM
|
* Time: 8:19 PM
|
||||||
*/
|
*/
|
||||||
class PlotResourceManager {
|
interface PlotResourceManager {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
PlotLineDef generateAndRegister();
|
||||||
|
|
||||||
|
void register(@NotNull PlotLineDef lineDef);
|
||||||
|
|
||||||
|
void unregister(@NotNull PlotLineDef lineDef);
|
||||||
|
|
||||||
|
void unregisterAll();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user