package org.geogebra.web.web.gui.view.dataCollection.Settings;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import org.geogebra.common.gui.SetLabels;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.main.Localization;
import org.geogebra.common.plugin.SensorLogger.Types;
import org.geogebra.web.html5.main.AppW;
import org.geogebra.web.web.css.GuiResources;
import org.geogebra.web.web.gui.images.AppResources;
import org.geogebra.web.web.gui.view.dataCollection.DataCollectionView;
import org.geogebra.web.web.gui.view.dataCollection.GeoListBox;
import org.geogebra.web.web.main.AppWFull;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.ToggleButton;
/**
* Settings for a sensor group
*/
public abstract class SensorSetting extends FlowPanel implements SetLabels {
private final static String REAL_FREQUENCY = "ActualFrequency";
/** caption */
protected String captionString;
/** Panel with an image to show if sensor is on or off */
private SimplePanel sensorOnOff;
/** A label with the caption */
protected Label captionLabel;
/** button to collapse/expand settings for this sensor */
ToggleButton collapse;
private Image sensorON;
private Image sensorOFF;
private boolean sensorIsOn = false;
/**
* panel with the name of the sensor data and the listbox with the depending
* geoElement
*/
FlowPanel dataValues;
/** the listBoxes */
private ArrayList<GeoListBox> listBoxes = new ArrayList<GeoListBox>();
/**
* the label and string of the caption for translations after changing the
* language
*/
protected HashMap<Label, String> rowCaptions = new HashMap<Label, String>();
/** application */
protected AppW app;
private DataCollectionView view;
private String unit;
private Label realFreqLabel;
private int realFreq;
private FlowPanel realFreqContainer;
/** localization */
protected Localization loc;
/**
*
* @param app
* {@link AppW}
* @param dataView
* {@link DataCollectionView}
* @param captionString
* the String to look up for translations
* @param unit
* unit of the sensor values
*/
public SensorSetting(AppW app, DataCollectionView dataView,
String captionString, String unit) {
this.captionString = captionString;
this.app = app;
this.loc = app.getLocalization();
this.view = dataView;
this.unit = unit;
createGUI();
}
private void createGUI() {
this.dataValues = new FlowPanel();
this.dataValues.addStyleName("panelIndent");
addCaption();
addFrequencyPanel();
addContent();
this.add(dataValues);
}
/**
* adds a panel to show the "real" frequency
*/
protected void addFrequencyPanel() {
this.realFreqContainer = new FlowPanel();
this.realFreqContainer.addStyleName("rowContainer");
this.realFreqLabel = new Label(loc.getMenu(REAL_FREQUENCY) + ": "
+ this.realFreq);
this.realFreqContainer.add(this.realFreqLabel);
this.dataValues.add(this.realFreqContainer);
setRealFreqVisible(false);
}
/** fill the panel */
protected abstract void addContent();
/**
* panel with a {@link #sensorOnOff "sensor-on-off" button}, a
* {@link #captionLabel label} with the name of the sensor and a
* {@link #collapse button} to expand/collapse the settings for this sensor.
* if sensor is turned off, it stops logging the data values of this sensor.
*/
private void addCaption() {
FlowPanel caption = new FlowPanel();
caption.addStyleName("panelTitle");
this.captionLabel = new Label();
updateCaptionLabel();
collapse = new ToggleButton(
new Image(GuiResources.INSTANCE.collapse()), new Image(
GuiResources.INSTANCE.expand()));
collapse.addStyleName("collapse");
collapse.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
dataValues.setVisible(!collapse.isDown());
}
});
sensorOnOff = new SimplePanel();
sensorON = new Image(AppResources.INSTANCE.shown());
sensorOFF = new Image(AppResources.INSTANCE.hidden());
sensorOnOff.add(sensorOFF);
sensorOnOff.addStyleName("sensorOnOffButton");
caption.add(sensorOnOff);
caption.add(this.captionLabel);
caption.add(collapse);
this.add(caption);
}
/**
* A row is used for one "sensor value" (e.g. Ax, Ay or Az). It contains the
* name of the sensor value and a {@link GeoListBox} to choose an element to
* which the received values should be logged.
*
* @param rowCaption
* caption
* @param type
* {@link Types}
*/
protected void addRow(String rowCaption, Types type) {
FlowPanel container = new FlowPanel();
container.addStyleName("rowContainer");
Label rowCaptionLabel = new Label();
container.add(rowCaptionLabel);
rowCaptions.put(rowCaptionLabel, rowCaption);
GeoListBox listBox = new GeoListBox(type, this, app,
this.view.getDataSettings());
listBox.addChangeHandler(this.view);
this.listBoxes.add(listBox);
container.add(listBox);
dataValues.add(container);
updateContent();
}
/**
* updates the entries for all {@link GeoListBox listBoxes}
*
* @param availableObjects
* {@link ArrayList}
* @param usedObjects
* {@link ArrayList}
*/
public void updateAllBoxes(ArrayList<GeoElement> availableObjects,
ArrayList<GeoElement> usedObjects) {
for (GeoListBox box : this.listBoxes) {
updateBox(box, availableObjects, usedObjects);
}
}
/**
* updates all {@link GeoListBox listBoxes} except the given one.
*
* @param listBox
* {@link GeoListBox}
* @param availableObjects
* {@link ArrayList}
* @param usedObjects
* {@link ArrayList}
*/
public void updateOtherBoxes(GeoListBox listBox,
ArrayList<GeoElement> availableObjects,
ArrayList<GeoElement> usedObjects) {
for (GeoListBox box : this.listBoxes) {
if (box != listBox) {
updateBox(box, availableObjects, usedObjects);
}
}
}
/**
* updates the entries of the given {@link GeoListBox}
*
* @param box
* @param availableObjects
* @param usedObjects
* {@link ArrayList}
*/
private static void updateBox(GeoListBox box,
ArrayList<GeoElement> availableObjects,
ArrayList<GeoElement> usedObjects) {
GeoElement selectedElem = box.getSelection();
box.clear();
if (selectedElem != null && usedObjects.contains(selectedElem)) {
box.addItem(selectedElem);
box.setSelection(selectedElem);
box.setSelectedIndex(box.getFirstFreeGeoListBoxIndex());
} else {
box.setSelection(null);
}
for (GeoElement elem : availableObjects) {
box.addItem(elem);
}
}
/**
*
* @return {@code true} if sensor is turned on
*/
public boolean isOn() {
return this.sensorIsOn;
}
/**
* @return list of all {@link GeoListBox geoListBoxes} of this sensor
*/
public ArrayList<GeoListBox> getListBoxes() {
return this.listBoxes;
}
@Override
public void setLabels() {
updateCaptionLabel();
// is null for TimeSetting
if (this.realFreqLabel != null) {
this.realFreqLabel.setText(loc.getMenu(REAL_FREQUENCY) + ": "
+ this.realFreq);
}
updateContent();
}
/**
* update text of the content
*/
private void updateContent() {
for (Entry<Label, String> entry : this.rowCaptions.entrySet()) {
Label label = entry.getKey();
label.setText(loc.getMenu(entry.getValue()));
}
}
/**
* sets the text of the {@link #captionLabel}
*/
protected void updateCaptionLabel() {
this.captionLabel.setText(
loc.getMenu(captionString) + " (" + loc.getMenu(this.unit)
+ ")");
}
/**
* updates the label of the "real" frequency
*
* @param freq
* int
*/
public void setRealFrequency(int freq) {
this.realFreq = freq;
this.realFreqLabel
.setText(loc.getMenu(REAL_FREQUENCY) + ": "
+ this.realFreq);
}
/**
* shows/hides the label with the "real" frequency
*
* @param visible
*/
private void setRealFreqVisible(boolean visible) {
if (this.realFreqContainer != null) {
this.realFreqContainer.setVisible(visible);
}
}
/**
* if sensor is set to ON the SensorLogger starts logging data for this
* sensor.
*
* @param flag
* {@code true} to turn sensor ON
*/
public void setOn(boolean flag) {
this.sensorIsOn = flag;
sensorOnOff.clear();
setRealFreqVisible(flag);
if (flag) {
sensorOnOff.add(sensorON);
for (GeoListBox listbox : listBoxes) {
if (listbox.getSelection() != null) {
((AppWFull) app).getDataCollection().registerGeo(
listbox.getType().toString(),
listbox.getSelection());
}
}
} else {
sensorOnOff.add(sensorOFF);
for (GeoListBox listbox : listBoxes) {
((AppWFull) app).getDataCollection()
.removeRegisteredGeo(listbox.getType());
}
}
}
}