package com.cedarsoft.spring.rcp.forms;
import com.cedarsoft.spring.SpringSupport;
import com.cedarsoft.spring.rcp.async.BackgroundAction;
import com.cedarsoft.spring.rcp.async.BlockingBackgroundActionRunner;
import com.cedarsoft.spring.rcp.dialog.ExtendedConfirmationDialog;
import com.cedarsoft.CanceledException;
import com.cedarsoft.SwingHelper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.binding.form.ValidatingFormModel;
import org.springframework.richclient.application.event.LifecycleApplicationEvent;
import org.springframework.richclient.dialog.ConfirmationDialog;
/**
* Represents a form with all necessary objects to display/edit/commit that form
*
* @param <T> the type
*/
public class DefaultFormUi<T> implements FormUi<T> {
@NotNull
private final FormFactory<T> formFactory;
@NotNull
private final FormBackend backend;
@NotNull
@NonNls
private final String baseId;
/**
* Do not use directly. Use {@link #getForm()} instead.
*/
private ExtendedForm<? extends T> form;
/**
* Creates a new form ui support
*
* @param baseId the base id
* @param backend the backend
* @param formFactory the form factory
*/
public DefaultFormUi( @NotNull @NonNls String baseId, @NotNull FormBackend backend, @NotNull FormFactory<T> formFactory ) {
this.baseId = baseId;
this.backend = backend;
this.formFactory = formFactory;
}
/**
* Old constructor
*
* @param form the form
*/
@Deprecated
public DefaultFormUi( @NotNull final ExtendedForm<? extends T> form ) {
this( form.getId(), new AbstractStaticFormBackend<T>( form.getFormModel() ) {
@Override
public void commit() {
form.commit();
}
}, new StaticFormFactory<T>( form ) );
}
/**
* Returns the form that is shown
*
* @return the form
*
* @throws CanceledException
*/
@Override
@NotNull
public ExtendedForm<? extends T> getForm() throws CanceledException {
if ( form == null ) {
form = formFactory.createForm( backend.getFormModel() );
}
return form;
}
/**
* Returns the form object
*
* @return the form object
*/
@Override
@NotNull
public T getFormObject() {
return getForm().getFormObject();
}
@Override
public void revert() {
revert( null );
}
@Override
public void revert( @Nullable final Runnable callback ) {
if ( getFormModel().isDirty() ) {
String msg = springSupport.getMessage( baseId + ".dirtyRevertMessage" );
String title = springSupport.getMessage( baseId + ".dirtyRevertTitle" );
ConfirmationDialog dlg = new ConfirmationDialog( title, msg ) {
@Override
protected void onConfirm() {
getFormModel().revert();
if ( callback != null ) {
callback.run();
}
}
};
dlg.showDialog();
} else {
getFormModel().revert();
if ( callback != null ) {
callback.run();
}
}
}
@NotNull
private ValidatingFormModel getFormModel() {
return getForm().getFormModel();
}
@Override
public void commit() {
SwingHelper.assertEventThread();
commit( shallAskForConfirmationOnCommit() );
}
/**
* Returns whether it shall be asked for confirmation on commit
*
* @return true if shall be asked for confirmation, false otherwise
*/
protected boolean shallAskForConfirmationOnCommit() {
return backend.shallAskForCommitConfirmation();
}
@Override
public void commit( boolean shallAskForConfirmation ) throws CanceledException {
if ( !getForm().isDirty() ) {
return; //Unnecessary to commit
}
if ( shallAskForConfirmation ) {
if ( !askForCommitConfirmation() ) {
//User declined commiting...
return;
}
}
getForm().commit();
new BlockingBackgroundActionRunner( springSupport.getActiveApplicationWindow(), new BackgroundAction( "saving" ) {
@Override
protected void executeInBackground() throws Exception {
String eventType;
if ( backend.isCreatingNew() ) {
eventType = LifecycleApplicationEvent.CREATED;
} else {
eventType = LifecycleApplicationEvent.MODIFIED;
}
backend.commit();
// And notify the rest of the application of the change
springSupport.publishEvent( new LifecycleApplicationEvent( eventType, getFormObject() ) );
}
} ).run();
}
/**
* Asks for commit confirmation
*
* @return whether it shall be commited
*
* @throws CanceledException
*/
protected boolean askForCommitConfirmation() throws CanceledException {
final Boolean[] confirmed = {null};
ExtendedConfirmationDialog dlg = new ExtendedConfirmationDialog( SpringSupport.INSTANCE.getMessage( "form.model.commit.title" ), null, SpringSupport.INSTANCE.getMessage( "form.model.commit.message" ) ) {
@Override
protected void onConfirm() {
confirmed[0] = true;
}
@Override
protected void onNo() {
confirmed[0] = false;
}
};
dlg.showDialog();
if ( confirmed[0] == null ) {
throw new CanceledException();
} else {
return confirmed[0];
}
}
@NotNull
public String getBaseId() {
return baseId;
}
@NotNull
public FormBackend getBackend() {
return backend;
}
@NotNull
public FormFactory<T> getFormFactory() {
return formFactory;
}
@NotNull
private final SpringSupport springSupport = SpringSupport.INSTANCE;
}