package org.ovirt.engine.ui.webadmin.uicommon.model;
import org.ovirt.engine.core.compat.Event;
import org.ovirt.engine.core.compat.EventArgs;
import org.ovirt.engine.core.compat.IEventListener;
import org.ovirt.engine.core.compat.PropertyChangedEventArgs;
import org.ovirt.engine.ui.uicommonweb.UICommand;
import org.ovirt.engine.ui.uicommonweb.models.CommonModel;
import org.ovirt.engine.ui.uicommonweb.models.ConfirmationModel;
import org.ovirt.engine.ui.uicommonweb.models.EntityModel;
import org.ovirt.engine.ui.uicommonweb.models.Model;
import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel;
import org.ovirt.engine.ui.webadmin.gin.ClientGinjector;
import org.ovirt.engine.ui.webadmin.section.main.presenter.popup.AbstractModelBoundPopupPresenterWidget;
import org.ovirt.engine.ui.webadmin.section.main.presenter.popup.DefaultConfirmationPopupPresenterWidget;
import org.ovirt.engine.ui.webadmin.uicommon.model.CommonModelChangeEvent.CommonModelChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.inject.Provider;
import com.gwtplatform.mvp.client.proxy.RevealRootPopupContentEvent;
/**
* Basic {@link ModelProvider} implementation that uses {@link CommonModelManager} for accessing the CommonModel
* instance.
*
* @param <M>
* Model type.
*/
public abstract class TabModelProvider<M extends EntityModel> implements ModelProvider<M> {
private final EventBus eventBus;
private final Provider<DefaultConfirmationPopupPresenterWidget> defaultConfirmPopupProvider;
private AbstractModelBoundPopupPresenterWidget<?, ?> windowPopup;
private AbstractModelBoundPopupPresenterWidget<?, ?> confirmWindowPopup;
public TabModelProvider(ClientGinjector ginjector) {
this.eventBus = ginjector.getEventBus();
this.defaultConfirmPopupProvider = ginjector.getDefaultConfirmationPopupProvider();
// Add handler to be notified when the CommonModel instance changes
eventBus.addHandler(CommonModelChangeEvent.getType(), new CommonModelChangeHandler() {
@Override
public void onCommonModelChange(CommonModelChangeEvent event) {
TabModelProvider.this.onCommonModelChange();
}
});
}
@Override
public void setEntity(Object value) {
getModel().setEntity(value);
}
protected CommonModel getCommonModel() {
return CommonModelManager.instance();
}
/**
* Callback fired when the {@link CommonModel} reference changes.
* <p>
* Override this method to register custom listeners on the corresponding model.
*/
protected void onCommonModelChange() {
// Add necessary property change handlers
getModel().getPropertyChangedEvent().addListener(new IEventListener() {
@Override
public void eventRaised(Event ev, Object sender, EventArgs args) {
String propName = ((PropertyChangedEventArgs) args).PropertyName;
// Handle popups that bind to "Window" and "ConfirmWindow" model properties
if ("Window".equals(propName)) {
handleWindowModelChange(windowPopup, false);
} else if ("ConfirmWindow".equals(propName)) {
handleWindowModelChange(confirmWindowPopup, true);
}
}
});
}
@SuppressWarnings("unchecked")
void handleWindowModelChange(AbstractModelBoundPopupPresenterWidget<?, ?> popup, boolean isConfirm) {
Model windowModel = isConfirm ? getModel().getConfirmWindow() : getModel().getWindow();
// Reveal new popup
if (windowModel != null && popup == null) {
AbstractModelBoundPopupPresenterWidget<?, ?> newPopup = null;
UICommand lastExecutedCommand = getModel().getLastExecutedCommand();
// Resolve
if (windowModel instanceof ConfirmationModel) {
newPopup = getConfirmModelPopup(lastExecutedCommand);
} else {
newPopup = getModelPopup(lastExecutedCommand);
}
// Reveal
if (newPopup != null) {
revealAndAssignPopup(windowModel,
(AbstractModelBoundPopupPresenterWidget<Model, ?>) newPopup, isConfirm);
} else {
// No popup bound to model, need to clear model reference manually
if (isConfirm) {
getModel().setConfirmWindow(null);
} else {
getModel().setWindow(null);
}
}
}
// Hide existing popup
else if (windowModel == null && popup != null) {
hideAndClearPopup(popup, isConfirm);
forceRefresh(getModel());
}
}
protected AbstractModelBoundPopupPresenterWidget<? extends Model, ?> getModelPopup(UICommand lastExecutedCommand) {
// No-op, override as necessary
return null;
}
protected AbstractModelBoundPopupPresenterWidget<? extends ConfirmationModel, ?> getConfirmModelPopup(UICommand lastExecutedCommand) {
// Reveal basic confirmation popup by default
return defaultConfirmPopupProvider.get();
}
/**
* Reveals a popup bound to the given model.
*/
public <T extends Model> void revealPopup(final T model,
final AbstractModelBoundPopupPresenterWidget<T, ?> popup) {
assert (model != null) : "Popup model must not be null";
// Initialize popup
popup.init(model);
// Add "Progress" property change handler to Window model
model.getPropertyChangedEvent().addListener(new IEventListener() {
@Override
public void eventRaised(Event ev, Object sender, EventArgs args) {
PropertyChangedEventArgs pcArgs = (PropertyChangedEventArgs) args;
if ("Progress".equals(pcArgs.PropertyName)) {
if (model.getProgress() != null) {
popup.startProgress(model.getProgress().getCurrentOperation());
} else {
popup.stopProgress();
}
}
}
});
// Reveal popup
RevealRootPopupContentEvent.fire(eventBus, popup);
}
public <T extends Model> void revealAndAssignPopup(T model,
AbstractModelBoundPopupPresenterWidget<T, ?> popup, boolean isConfirm) {
revealPopup(model, popup);
// Assign popup reference
if (isConfirm) {
confirmWindowPopup = popup;
} else {
windowPopup = popup;
}
}
void hideAndClearPopup(AbstractModelBoundPopupPresenterWidget<?, ?> popup, boolean isConfirm) {
popup.hideAndUnbind();
// Clear popup reference
if (isConfirm) {
confirmWindowPopup = null;
} else {
windowPopup = null;
}
}
void forceRefresh(M model) {
if (model instanceof SearchableListModel && !model.getLastExecutedCommand().getIsCancel()) {
// Refresh the grid after a Dialog
SearchableListModel searchableList = (SearchableListModel) model;
searchableList.getForceRefreshCommand().Execute();
}
}
}