package org.geogebra.web.web.gui.dialog; import org.geogebra.common.gui.InputHandler; import org.geogebra.common.gui.SetLabels; import org.geogebra.common.gui.dialog.InputDialog; import org.geogebra.common.gui.view.algebra.DialogType; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.main.Feature; import org.geogebra.common.main.Localization; import org.geogebra.common.util.AsyncOperation; import org.geogebra.common.util.lang.Unicode; import org.geogebra.web.html5.event.FocusListenerW; import org.geogebra.web.html5.gui.GDialogBox; import org.geogebra.web.html5.gui.GPopupPanel; import org.geogebra.web.html5.gui.HasKeyboardPopup; import org.geogebra.web.html5.main.AppW; import org.geogebra.web.web.gui.view.algebra.InputPanelW; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.DomEvent; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; public class InputDialogW extends InputDialog implements ClickHandler, SetLabels, KeyUpHandler, KeyPressHandler { protected final AppW app; public static final int DEFAULT_COLUMNS = 30; public static final int DEFAULT_ROWS = 10; protected InputPanelW inputPanel; protected Button btApply, btProperties, btCancel, btOK, btHelp; protected GDialogBox wrappedPopup; protected GeoElement geo; private String title; protected VerticalPanel messagePanel, errorPanel; protected FlowPanel btPanel; protected final Localization loc; public InputDialogW(boolean modal, AppW app, boolean hasKeyboard){ this.app = app; this.loc = app.getLocalization(); if (hasKeyboard){ wrappedPopup = new DialogBoxKbW(false, modal, this, app.getPanel()); } else { wrappedPopup = new DialogBoxW(false, modal, this, app.getPanel()); } if (app.has(Feature.DIALOGS_OVERLAP_KEYBOARD)) { wrappedPopup.setOverlapFeature(true); } } public InputDialogW(AppW app, String message, String title, String initString, boolean autoComplete, InputHandler handler, boolean modal, boolean selectInitText) { this(app, message, title, initString, autoComplete, handler, modal, selectInitText, DialogType.GeoGebraEditor); } /** * @param app * @param message * @param title * @param initString * @param autoComplete * @param handler * @param modal * @param selectInitText * @param geo * @param checkBox * @param type */ public InputDialogW(AppW app, String message, String title, String initString, boolean autoComplete, InputHandler handler, boolean modal, final boolean selectInitText, DialogType type) { this(modal, app, true); this.setInputHandler(handler); setInitString(initString); createGUI(title, message, autoComplete, DEFAULT_COLUMNS, 1, true, selectInitText, false, false, type); centerAndFocus(selectInitText); } public static class DialogBoxKbW extends DialogBoxW implements HasKeyboardPopup { public DialogBoxKbW(boolean b, boolean modal, InputDialogW inputDialogW, Panel panel) { super(b, modal, inputDialogW, panel); } } protected void centerAndFocus(final boolean selectInitText) { wrappedPopup.center(); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { if (inputPanel != null) { inputPanel.getTextComponent().setFocus(true); // Firefox: correct cursor position #5419 if (!selectInitText) { inputPanel.getTextComponent().setCaretPosition( inputPanel.getText().length()); } } } }); } public InputDialogW(AppW app, String message, String title, String initString, InputHandler handler, GeoElement geo) { this(false, app, false); this.geo = geo; this.setInputHandler(handler); setInitString(initString); createGUI(title, message, true, DEFAULT_COLUMNS, 1, true, false, geo != null, false, DialogType.GeoGebraEditor); centerAndFocus(false); } public InputDialogW(AppW app, String message, String title, String initString, boolean autoComplete, InputHandler handler) { this(app, message, title, initString, autoComplete, handler, false, false); } public InputDialogW(AppW app2, String message, String title2, String initString, boolean autoComplete, InputHandler handler, boolean selectInitText) { this(app2, message, title2, initString, autoComplete, handler, false, selectInitText); } /** * @param title1 * @param message * @param autoComplete * @param columns * @param rows * @param showSymbolPopupIcon * @param selectInitText * @param showProperties * @param showApply * @param type */ protected void createGUI(String title1, String message, boolean autoComplete, int columns, int rows, boolean showSymbolPopupIcon, boolean selectInitText, boolean showProperties, boolean showApply, DialogType type) { this.title = title1; // Create components to be displayed inputPanel = new InputPanelW(getInitString(), app, rows, columns, showSymbolPopupIcon/* , type */); if (app.has(Feature.KEYBOARD_BEHAVIOUR)) { app.registerPopup(wrappedPopup); } if (app.has(Feature.DIALOGS_OVERLAP_KEYBOARD)) { wrappedPopup.addCloseHandler(new CloseHandler<GPopupPanel>() { @Override public void onClose(CloseEvent<GPopupPanel> event) { app.unregisterPopup(wrappedPopup); app.hideKeyboard(); } }); } // add key handler for ENTER if inputPanel uses a text field if (inputPanel.getTextComponent() != null) { inputPanel.getTextComponent().getTextField().getValueBox().addKeyUpHandler(this); inputPanel.getTextComponent().addFocusListener(new FocusListenerW(this)); inputPanel.getTextComponent().getTextField().getValueBox().addKeyPressHandler(this); } // message panel messagePanel = new VerticalPanel(); String[] lines = message.split("\n"); for (String item : lines) { messagePanel.add(new Label(item)); } messagePanel.addStyleName("Dialog-messagePanel"); errorPanel = new VerticalPanel(); errorPanel.addStyleName("Dialog-errorPanel"); // create buttons btProperties = new Button(); btProperties.addClickHandler(this); btOK = new Button(); btOK.addClickHandler(this); btCancel = new Button(); btCancel.addClickHandler(this); btCancel.addStyleName("cancelBtn"); btApply = new Button(); btApply.addClickHandler(this); // create button panel btPanel = new FlowPanel(); btPanel.addStyleName("DialogButtonPanel"); btPanel.add(btOK); btPanel.add(btCancel); // just tmp. if (showApply) { btPanel.add(btApply); } // if (showProperties) { // btPanel.add(btProperties); // } setLabels(); VerticalPanel centerPanel = new VerticalPanel(); centerPanel.addStyleName("Dialog-content"); centerPanel.add(messagePanel); centerPanel.add(inputPanel); centerPanel.add(errorPanel); centerPanel.add(btPanel); wrappedPopup.setWidget(centerPanel); } /** * Handles button clicks for dialog. */ @Override public void onClick(ClickEvent e) { actionPerformed(e); } protected void closeIOSKeyboard() { // implemented in TextInputDialog } protected void actionPerformed(DomEvent event) { Widget source = (Widget) event.getSource(); if (source == btOK || sourceShouldHandleOK(source)) { closeIOSKeyboard(); inputText = inputPanel.getText(); processInputHandler(new AsyncOperation<Boolean>() { @Override public void callback(Boolean ok) { setVisible(!ok); if (ok) { resetMode(); } } }); } else if (source == btApply) { inputText = inputPanel.getText(); processInputHandler(null); } else if (source == btProperties && geo != null) { setVisible(false); openProperties(app, geo); } else if (source == btCancel) { closeIOSKeyboard(); cancel(); resetMode(); } } protected void resetMode() { // only needed for texts } protected void cancel() { setVisible(false); } public void setVisible(boolean visible) { inputPanel.setVisible(visible); if (visible){ wrappedPopup.show(); inputPanel.setTextComponentFocus(); }else{ forceHideKeyboard(); wrappedPopup.hide(); } } private native void forceHideKeyboard() /*-{ if ($wnd.android && $wnd.android.callPlugin) { $wnd.android.callPlugin("CloseKeyboard", []); } }-*/; @Override public void setLabels() { wrappedPopup.setText(title); btOK.setText(loc.getPlain("OK")); btApply.setText(loc.getPlain("Apply")); btCancel.setText(loc.getPlain("Cancel")); btProperties.setText(loc.getPlain("Properties") + Unicode.ellipsis); } @Override public void onKeyUp(KeyUpEvent event) { //enter press if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER){ actionPerformed(event); return; } } private boolean showingError = false; @Override public void showError(String msg) { if(msg == null){ showingError = false; } else if (!showingError) { showingError = true; errorPanel.clear(); String[] lines = msg.split("\n"); for (String item : lines) { errorPanel.add(new Label(item)); } } } /** * @param source the event source * @return true if the source widget should handle the OK event */ protected boolean sourceShouldHandleOK(Object source) { return (inputPanel.getTextComponent() != null && source == inputPanel .getTextComponent().getTextField().getValueBox()); } @Override public void showCommandError(String command, String message) { app.getDefaultErrorHandler().showCommandError(command, message); } @Override public String getCurrentCommand() { return inputPanel.getTextComponent().getCommand(); } @Override public boolean onUndefinedVariables(String string, AsyncOperation<String[]> callback) { return app.getGuiManager().checkAutoCreateSliders(string, callback); } @Override public void onKeyPress(KeyPressEvent event) { // overridden in angle dialog } @Override public void resetError() { showError(null); } }