/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
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.
*/
package org.geogebra.web.web.gui.dialog;
import org.geogebra.common.euclidian.smallscreen.AdjustSlider;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.geos.GeoAngle;
import org.geogebra.common.kernel.geos.GeoAngle.AngleStyle;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoNumeric;
import org.geogebra.common.main.Feature;
import org.geogebra.common.main.Localization;
import org.geogebra.common.util.lang.Unicode;
import org.geogebra.web.html5.event.FocusListenerW;
import org.geogebra.web.html5.gui.GPopupPanel;
import org.geogebra.web.html5.gui.HasKeyboardPopup;
import org.geogebra.web.html5.gui.inputfield.AutoCompleteTextFieldW;
import org.geogebra.web.html5.main.AppW;
import org.geogebra.web.web.gui.properties.SliderPanelW;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Web dialog for slider creation
*/
public class SliderDialogW extends DialogBoxW
implements ClickHandler, ChangeHandler, ValueChangeHandler<Boolean>, HasKeyboardPopup
{
private Button btOK, btCancel;
private AutoCompleteTextFieldW tfLabel;
private RadioButton rbNumber, rbAngle, rbInteger;
private SliderPanelW sliderPanel;
private VerticalPanel mainWidget;
private VerticalPanel contentWidget;
private FlowPanel bottomWidget;
private HorizontalPanel radioButtonWidget;
private VerticalPanel nameWidget;
private AppW app;
//private SliderPanel sliderPanel;
private GeoElement geoResult;
private GeoNumeric number;
private GeoAngle angle;
private Localization loc;
/**
* Creates a dialog to create a new GeoNumeric for a slider.
*
* @param x
* x-coordinate of slider in screen coords
* @param y
* x-coordinate of slider in screen coords
* @param app
* application
*/
public SliderDialogW(final AppW app, int x, int y) {
super(false, true, null, app.getPanel());
if (app.has(Feature.DIALOGS_OVERLAP_KEYBOARD)) {
setOverlapFeature(true);
}
//super(app.getFrame(), false);
this.app = app;
this.loc = app.getLocalization();
this.addStyleName("sliderDialog");
this.addStyleName("GeoGebraFrame");
//addWindowListener(this);
// create temp geos that may be returned as result
Construction cons = app.getKernel().getConstruction();
number = new GeoNumeric(cons);
angle = new GeoAngle(cons);
// allow outside range 0-360
angle.setAngleStyle(AngleStyle.UNBOUNDED);
GeoNumeric.setSliderFromDefault(number,false);
GeoNumeric.setSliderFromDefault(angle,true);
number.setValue(1);
angle.setValue(45 * Math.PI/180);
number.setSliderLocation(x, y, true);
angle.setSliderLocation(x, y, true);
geoResult = null;
setWidget(mainWidget = new VerticalPanel());
addStyleName("GeoGebraPopup");
createGUI();
this.setGlassEnabled(true);
this.setVisible(true);
GeoElement selGeo = rbAngle.getValue() ? angle : number;
Object [] geos = { selGeo };
sliderPanelUpdate(geos);
if (app.has(Feature.KEYBOARD_BEHAVIOUR)) {
app.registerPopup(this);
}
if (app.has(Feature.DIALOGS_OVERLAP_KEYBOARD)) {
this.addCloseHandler(new CloseHandler<GPopupPanel>() {
@Override
public void onClose(CloseEvent<GPopupPanel> event) {
app.unregisterPopup(SliderDialogW.this);
app.hideKeyboard();
}
});
}
}
private void createGUI() {
// setTitle(loc.getMenu("Slider"));
//setResizable(false);
this.getCaption().setText(loc.getMenu("Slider"));
//Create components to be displayed
//mainWidget.setHorizontalAlignment(VerticalPanel.ALIGN_CENTER);
mainWidget.add(contentWidget = new VerticalPanel());
mainWidget.add(bottomWidget = new FlowPanel());
bottomWidget.setStyleName("DialogButtonPanel");
contentWidget.add(nameWidget = new VerticalPanel());
contentWidget.add(radioButtonWidget = new HorizontalPanel());
radioButtonWidget.setStyleName("DialogRbPanel");
// radio buttons for number or angle
String id = DOM.createUniqueId();
rbNumber = new RadioButton(id, loc.getMenu("Numeric"));
rbNumber.addValueChangeHandler(this);
rbNumber.setValue(true);
rbAngle = new RadioButton(id, loc.getMenu("Angle"));
rbAngle.addValueChangeHandler(this);
rbInteger = new RadioButton(id, loc.getMenu("Integer"));
rbInteger.addValueChangeHandler(this);
radioButtonWidget.add(rbNumber);
radioButtonWidget.add(rbAngle);
radioButtonWidget.add(rbInteger);
sliderPanel = new SliderPanelW(app, true, true);
sliderPanel.getWidget().setStyleName("sliderPanelWidget");
//nameWidget.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
Label nameLabel = new Label(loc.getMenu("Name"));
nameWidget.add(nameLabel);
tfLabel = new AutoCompleteTextFieldW(-1, app);
tfLabel.enableGGBKeyboard();
updateLabelField(number, false);
tfLabel.addFocusListener(new FocusListenerW(tfLabel));
tfLabel.requestToShowSymbolButton();
nameWidget.add(tfLabel);
contentWidget.add(sliderPanel.getWidget());
// buttons
btOK = new Button(loc.getMenu("OK"));
btOK.addClickHandler(this);
// btApply.getElement().getStyle().setMargin(3, Style.Unit.PX);
btCancel = new Button(loc.getMenu("Cancel"));
btCancel.addStyleName("cancelBtn");
btCancel.addClickHandler(this);
// btCancel.getElement().getStyle().setMargin(3, Style.Unit.PX);
bottomWidget.add(btOK);
bottomWidget.add(btCancel);
}
private void updateLabelField(GeoElement geo, boolean isInteger) {
String def = geo.isAngle() ? " = " + Unicode.FORTY_FIVE_DEGREES
: " = 1";
tfLabel.setText(geo.getDefaultLabel(isInteger) + def); // =45degrees
}
/**
* Sets the geoResult name and value: this is temporarily just a default label
*
* @return GeoElement: the geoResult itself
*/
public GeoElement getResult() {
if (geoResult != null) {
// set label of geoResult
String strLabel;
String text = tfLabel.getText();
try {
strLabel = app.getKernel().getAlgebraProcessor().
parseLabel(text);
} catch (Exception e) {
strLabel = null;
}
geoResult.setLabel(strLabel);
// allow eg a=2 in the Name dialog to set the initial value
if (strLabel != null && text.indexOf('=') > -1 && text.indexOf('=') == text.lastIndexOf('=')) {
try {
double val = 0;
if (text.indexOf(Unicode.DEGREE_CHAR) > text.indexOf('=')) {
val = Double.parseDouble(text.substring(
text.indexOf('=') + 1,
text.indexOf(Unicode.DEGREE_CHAR)));
val *= Math.PI / 180;
} else {
val = Double.parseDouble(text.substring(text
.indexOf('=') + 1));
}
GeoNumeric geoNum = ((GeoNumeric)geoResult);
if (val > geoNum.getIntervalMax()) {
geoNum.setIntervalMax(val);
} else if (val < geoNum.getIntervalMin()) {
geoNum.setIntervalMin(val);
}
geoNum.setValue(val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return geoResult;
}
@Override
public void onClick(ClickEvent e) {
Element target = e.getNativeEvent().getEventTarget().cast();
if (target == btOK.getElement()) {
geoResult = rbAngle.getValue() ? angle : number;
getResult();
geoResult.setLabelMode(GeoElement.LABEL_NAME_VALUE);
geoResult.setLabelVisible(true);
sliderPanel.applyAll(geoResult);
geoResult.update();
//((GeoNumeric)geoResult).setRandom(cbRandom.isSelected());
if (!rbAngle.getValue()) {
AdjustSlider.ensureOnScreen((GeoNumeric) geoResult,
app.getActiveEuclidianView());
}
hide();
app.getActiveEuclidianView().requestFocusInWindow();
app.storeUndoInfo();
app.getKernel().notifyRepaint();
} else if (target == btCancel.getElement()) {
hide();
app.getActiveEuclidianView().requestFocusInWindow();
}
}
@Override
public void onValueChange(ValueChangeEvent<Boolean> vc) {
GeoElement selGeo = rbAngle.getValue() ? angle : number;
if (vc.getSource() == rbInteger) {
number.setAutoStep(false);
number.setAnimationStep(1);
number.setIntervalMin(1);
number.setIntervalMax(30);
updateLabelField(number, true);
} else if (vc.getSource() == rbNumber) {
GeoNumeric num = app.getKernel().getAlgoDispatcher().getDefaultNumber(false);
number.setAutoStep(num.isAutoStep());
number.setAnimationStep(num.getAnimationStep());
number.setIntervalMin(num.getIntervalMin());
number.setIntervalMax(num.getIntervalMax());
updateLabelField(number, false);
} else {
updateLabelField(angle, false);
}
GeoElement [] geos = { selGeo };
sliderPanelUpdate(geos);
}
private void sliderPanelUpdate(Object[] geos) {
sliderPanel.updatePanel(geos);
}
@Override
public void onChange(ChangeEvent event) {
// TODO Auto-generated method stub
}
}