package org.geogebra.web.html5.javax.swing;
import org.geogebra.common.javax.swing.GOptionPane;
import org.geogebra.common.main.App;
import org.geogebra.common.main.Localization;
import org.geogebra.common.util.AsyncOperation;
import org.geogebra.common.util.debug.Log;
import org.geogebra.web.html5.css.GuiResourcesSimple;
import org.geogebra.web.html5.gui.GDialogBox;
import org.geogebra.web.html5.gui.HasKeyboardPopup;
import org.geogebra.web.html5.gui.inputfield.AutoCompleteTextFieldW;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Generates simple option and input dialogs modeled after the dialogs generated
* by the JOptionPane class.
*
*/
public class GOptionPaneW extends GDialogBox
implements ClickHandler, HasKeyboardPopup {
private App app;
private String title, message, initialSelectionValue;
private Button btnOK, btnCancel;
private Button[] optionButtons;
private String[] optionNames;
private int optionType, messageType;
private boolean requiresReturnValue;
private Localization loc;
private AsyncOperation<String[]> returnHandler;
private AutoCompleteTextFieldW inputField;
private FlowPanel mainPanel;
private FlowPanel buttonPanel;
private ScrollPanel scrollPanel;
private int returnOption;
private String returnValue;
private VerticalPanel messageTextPanel;
private Image icon;
private HorizontalPanel messagePanel;
private String okLabel = null;
private int enterOption;
private static FocusWidget caller;
/**
* Singleton instance of GOptionPaneW. Provides entry point for all calls to
* show a dialog or access getters/setters.
*/
@Deprecated
public static GOptionPaneW INSTANCE = new GOptionPaneW();
/**
* A private constructor is used to force use of singleton instance.
*
* @deprecated
*/
@Deprecated
private GOptionPaneW() {
super(false, true, RootPanel.get());
createGUI();
}
public GOptionPaneW(Panel root) {
super(false, true, root);
createGUI();
}
private void showDialog(boolean autoComplete) {
loc = app.getLocalization();
updateGUI();
center();
if (inputField != null) {
inputField.setAutoComplete(autoComplete);
}
show();
}
protected void close() {
// if hide is called before the callback the callback can create another
// Message (without being hidden instantanousely)!
hide();
if (requiresReturnValue) {
if (returnOption == GOptionPane.CANCEL_OPTION) {
returnValue = initialSelectionValue;
} else {
returnValue = inputField.getText();
}
}
if (returnHandler != null) {
Log.debug("option: " + returnOption + " value: " + returnValue);
String[] dialogResult = { returnOption + "", returnValue };
returnHandler.callback(dialogResult);
}
// return the focus to the input field calling this dialog
if (caller != null) {
caller.setFocus(true);
}
caller = null;
}
public static void setCaller(FocusWidget c) {
caller = c;
}
@Override
public void setGlassEnabled(boolean enabled) {
super.setGlassEnabled(enabled);
}
private void createGUI() {
setGlassEnabled(true);
addStyleName("DialogBox");
btnOK = new Button();
btnOK.addClickHandler(this);
btnCancel = new Button();
btnCancel.addClickHandler(this);
btnCancel.addStyleName("cancelBtn");
buttonPanel = new FlowPanel();
buttonPanel.addStyleName("DialogButtonPanel");
messagePanel = new HorizontalPanel();
messagePanel.addStyleName("Dialog-messagePanel");
messagePanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
messageTextPanel = new VerticalPanel();
mainPanel = new FlowPanel();
mainPanel.addStyleName("Dialog-content");
}
private void updateGUI() {
mainPanel.clear();
updateMessagePanel();
mainPanel.add(messagePanel);
if (requiresReturnValue) {
updateInputField();
mainPanel.add(inputField);
}
updateButtonPanel();
mainPanel.add(buttonPanel);
clear();
add(mainPanel);
setText(title);
}
private void updateButtonPanel() {
buttonPanel.clear();
switch (optionType) {
case GOptionPane.CUSTOM_OPTION:
optionButtons = new Button[optionNames.length];
for (int i = optionNames.length - 1; i >= 0; i--) {
optionButtons[i] = new Button(optionNames[i]);
optionButtons[i].addClickHandler(this);
// Styling of cancel button should be different
if (optionNames[i]
.equals(app.getLocalization().getMenu("Cancel"))) {
optionButtons[i].addStyleName("cancelBtn");
}
buttonPanel.add(optionButtons[i]);
}
break;
case GOptionPane.OK_OPTION:
case GOptionPane.DEFAULT_OPTION:
buttonPanel.add(btnOK);
setLabels();
break;
case GOptionPane.OK_CANCEL_OPTION:
buttonPanel.add(btnOK);
buttonPanel.add(btnCancel);
setLabels();
break;
default:
buttonPanel.add(btnOK);
setLabels();
}
}
private void updateMessagePanel() {
messagePanel.clear();
messageTextPanel.clear();
updateIcon();
if (icon != null) {
messagePanel.add(icon);
}
if (scrollPanel != null) {
messagePanel.add(scrollPanel);
messagePanel.addStyleName("examMessagePanel");
} else {
String[] lines = message.split("\n");
for (String item : lines) {
messageTextPanel.add(new Label(item));
}
messagePanel.add(messageTextPanel);
}
}
private void setLabels() {
btnOK.setText(okLabel == null ? loc.getPlain("OK") : okLabel);
btnCancel.setText(loc.getPlain("Cancel"));
}
private void updateInputField() {
if (inputField == null) {
inputField = new AutoCompleteTextFieldW(app);
}
inputField.setText(initialSelectionValue);
}
private void updateIcon() {
if (icon != null) {
return;
}
switch (messageType) {
case GOptionPane.ERROR_MESSAGE:
icon = new Image(
GuiResourcesSimple.INSTANCE.dialog_error().getSafeUri());
break;
case GOptionPane.INFORMATION_MESSAGE:
icon = new Image(
GuiResourcesSimple.INSTANCE.dialog_info().getSafeUri());
break;
case GOptionPane.WARNING_MESSAGE:
icon = new Image(
GuiResourcesSimple.INSTANCE.dialog_warning().getSafeUri());
break;
case GOptionPane.QUESTION_MESSAGE:
icon = new Image(
GuiResourcesSimple.INSTANCE.dialog_question().getSafeUri());
break;
default:
case GOptionPane.PLAIN_MESSAGE:
icon = null;
break;
}
}
@Override
public void onClick(ClickEvent event) {
Object source = event.getSource();
Log.debug("source is: " + source);
if (source == btnOK) {
Log.debug("btnOk");
returnOption = GOptionPane.OK_OPTION;
close();
}
if (source == btnCancel) {
Log.debug("btnCancel");
returnOption = GOptionPane.CANCEL_OPTION;
close();
}
if (optionButtons == null) {
return;
}
for (int i = 0; i < optionButtons.length; i++) {
if (source == optionButtons[i]) {
returnOption = i;
close();
}
}
}
/**
* Close the dialog on key events ENTER or ESC.
*/
@Override
protected void onPreviewNativeEvent(final NativePreviewEvent event) {
super.onPreviewNativeEvent(event);
if (!isShowing()) {
return;
}
if (event.getTypeInt() == Event.ONKEYUP) {
int keyCode = event.getNativeEvent().getKeyCode();
if (keyCode == KeyCodes.KEY_ESCAPE) {
returnOption = GOptionPane.CANCEL_OPTION;
close();
} else if (keyCode == KeyCodes.KEY_ENTER) {
returnOption = optionType == GOptionPane.CUSTOM_OPTION
? enterOption : GOptionPane.OK_OPTION;
close();
}
}
}
// ===================================================================
// Dialog Launching Methods
// ===================================================================
/**
* Launches a confirm dialog.
*/
public int showConfirmDialog(App app, String message, String title,
int optionType, int messageType, Image icon) {
this.app = app;
this.message = message;
this.title = title;
this.optionType = optionType;
this.messageType = messageType;
this.icon = icon;
this.okLabel = null;
this.returnHandler = null;
requiresReturnValue = false;
showDialog(true);
showDialog(true);
return returnOption;
}
public int showConfirmDialog(App app, ScrollPanel scrollPanel, String title,
int optionType, int messageType, String okLabel, Image icon,
AsyncOperation<String[]> returnHandler) {
this.app = app;
this.scrollPanel = scrollPanel;
this.title = title;
this.optionType = optionType;
this.messageType = messageType;
this.icon = icon;
this.okLabel = okLabel;
this.returnHandler = returnHandler;
// this.returnHandler = null;
requiresReturnValue = false;
this.addStyleName("centerDialog");
showDialog(true);
showDialog(true);
return returnOption;
}
/**
* Launches a customizable option dialog.
*
* The dialog result is returned in the parameter of the handler callback
* function as an array of two strings: <br>
*
* dialogResult[0] = returnOption <br>
* dialogResult[1] = returnValue <br>
*
* (Note that returnValue is meaningless here.)
*/
public void showOptionDialog(App app, String message, String title,
int enterOption, int messageType, Object icon, String[] optionNames,
AsyncOperation<String[]> handler) {
this.app = app;
this.message = message;
this.title = title;
this.optionType = GOptionPane.CUSTOM_OPTION;
this.enterOption = enterOption;
this.messageType = messageType;
this.icon = (Image) icon;
this.scrollPanel = null;
this.optionNames = optionNames;
this.returnHandler = handler;
requiresReturnValue = false;
showDialog(true);
}
/**
* Launches a simple input dialog. The dialog result is returned in the
* parameter of the handler callback function as an array of two strings:
* <br>
*
* dialogResult[0] = returnOption <br>
* dialogResult[1] = returnValue
*
*/
public void showInputDialog(App app, String message,
String initialSelectionValue, Object icon,
AsyncOperation<String[]> handler, boolean autoComplete) {
this.app = app;
this.message = message;
this.title = null;
this.optionType = GOptionPane.OK_CANCEL_OPTION;
this.messageType = GOptionPane.PLAIN_MESSAGE;
this.icon = (Image) icon;
this.initialSelectionValue = initialSelectionValue;
this.returnHandler = handler;
requiresReturnValue = true;
showDialog(autoComplete);
}
public void showSaveDialog(App app, String title,
String initialSelectionValue, Object icon,
AsyncOperation<String[]> handler, String okLabel) {
this.app = app;
this.message = "";
this.title = title;
this.okLabel = okLabel;
this.optionType = GOptionPane.OK_CANCEL_OPTION;
this.messageType = GOptionPane.PLAIN_MESSAGE;
this.icon = (Image) icon;
this.initialSelectionValue = initialSelectionValue;
this.returnHandler = handler;
requiresReturnValue = true;
showDialog(false);
}
/**
* Launches a customizable input dialog. The dialog result is returned in
* the parameter of the handler callback function as an array of two
* strings: <br>
*
* dialogResult[0] = returnOption <br>
* dialogResult[1] = returnValue
*
*/
public void showInputDialog(App app, String message, String title,
String initialSelectionValue, int optionType, int messageType,
Object icon, String[] optionNames,
AsyncOperation<String[]> handler) {
this.app = app;
this.message = message;
this.title = title;
this.optionType = optionType;
this.messageType = messageType;
this.icon = (Image) icon;
this.optionNames = optionNames;
this.initialSelectionValue = initialSelectionValue;
this.returnHandler = handler;
requiresReturnValue = true;
showDialog(true);
}
public void showInputDialog(App app, String message,
String initialSelectionValue, Object icon,
AsyncOperation<String[]> handler) {
showInputDialog(app, message, initialSelectionValue, icon, handler,
true);
}
}