/*
* Copyright ${year} Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.workbench.common.stunner.standalone.client.screens;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Dependent;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import com.google.gwt.logging.client.LogConfiguration;
import com.google.gwt.user.client.ui.IsWidget;
import org.kie.workbench.common.stunner.client.widgets.menu.dev.MenuDevCommandsBuilder;
import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionPresenter;
import org.kie.workbench.common.stunner.client.widgets.presenters.session.SessionPresenterFactory;
import org.kie.workbench.common.stunner.client.widgets.views.session.ScreenErrorView;
import org.kie.workbench.common.stunner.client.widgets.views.session.ScreenPanelView;
import org.kie.workbench.common.stunner.core.api.DefinitionManager;
import org.kie.workbench.common.stunner.core.client.api.SessionManager;
import org.kie.workbench.common.stunner.core.client.canvas.CanvasHandler;
import org.kie.workbench.common.stunner.core.client.service.ClientDiagramService;
import org.kie.workbench.common.stunner.core.client.service.ClientRuntimeError;
import org.kie.workbench.common.stunner.core.client.service.ServiceCallback;
import org.kie.workbench.common.stunner.core.client.session.ClientReadOnlySession;
import org.kie.workbench.common.stunner.core.client.session.ClientSession;
import org.kie.workbench.common.stunner.core.client.session.event.OnSessionErrorEvent;
import org.kie.workbench.common.stunner.core.client.session.impl.AbstractClientFullSession;
import org.kie.workbench.common.stunner.core.client.session.impl.AbstractClientReadOnlySession;
import org.kie.workbench.common.stunner.core.client.util.ClientSessionUtils;
import org.kie.workbench.common.stunner.core.diagram.Diagram;
import org.uberfire.client.annotations.WorkbenchContextId;
import org.uberfire.client.annotations.WorkbenchMenu;
import org.uberfire.client.annotations.WorkbenchPartTitle;
import org.uberfire.client.annotations.WorkbenchPartView;
import org.uberfire.client.annotations.WorkbenchScreen;
import org.uberfire.client.mvp.PlaceManager;
import org.uberfire.client.workbench.events.ChangeTitleWidgetEvent;
import org.uberfire.ext.widgets.common.client.common.BusyPopup;
import org.uberfire.lifecycle.OnClose;
import org.uberfire.lifecycle.OnFocus;
import org.uberfire.lifecycle.OnLostFocus;
import org.uberfire.lifecycle.OnOpen;
import org.uberfire.lifecycle.OnStartup;
import org.uberfire.mvp.Command;
import org.uberfire.mvp.PlaceRequest;
import org.uberfire.workbench.model.menu.MenuFactory;
import org.uberfire.workbench.model.menu.MenuItem;
import org.uberfire.workbench.model.menu.Menus;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
import static org.uberfire.commons.validation.PortablePreconditions.checkNotNull;
// TODO: i18n.
@Dependent
@WorkbenchScreen(identifier = SessionDiagramViewerScreen.SCREEN_ID)
public class SessionDiagramViewerScreen {
private static Logger LOGGER = Logger.getLogger(SessionDiagramViewerScreen.class.getName());
public static final String SCREEN_ID = "SessionDiagramViewerScreen";
private final ShowcaseDiagramService diagramLoader;
private final SessionManager sessionManager;
private final SessionPresenterFactory<Diagram, AbstractClientReadOnlySession, AbstractClientFullSession> sessionPresenterFactory;
private final PlaceManager placeManager;
private final Event<ChangeTitleWidgetEvent> changeTitleNotificationEvent;
private final MenuDevCommandsBuilder menuDevCommandsBuilder;
private final ScreenPanelView screenPanelView;
private final ScreenErrorView screenErrorView;
private SessionPresenter<AbstractClientReadOnlySession, ?, Diagram> presenter;
private PlaceRequest placeRequest;
private String title = "Viewer Screen";
private Menus menu = null;
@Inject
public SessionDiagramViewerScreen(final DefinitionManager definitionManager,
final ClientDiagramService clientDiagramServices,
final ShowcaseDiagramService diagramLoader,
final SessionManager sessionManager,
final SessionPresenterFactory<Diagram, AbstractClientReadOnlySession, AbstractClientFullSession> sessionPresenterFactory,
final PlaceManager placeManager,
final Event<ChangeTitleWidgetEvent> changeTitleNotificationEvent,
final ClientSessionUtils sessionUtils,
final MenuDevCommandsBuilder menuDevCommandsBuilder,
final ScreenPanelView screenPanelView,
final ScreenErrorView screenErrorView) {
this.diagramLoader = diagramLoader;
this.sessionManager = sessionManager;
this.sessionPresenterFactory = sessionPresenterFactory;
this.placeManager = placeManager;
this.changeTitleNotificationEvent = changeTitleNotificationEvent;
this.menuDevCommandsBuilder = menuDevCommandsBuilder;
this.screenPanelView = screenPanelView;
this.screenErrorView = screenErrorView;
}
@PostConstruct
@SuppressWarnings("unchecked")
public void init() {
}
@OnStartup
public void onStartup(final PlaceRequest placeRequest) {
this.placeRequest = placeRequest;
this.menu = makeMenuBar();
final String name = placeRequest.getParameter("name",
"");
final boolean isCreate = name == null || name.trim().length() == 0;
if (isCreate) {
LOGGER.log(SEVERE,
"This screen it's just read only!");
} else {
// Load an existing diagram.
load(name,
() -> {
final Diagram diagram = getDiagram();
if (null != diagram) {
// Update screen title.
updateTitle(diagram.getMetadata().getTitle());
}
});
}
}
private Menus makeMenuBar() {
if (menuDevCommandsBuilder.isEnabled()) {
return MenuFactory
.newTopLevelMenu("Dev")
.withItems(new ArrayList<MenuItem>(1) {{
add(menuDevCommandsBuilder.build());
}})
.endMenu()
.build();
}
return null;
}
private void load(final String name,
final Command callback) {
BusyPopup.showMessage("Loading");
diagramLoader.loadByName(name,
new ServiceCallback<Diagram>() {
@Override
public void onSuccess(final Diagram diagram) {
final AbstractClientReadOnlySession session = newSession(diagram);
presenter = sessionPresenterFactory.newPresenterViewer();
screenPanelView.setWidget(presenter.getView());
presenter
.withToolbar(true)
.withPalette(false)
.displayNotifications(type -> true).open(diagram,
session,
new SessionPresenter.SessionPresenterCallback<AbstractClientReadOnlySession, Diagram>() {
@Override
public void afterSessionOpened() {
}
@Override
public void afterCanvasInitialized() {
}
@Override
public void onSuccess() {
BusyPopup.close();
callback.execute();
}
@Override
public void onError(final ClientRuntimeError error) {
SessionDiagramViewerScreen.this.showError(error);
callback.execute();
}
});
}
@Override
public void onError(final ClientRuntimeError error) {
SessionDiagramViewerScreen.this.showError(error);
callback.execute();
}
});
}
private AbstractClientReadOnlySession newSession(final Diagram diagram) {
return (AbstractClientReadOnlySession) sessionManager.getSessionFactory(diagram,
ClientReadOnlySession.class).newSession();
}
private void updateTitle(final String title) {
// Change screen title.
SessionDiagramViewerScreen.this.title = title;
changeTitleNotificationEvent.fire(new ChangeTitleWidgetEvent(placeRequest,
this.title));
}
@OnOpen
public void onOpen() {
resume();
}
@OnFocus
public void onFocus() {
if (null != getSession() && !isSameSession(sessionManager.getCurrentSession())) {
sessionManager.open(getSession());
} else if (null != getSession()) {
log(FINE,
"Session already active, no action.");
}
}
private boolean isSameSession(final ClientSession other) {
checkNotNull("session",
getSession());
return null != other && getSession().equals(other);
}
@OnLostFocus
public void OnLostFocus() {
}
@OnClose
public void onClose() {
destroySession();
}
@WorkbenchMenu
public Menus getMenu() {
return menu;
}
private void resume() {
if (null != getSession()) {
sessionManager.resume(getSession());
}
}
private void destroySession() {
presenter.destroy();
}
@WorkbenchPartTitle
public String getTitle() {
return title;
}
@WorkbenchPartView
public IsWidget getWidget() {
return screenPanelView.asWidget();
}
@WorkbenchContextId
public String getMyContextRef() {
return "sessionDiagramViewerScreenContext";
}
private AbstractClientReadOnlySession getSession() {
return null != presenter ? presenter.getInstance() : null;
}
private CanvasHandler getCanvasHandler() {
return null != sessionManager.getCurrentSession() ? sessionManager.getCurrentSession().getCanvasHandler() : null;
}
private Diagram getDiagram() {
return null != getCanvasHandler() ? getCanvasHandler().getDiagram() : null;
}
private void showError(final ClientRuntimeError error) {
screenErrorView.showError(error);
screenPanelView.setWidget(screenErrorView.asWidget());
log(Level.SEVERE,
error.toString());
BusyPopup.close();
}
void onSessionErrorEvent(@Observes OnSessionErrorEvent errorEvent) {
if (null != getSession() && isSameSession(errorEvent.getSession())) {
showError(errorEvent.getError());
// TODO executeWithConfirm( "An error happened [" + errorEvent.getError() + "]. Do you want" +
// "to refresh the diagram (Last changes can be lost)? ", this::menu_refresh );
}
}
private void log(final Level level,
final String message) {
if (LogConfiguration.loggingIsEnabled()) {
LOGGER.log(level,
message);
}
}
}