diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java index d05b540acc66f0b5318da26586ea1e612ed9f3d5..8208c2a0e9f21efd75bf1bc8593c5f36b064efa2 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AbstractAsyncCallback.java @@ -34,29 +34,37 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.exception.InvalidSessi */ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> { - private static final ICallbackListener DUMMY_LISTENER = new ICallbackListener() + private static final ICallbackListener DEFAULT_LISTENER = new ICallbackListener() { - public void onFailureOf(AsyncCallback<Object> callback, String failureMessage, - Throwable throwable) + + // + // ICallbackListener + // + + public final void onFailureOf(final AsyncCallback<Object> callback, + final String failureMessage, final Throwable throwable) { MessageBox.alert("Error", failureMessage, null); } - public void finishOnSuccessOf(AsyncCallback<Object> callback, Object result) + public final void finishOnSuccessOf(final AsyncCallback<Object> callback, + final Object result) { } }; private static final String PREFIX = "exception_"; - private static ICallbackListener callbackListener = DUMMY_LISTENER; + private static ICallbackListener staticCallbackListener = DEFAULT_LISTENER; private static final List<AbstractAsyncCallback<?>> callbackObjects = new ArrayList<AbstractAsyncCallback<?>>(); /** - * Sets all callback objects silent. Note: THIS METHOD SHOULD NEVER BE USED. It is only used - * inside the testing framework. + * Sets all callback objects silent. + * <p> + * <b>Note</b>: THIS METHOD SHOULD NEVER BE USED. It is only used inside the testing framework. + * </p> */ public static void setAllCallbackObjectsSilent() { @@ -68,44 +76,75 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> } /** - * Sets the global callback listener. Note: THIS METHOD SHOULD NEVER BE USED. It is only used - * inside the testing framework. + * Sets the global callback listener. + * <p> + * Note: THIS METHOD SHOULD NEVER BE USED. It is only used inside the testing framework. + * </p> */ - public static void setCallbackListener(final ICallbackListener listenerOrNull) + public static void setStaticCallbackListener(final ICallbackListener listenerOrNull) { - callbackListener = listenerOrNull == null ? DUMMY_LISTENER : listenerOrNull; + staticCallbackListener = listenerOrNull == null ? DEFAULT_LISTENER : listenerOrNull; } protected final IViewContext<?> viewContext; private boolean silent; + private final ICallbackListener callbackListener; + /** * Creates an instance for the specified view context. */ public AbstractAsyncCallback(final IViewContext<?> viewContext) + { + this(viewContext, null); + } + + /** + * Creates an instance for the specified view context. + */ + public AbstractAsyncCallback(final IViewContext<?> viewContext, + final ICallbackListener callbackListenerOrNull) { this.viewContext = viewContext; - if (callbackListener != DUMMY_LISTENER) + if (staticCallbackListener != DEFAULT_LISTENER) { callbackObjects.add(this); } + if (callbackListenerOrNull != null) + { + callbackListener = callbackListenerOrNull; + } else + { + callbackListener = null; + } } @SuppressWarnings("unchecked") - private AsyncCallback<Object> getThis() + private final AsyncCallback<Object> getThis() { return (AsyncCallback<Object>) this; } /** - * Terminates {@link #onFailure(Throwable)}. Default behavior does nothing. Override this in - * subclasses. + * Terminates {@link #onFailure(Throwable)}. + * <p> + * Default behavior does nothing. Override this in subclasses. + * </p> */ protected void finishOnFailure(final Throwable caught) { } + /** + * Processes the specified result of an asynchronous method invocation. + */ + protected abstract void process(final T result); + + // + // AsyncCallback + // + public final void onFailure(final Throwable caught) { if (silent) @@ -135,7 +174,14 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> msg = message; } } - callbackListener.onFailureOf(getThis(), msg, caught); + if (callbackListener != null) + { + callbackListener.onFailureOf(getThis(), msg, caught); + } + if (staticCallbackListener != DEFAULT_LISTENER || callbackListener == null) + { + staticCallbackListener.onFailureOf(getThis(), msg, caught); + } final IPageController pageController = viewContext.getPageController(); if (caught instanceof InvalidSessionException) { @@ -151,11 +197,13 @@ public abstract class AbstractAsyncCallback<T> implements AsyncCallback<T> return; } process(result); - callbackListener.finishOnSuccessOf(getThis(), result); + if (callbackListener != null) + { + callbackListener.finishOnSuccessOf(getThis(), result); + } + if (staticCallbackListener != DEFAULT_LISTENER || callbackListener == null) + { + staticCallbackListener.finishOnSuccessOf(getThis(), result); + } } - - /** - * Processes the specified result of an asynchronous method invocation. - */ - protected abstract void process(T result); } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InfoBox.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InfoBox.java index 1f60eee953a308538fe1367f2f9f7f4b4702b8f2..496f12b3bb74130b43179886aae2d9056902138e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InfoBox.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/widget/InfoBox.java @@ -16,48 +16,101 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget; -import com.extjs.gxt.ui.client.widget.form.LabelField; +import com.extjs.gxt.ui.client.util.TextMetrics; +import com.extjs.gxt.ui.client.widget.Html; +import com.extjs.gxt.ui.client.widget.MessageBox; import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.StringUtils; /** + * A {@link Html} extension that should be used as information panel. + * <p> + * It nicely informs the user about a certain action result. It should be used instead of a + * {@link MessageBox} in some cases. + * </p> + * * @author Christian Ribeaud */ -public final class InfoBox extends LabelField +public final class InfoBox extends Html { public InfoBox() { - setVisible(false); setStyleAttribute("textAlign", "center"); - setPosition(-2, 0); + setStyleAttribute("borderStyle", "solid"); + setStyleAttribute("borderWidth", "1px"); + setHeight(computeHeight()); + reset(); } - private void setStrongStyle() + private final int computeHeight() { - setStyleAttribute("backgroundColor", "#feffbe"); - setStyleAttribute("border", "1px solid #edee8b"); + final TextMetrics textMetrics = TextMetrics.get(); + textMetrics.bind(getElement()); + return textMetrics.getHeight("X"); } - private void setLightStyle() + /** + * Display given <var>text</var> as <i>error</i> text. + */ + public final void displayError(final String text) { - setStyleAttribute("backgroundColor", "#feffdf"); - setStyleAttribute("color", "gray"); - setStyleAttribute("border", "1px solid #e7e7e7"); + display(text, Type.ERROR); } - public void fade() + /** + * Display given <var>text</var> as <i>info</i> text. + */ + public final void displayInfo(final String text) { - setLightStyle(); + display(text, Type.INFO); } - public void display(final String text) + /** + * Displays given <var>text</var> of given <var>type</var>. + */ + public final void display(final String text, final Type type) { if (StringUtils.isBlank(text) == false) { - setStrongStyle(); - setVisible(true); - setText(text); + setStyleAttribute("backgroundColor", type.backgroundColor); + setStyleAttribute("borderColor", type.borderColor); + setHtml(text); + } + } + + /** + * Resets the info box. + * <p> + * Background resp. border color are reset to <i>white</i>. And <i>HTML</i> text is reset to + * empty string. + * </p> + */ + public final void reset() + { + setStyleAttribute("backgroundColor", "#ffffff"); + setStyleAttribute("borderColor", "#ffffff"); + setHtml(""); + } + + // + // Helper classes + // + + private static enum Type + { + + ERROR("#f6cece", "#f5a9a9"), INFO("#cef6ce", "#a9f5a9"); + + private final String backgroundColor; + + private final String borderColor; + + private Type(final String backgroundColor, final String borderColor) + { + + this.backgroundColor = backgroundColor; + this.borderColor = borderColor; } } } \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java index 32cf560f15f7a11c64e36ea9a517a3240324fbba..1a75b571a406c30b5f27f4c855dfa9e134b4b4de 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleBatchRegistrationForm.java @@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.generic.client.web.client.application.sa import com.extjs.gxt.ui.client.Events; import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.Style.Scroll; import com.extjs.gxt.ui.client.event.ButtonEvent; import com.extjs.gxt.ui.client.event.FormEvent; import com.extjs.gxt.ui.client.event.Listener; @@ -65,6 +66,7 @@ public final class GenericSampleBatchRegistrationForm extends LayoutContainer final IViewContext<IGenericClientServiceAsync> viewContext, final SampleType sampleType) { super(createLayout()); + setScrollMode(Scroll.AUTO); this.viewContext = viewContext; add(createUI()); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java index 9f33955e94669b793297267acc52445ae24c335f..f96996a571bf30394c5ef90a32d42d0172559959 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/client/web/client/application/sample/GenericSampleRegistrationForm.java @@ -22,11 +22,13 @@ import java.util.List; import com.extjs.gxt.ui.client.Events; import com.extjs.gxt.ui.client.Style.HorizontalAlignment; -import com.extjs.gxt.ui.client.event.BaseEvent; -import com.extjs.gxt.ui.client.event.ComponentEvent; +import com.extjs.gxt.ui.client.Style.Scroll; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.util.Format; +import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.AdapterField; import com.extjs.gxt.ui.client.widget.form.CheckBox; @@ -36,11 +38,14 @@ import com.extjs.gxt.ui.client.widget.form.FormPanel; import com.extjs.gxt.ui.client.widget.form.MultiField; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.form.Validator; +import com.extjs.gxt.ui.client.widget.layout.FlowLayout; import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.ListBox; import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback; import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ICallbackListener; import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext; import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.DateRenderer; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.GroupSelectionWidget; @@ -60,7 +65,7 @@ import ch.systemsx.cisd.openbis.plugin.generic.client.web.client.IGenericClientS * * @author Izabela Adamczyk */ -public final class GenericSampleRegistrationForm extends FormPanel +public final class GenericSampleRegistrationForm extends LayoutContainer { private static final String PREFIX = "generic-sample-registration_"; @@ -100,6 +105,8 @@ public final class GenericSampleRegistrationForm extends FormPanel private InfoBox infoBox; + private FormPanel formPanel; + private static final String MANDATORY_LABEL_SEPARATOR = ": *"; static final int LABEL_WIDTH = 100; @@ -109,27 +116,34 @@ public final class GenericSampleRegistrationForm extends FormPanel public GenericSampleRegistrationForm( final IViewContext<IGenericClientServiceAsync> viewContext, final SampleType sampleType) { + setLayout(new FlowLayout(5)); this.viewContext = viewContext; this.sampleType = sampleType; - configureForm(); - createFormFields(); + setScrollMode(Scroll.AUTO); + add(infoBox = createInfoBox()); + add(formPanel = creatFormPanel()); + } + + private final static InfoBox createInfoBox() + { + final InfoBox infoBox = new InfoBox(); + return infoBox; } private final void createFormFields() { - infoBox = new InfoBox(); codeField = new CodeField(viewContext.getMessageProvider().getMessage("code")); codeField.setId(CODE_FIELD_ID); - codeField.addListener(Events.Focus, new Listener<BaseEvent>() + codeField.addListener(Events.Focus, new Listener<FieldEvent>() { // // Listener // - public final void handleEvent(final BaseEvent be) + public final void handleEvent(final FieldEvent be) { - infoBox.fade(); + infoBox.reset(); } }); @@ -140,13 +154,13 @@ public final class GenericSampleRegistrationForm extends FormPanel sharedCheckbox.setId(SHARED_CHECKBOX_ID); sharedCheckbox.setBoxLabel("Shared"); sharedCheckbox.setValue(SELECT_GROUP_BY_DEFAULT == false); - sharedCheckbox.addListener(Events.Change, new Listener<BaseEvent>() + sharedCheckbox.addListener(Events.Change, new Listener<FieldEvent>() { // // Listener // - public final void handleEvent(final BaseEvent be) + public final void handleEvent(final FieldEvent be) { groupSelectionWidget .setEnabled(sharedCheckbox.getValue().booleanValue() == false); @@ -192,20 +206,21 @@ public final class GenericSampleRegistrationForm extends FormPanel } } - private final void configureForm() + private final FormPanel creatFormPanel() { - setHeaderVisible(false); - setBodyBorder(false); - setWidth(LABEL_WIDTH + FIELD_WIDTH + 40); - - setLabelWidth(LABEL_WIDTH); - setFieldWidth(FIELD_WIDTH); - setButtonAlign(HorizontalAlignment.RIGHT); + final FormPanel panel = new FormPanel(); + panel.setHeaderVisible(false); + panel.setBodyBorder(false); + panel.setWidth(LABEL_WIDTH + FIELD_WIDTH + 40); + + panel.setLabelWidth(LABEL_WIDTH); + panel.setFieldWidth(FIELD_WIDTH); + panel.setButtonAlign(HorizontalAlignment.RIGHT); final Button saveButton = new Button(viewContext.getMessageProvider().getMessage("button_save")); saveButton.setStyleAttribute("marginRight", "20px"); saveButton.setId(SAVE_BUTTON_ID); - saveButton.addSelectionListener(new SelectionListener<ComponentEvent>() + saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() { // @@ -213,14 +228,14 @@ public final class GenericSampleRegistrationForm extends FormPanel // @Override - public final void componentSelected(final ComponentEvent ce) + public final void componentSelected(final ButtonEvent ce) { submitForm(); } }); final Button resetButton = new Button(viewContext.getMessageProvider().getMessage("button_reset")); - resetButton.addSelectionListener(new SelectionListener<ComponentEvent>() + resetButton.addSelectionListener(new SelectionListener<ButtonEvent>() { // @@ -228,13 +243,14 @@ public final class GenericSampleRegistrationForm extends FormPanel // @Override - public final void componentSelected(final ComponentEvent ce) + public final void componentSelected(final ButtonEvent ce) { - reset(); + formPanel.reset(); } }); - addButton(resetButton); - addButton(saveButton); + panel.addButton(resetButton); + panel.addButton(saveButton); + return panel; } private final String createSampleIdentifier() @@ -281,7 +297,7 @@ public final class GenericSampleRegistrationForm extends FormPanel private final void submitForm() { - if (isValid()) + if (formPanel.isValid()) { final SampleToRegister sampleToRegister = new SampleToRegister(createSampleIdentifier(), sampleType.getCode(), @@ -302,25 +318,15 @@ public final class GenericSampleRegistrationForm extends FormPanel } } - private final void resetForm(final String info) + private final void addFormFields() { - createFormFields(); - addFormFields(); - infoBox.display(info); - layout(); - } - - public void addFormFields() - { - removeAll(); - add(infoBox); - add(codeField); - add(groupMultiField); - add(parentGenerator); - add(parentContainer); + formPanel.add(codeField); + formPanel.add(groupMultiField); + formPanel.add(parentGenerator); + formPanel.add(parentContainer); for (final Field<?> propertyField : propertyFields) { - add(propertyField); + formPanel.add(propertyField); } } @@ -369,6 +375,7 @@ public final class GenericSampleRegistrationForm extends FormPanel protected final void onRender(final Element target, final int index) { super.onRender(target, index); + createFormFields(); addFormFields(); } @@ -380,7 +387,30 @@ public final class GenericSampleRegistrationForm extends FormPanel { RegisterSampleCallback(final IViewContext<?> viewContext) { - super(viewContext); + super(viewContext, new ICallbackListener() + { + + // + // ICallbackListener + // + + public final void finishOnSuccessOf(final AsyncCallback<Object> callback, + final Object result) + { + final String message = + createSuccessfullRegistrationInfo(sharedCheckbox.getValue(), + codeField.getValue(), groupSelectionWidget + .tryGetSelectedGroup()); + infoBox.displayInfo(message); + formPanel.reset(); + } + + public final void onFailureOf(final AsyncCallback<Object> callback, + final String failureMessage, final Throwable throwable) + { + infoBox.displayError(failureMessage); + } + }); } // @@ -390,11 +420,6 @@ public final class GenericSampleRegistrationForm extends FormPanel @Override protected final void process(final Void result) { - - final String message = - createSuccessfullRegistrationInfo(sharedCheckbox.getValue(), codeField - .getValue(), groupSelectionWidget.tryGetSelectedGroup()); - resetForm(message); } } diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java index 7031385c8eb3d99ced49562cc174f160690a581a..35675f1c7ea58b901fe6dd3de556031b57df58ea 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/testframework/RemoteConsole.java @@ -56,7 +56,7 @@ public class RemoteConsole { this.testCase = testCase; commands = new ArrayList<ITestCommand>(); - AbstractAsyncCallback.setCallbackListener(new ICallbackListener() + AbstractAsyncCallback.setStaticCallbackListener(new ICallbackListener() { public void onFailureOf(AsyncCallback<Object> callback, String failureMessage, Throwable throwable) @@ -121,7 +121,7 @@ public class RemoteConsole @Override public void run() { - AbstractAsyncCallback.setCallbackListener(null); + AbstractAsyncCallback.setStaticCallbackListener(null); int numberOfUnexcutedCommands = commands.size() - entryIndex; if (numberOfUnexcutedCommands > 0) {