package org.geogebra.web.web.gui.view.functioninspector;
import java.util.ArrayList;
import java.util.Arrays;
import org.geogebra.common.awt.GColor;
import org.geogebra.common.euclidian.event.KeyEvent;
import org.geogebra.common.euclidian.event.KeyHandler;
import org.geogebra.common.gui.view.functioninspector.FunctionInspector;
import org.geogebra.common.gui.view.functioninspector.FunctionInspectorModel.Colors;
import org.geogebra.common.kernel.arithmetic.NumberValue;
import org.geogebra.common.kernel.geos.GeoFunction;
import org.geogebra.common.main.Localization;
import org.geogebra.common.util.debug.Log;
import org.geogebra.web.html5.gui.FastClickHandler;
import org.geogebra.web.html5.gui.inputfield.AutoCompleteTextFieldW;
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.util.ImageOrText;
import org.geogebra.web.web.gui.util.MyCJButton;
import org.geogebra.web.web.gui.util.MyToggleButtonW;
import org.geogebra.web.web.gui.util.PopupMenuButtonW;
import org.geogebra.web.web.gui.util.PopupMenuHandler;
import org.geogebra.web.web.gui.util.StandardButton;
import org.geogebra.web.web.gui.view.algebra.InputPanelW;
import org.geogebra.web.web.gui.view.functioninspector.GridModel.DataCell;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.user.client.Window;
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.TabBar;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.Widget;
public class FunctionInspectorW extends FunctionInspector {
private static final int PADDING_RIGHT = 45;
// color constants
private static final GColor DISPLAY_GEO_COLOR = GColor.RED;
private static final GColor DISPLAY_GEO2_COLOR = GColor.RED;
private static final GColor EVEN_ROW_COLOR = GColor.newColor(241, 245, 250);
private static final GColor TABLE_GRID_COLOR = GColor.GRAY;
private static final int TAB_INTERVAL_IDX = 0;
private static final String[] DEFAULT_XY_HEADERS = { "x", "y(x)" };
private static final String PREFIX = "[FUNC_ISPECTOR]";
private static final int HEADER_PADDING = 44;
private FlowPanel mainPanel;
private TabPanel tabPanel;
private FlowPanel intervalTab;
private FlowPanel pointsTab;
private MyToggleButtonW btnTable;
private MyToggleButtonW btnXYSegments;
private MyToggleButtonW btnTangent;
private MyToggleButtonW btnOscCircle;
private StandardButton btnHelp;
PopupMenuButtonW btnOptions;
// private MenuBar btnOptions;
private Label lblGeoName, lblStep, lblInterval;
AutoCompleteTextFieldW fldStep, fldLow, fldHigh;
private InspectorTableW tableXY;
private GridModel modelXY, modelInterval;
PopupMenuButtonW btnAddColumn;
private MyCJButton btnRemoveColumn;
private int pointCount = 9;
/**
* @param app
* @param selectedGeo
*/
public FunctionInspectorW(AppW app, GeoFunction selectedGeo) {
super(app, selectedGeo);
Log.debug("[!!!] constructor");
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(final ResizeEvent event) {
FunctionInspectorW.this.onResize();
}
});
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
onResize();
}
});
}
@Override
public void createGUI() {
super.createGUI();
setInspectorVisible(true);
}
@Override
public void reset() {
// TODO Auto-generated method stub
}
@Override
public boolean hasFocus() {
// TODO Auto-generated method stub
return false;
}
@Override
public void updateFonts() {
// TODO Auto-generated method stub
}
private static void debug(String msg) {
Log.debug(PREFIX + " " + msg);
}
@Override
public void updateXYTable(boolean isTable) {
// reset table model and update the XYtable
tableXY.setCellEditable(-1, -1);
if (isTable) {
int row = (pointCount) / 2;
modelXY.setRowCount(pointCount);
Log.debug("[updateXYTable] pointCount: " + pointCount + " row: "
+ row);
tableXY.setCellEditable(row, 0);
tableXY.setSelectedRow(row);
} else {
modelXY.setRowCount(1);
tableXY.setSelectedRow(0);
tableXY.setCellEditable(0, 0);
// tableXY.changeSelection(0, 0, false, false);
// tableXY.setRowSelectionAllowed(false);
}
updateXYTable();
Log.debug(modelXY.toString());
updateTestPoint();
}
@Override
public void updateInterval(ArrayList<String> property,
ArrayList<String> value) {
debug("updateInterval");
modelInterval.removeAll();
modelInterval.setHeaders(getModel().getIntervalColumnNames());
for (int i = 0; i < property.size(); i++) {
modelInterval
.addAsRow(Arrays.asList(property.get(i), value.get(i)));
}
debug("updateInterval ended");
}
@Override
public void setXYValueAt(Double value, int row, int col) {
debug("[XY] setData");
modelXY.setData(row, col, getModel().format(value));
debug("setData ended");
}
@Override
public Object getXYValueAt(int row, int col) {
Log.debug("GETDATA row: " + row + " col: " + col);
DataCell value = modelXY.getData(row, col);
return value != null ? value.toString() : "";
}
@Override
public void addTableColumn(String name) {
modelXY.addColumn(name);
updateXYTable();
}
@Override
public void setGeoName(String name) {
lblGeoName.setText(name);
}
@Override
public void changeTableSelection() {
updateXYTable();
updateTestPoint();
}
@Override
public void updateHighAndLow(boolean isAscending, boolean isLowSelected) {
if (isAscending) {
if (isLowSelected) {
doTextFieldActionPerformed(fldLow);
} else {
doTextFieldActionPerformed(fldHigh);
}
}
updateIntervalFields();
}
@Override
public void setStepText(String text) {
fldStep.setText(text);
}
@Override
public void setStepVisible(boolean isVisible) {
lblStep.setVisible(isVisible);
fldStep.setVisible(isVisible);
}
@Override
public GColor getColor(Colors id) {
GColor color;
switch (id) {
case EVEN_ROW:
color = EVEN_ROW_COLOR;
break;
case GEO:
color = DISPLAY_GEO_COLOR;
break;
case GEO2:
color = DISPLAY_GEO2_COLOR;
break;
case GRID:
color = TABLE_GRID_COLOR;
break;
default:
color = GColor.BLACK;
break;
}
return color;
}
@Override
public int getSelectedXYRow() {
int row = tableXY.getSelectedRow() - 1;
return row;
}
@Override
protected void buildTabPanel() {
tabPanel = new TabPanel();
tabPanel.add(intervalTab, "Interval");
tabPanel.add(pointsTab, "Points");
tabPanel.selectTab(TAB_INTERVAL_IDX);
tabPanel.addSelectionHandler(new SelectionHandler<Integer>() {
@Override
public void onSelection(SelectionEvent<Integer> event) {
updateTabPanels();
}
});
mainPanel.add(tabPanel);
}
@Override
protected void buildHelpPanel() {
btnHelp = new StandardButton(GuiResources.INSTANCE.menu_icon_help());
btnHelp.addStyleName("MyCanvasButton");
btnHelp.addFastClickHandler(new FastClickHandler() {
@Override
public void onClick(Widget source) {
app.getGuiManager().openHelp("Function_Inspector_Tool");
}
});
}
@Override
protected void buildHeaderPanel() {
FlowPanel header = new FlowPanel();
FlowPanel buttons = new FlowPanel();
header.add(lblGeoName);
buttons.add(btnHelp);
buttons.add(btnOptions);
header.add(buttons);
buttons.setStyleName("panelRow");
header.setStyleName("panelRow");
buildHelpPanel();
mainPanel.add(header);
}
@Override
protected void createTabIntervalPanel() {
intervalTab = new FlowPanel();
InspectorTableW tableInterval = new InspectorTableW(app, 2);
modelInterval = tableInterval.getModel();
intervalTab.add(tableInterval);
FlowPanel toolBar = new FlowPanel();
toolBar.setStyleName("panelRow");
toolBar.add(fldLow);
toolBar.add(lblInterval);
toolBar.add(fldHigh);
intervalTab.add(toolBar);
intervalTab.setStyleName("propertiesTab");
}
@Override
protected void createTabPointPanel() {
debug("createTabPointPanel()");
pointsTab = new FlowPanel();
pointsTab.setStyleName("propertiesTab");
FlowPanel header = new FlowPanel();
header.setStyleName("panelRow");
createStep();
createBtnAddColumn();
createBtnRemoveColumn();
header.add(lblStep);
header.add(fldStep);
header.add(btnAddColumn);
header.add(btnRemoveColumn);
pointsTab.add(header);
createXYtable();
pointsTab.add(tableXY);
FlowPanel btnPanel = createBtnPanel();
pointsTab.add(btnPanel);
debug("createTabPointPanel() ENDED");
}
/**
* @return
*/
private FlowPanel createBtnPanel() {
FlowPanel btnPanel = new FlowPanel();
btnPanel.setStyleName("panelRowIndent");
btnTable = new MyToggleButtonW(new Image(AppResources.INSTANCE.table()
.getSafeUri()));
btnXYSegments = new MyToggleButtonW(new Image(AppResources.INSTANCE
.xy_segments().getSafeUri()));
btnTangent = new MyToggleButtonW(new Image(AppResources.INSTANCE
.tangent_line().getSafeUri()));
btnOscCircle = new MyToggleButtonW(new Image(AppResources.INSTANCE
.osculating_circle().getSafeUri()));
btnPanel.add(btnTable);
btnPanel.add(btnXYSegments);
btnPanel.add(btnTangent);
btnPanel.add(btnOscCircle);
ClickHandler btnClick = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
updateGUI();
}
};
btnTable.addClickHandler(btnClick);
btnXYSegments.addClickHandler(btnClick);
btnTangent.addClickHandler(btnClick);
btnOscCircle.addClickHandler(btnClick);
btnXYSegments.setDown(true);
return btnPanel;
}
private void createBtnRemoveColumn() {
btnRemoveColumn = new MyCJButton();
btnRemoveColumn.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
removeColumn();
}
});
}
private void createXYtable() {
tableXY = new InspectorTableW(app, 2);
modelXY = tableXY.getModel();
modelXY.setHeaders(DEFAULT_XY_HEADERS);
// modelXY.setRowCount(pointCount);
tableXY.addKeyHandler(new KeyHandler() {
@Override
public void keyReleased(KeyEvent e) {
if (e.isEnterKey()) {
changeXYStart();
}
}
});
tableXY.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
changeXYStart();
}
});
}
private void createStep() {
lblStep = new Label();
InputPanelW stepPanel = new InputPanelW(app, -1, false);
fldStep = stepPanel.getTextComponent();
fldStep.addKeyHandler(new KeyHandler() {
@Override
public void keyReleased(KeyEvent e) {
if (e.isEnterKey()) {
doTextFieldActionPerformed(fldStep);
}
}
});
fldStep.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
doTextFieldActionPerformed(fldStep);
}
});
fldStep.setColumns(6);
}
void changeXYStart() {
Double value = tableXY.getDoubleEdited();
Log.debug("[TESTPOINT] edited value is: " + value);
if (value != null) {
changeStart(value);
}
}
private void createBtnAddColumn() {
btnAddColumn = new PopupMenuButtonW(app,
ImageOrText.convert(getModel().getColumnNames()), -1, 1,
org.geogebra.common.gui.util.SelectionTable.MODE_TEXT) {
@Override
public void handlePopupActionEvent() {
super.handlePopupActionEvent();
getModel().addColumn(getSelectedIndex());
btnAddColumn.setSelectedIndex(-1);
}
};
btnAddColumn.setKeepVisible(false);
btnAddColumn.setText("\u271A");
btnAddColumn.setSelectedIndex(-1);
}
@Override
protected void createGUIElements() {
mainPanel = new FlowPanel();
mainPanel.addStyleName("functionInspectorMainPanel");
lblGeoName = new Label(getModel().getTitleString());
lblInterval = new Label();
InputPanelW lowPanel = new InputPanelW(app, -1, false);
fldLow = lowPanel.getTextComponent();
fldLow.setColumns(6);
fldLow.addKeyHandler(new KeyHandler() {
@Override
public void keyReleased(KeyEvent e) {
if (e.isEnterKey()) {
doTextFieldActionPerformed(fldLow);
}
}
});
fldLow.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
doTextFieldActionPerformed(fldLow);
}
});
InputPanelW highPanel = new InputPanelW(app, -1, false);
fldHigh = highPanel.getTextComponent();
fldHigh.setColumns(6);
fldHigh.addKeyHandler(new KeyHandler() {
@Override
public void keyReleased(KeyEvent e) {
if (e.isEnterKey()) {
doTextFieldActionPerformed(fldHigh);
}
}
});
fldHigh.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
doTextFieldActionPerformed(fldHigh);
}
});
}
void doTextFieldActionPerformed(AutoCompleteTextFieldW source) {
try {
String inputText = source.getText().trim();
// allow input such as sqrt(2)
NumberValue nv;
nv = getKernel().getAlgebraProcessor().evaluateToNumeric(inputText,
false);
double value = nv.getDouble();
if (source == fldStep) {
getModel().applyStep(value);
updateXYTable();
} else if (source == fldLow) {
getModel().applyLow(value);
updateIntervalTable();
} else if (source == fldHigh) {
getModel().applyHigh(value);
updateIntervalTable();
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
@Override
protected void updatePointsTab() {
Log.debug("UPDATE POINTS TAB");
getModel().updatePoints(btnTangent.isSelected(),
btnOscCircle.isSelected(), btnXYSegments.isSelected(),
btnTable.isSelected());
}
@Override
protected boolean isIntervalTabSelected() {
return tabPanel.getTabBar().getSelectedTab() == TAB_INTERVAL_IDX;
}
@Override
protected void updateIntervalFields() {
if (isIntervalTabSelected()) {
double[] coords = new double[3];
getModel().getLowPoint().getCoords(coords);
fldLow.setText(coords[0] + "");
getModel().getHighPoint().getCoords(coords);
fldHigh.setText(coords[0] + "");
getModel().updateIntervalTable();
}
}
@Override
protected void updateXYTable() {
getModel().updateXYTable(modelXY.getRowCount(), btnTable.isSelected());
}
@Override
protected void removeColumn() {
if (modelXY.getColumnCount() == 2) {
return;
}
Log.debug("Removing column");
getModel().removeColumn();
modelXY.removeColumn();
updateXYTable();
}
@Override
protected void changeStart(double x) {
setStart(x);
}
@Override
protected void createOptionsButton() {
ImageOrText[] strOptions = new ImageOrText[] { new ImageOrText(
app.getLocalization().getMenu("CopyToSpreadsheet")) };
btnOptions = new PopupMenuButtonW((AppW) app, strOptions,
strOptions.length, 1,
org.geogebra.common.gui.util.SelectionTable.MODE_TEXT);
ImageOrText icon = new ImageOrText(
GuiResources.INSTANCE.menu_icon_tools());
btnOptions.setFixedIcon(icon);
btnOptions.setSelectedIndex(-1);
btnOptions.addPopupHandler(new PopupMenuHandler() {
@Override
public void fireActionPerformed(PopupMenuButtonW actionButton) {
doCopyToSpreadsheet();
btnOptions.setSelectedIndex(-1);
}
});
}
@Override
protected void doCopyToSpreadsheet() {
if (isIntervalTabSelected()) {
getModel().copyIntervalsToSpreadsheet(2, 9);// modelInterval.getColumnCount(),
// modelInterval.getRowCount());
} else {
getModel().copyPointsToSpreadsheet(modelXY.getColumnCount(),
modelXY.getRowCount());
}
}
public Widget getWrappedPanel() {
return mainPanel;
}
@Override
public boolean suggestRepaint() {
return false;
}
@Override
public void setLabels() {
debug("setLabels");
Localization loc = app.getLocalization();
// wrappedDialog.setTitle(loc.getMenu("FunctionInspector"));
lblStep.setText(loc.getMenu("Step") + ":");
lblInterval.setText(" \u2264 x \u2264 "); // <= x <=
//
// // header text
//
TabBar tabBar = tabPanel.getTabBar();
tabBar.setTabText(0, loc.getPlain("fncInspector.Interval"));
tabBar.setTabText(1, loc.getPlain("fncInspector.Points"));
lblGeoName.setText(getModel().getTitleString());
//
// // tool tips
btnHelp.setTitle(loc.getPlain("ShowOnlineHelp"));
btnOscCircle.setToolTipText(loc
.getPlainTooltip("fncInspector.showOscCircle"));
btnXYSegments.setToolTipText(loc
.getPlainTooltip("fncInspector.showXYLines"));
btnTable.setToolTipText(loc.getPlainTooltip("fncInspector.showTable"));
btnTangent.setToolTipText(loc
.getPlainTooltip("fncInspector.showTangent"));
btnAddColumn.setToolTipText(loc
.getPlainTooltip("fncInspector.addColumn"));
btnRemoveColumn.setTitle(loc
.getPlainTooltip("fncInspector.removeColumn"));
// fldStep.setToolTipText(loc.getPlainTooltip("fncInspector.step"));
// lblStep.setToolTipText(loc.getPlainTooltip("fncInspector.step"));
//
// // add/remove extra column buttons
btnRemoveColumn.setText("\u2718");
btnAddColumn.setText("\u271A");
btnOptions.getMyTable().updateText(
new ImageOrText[] { new ImageOrText(
app.getLocalization()
.getMenu("CopyToSpreadsheet")) });
btnAddColumn.getMyTable().updateText(
ImageOrText.convert(getModel().getColumnNames()));
modelInterval.setHeaders(getModel().getIntervalColumnNames());
debug("setLabels ended");
}
void onResize() {
if (this.mainPanel.getOffsetHeight() != 0) {
this.tabPanel.setHeight(this.mainPanel.getOffsetHeight()
- HEADER_PADDING + "px");
this.intervalTab.setWidth(this.mainPanel.getOffsetWidth() - PADDING_RIGHT
+ "px");
this.pointsTab.setWidth(this.mainPanel.getOffsetWidth()
- PADDING_RIGHT + "px");
}
}
}