package org.ovirt.engine.ui.userportal.client.views.extended.maingrid.components;
import java.util.HashMap;
import java.util.Map;
import com.google.gwt.core.client.GWT;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VMStatus;
import org.ovirt.engine.core.common.businessentities.VmOsType;
import org.ovirt.engine.core.common.businessentities.vm_pools;
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.ui.frontend.ConsoleErrors;
import org.ovirt.engine.ui.frontend.ErrorTranslator;
import org.ovirt.engine.ui.frontend.Message;
import org.ovirt.engine.ui.uicommon.UICommand;
import org.ovirt.engine.ui.uicommon.models.userportal.UserPortalItemModel;
import org.ovirt.engine.ui.uicommon.models.vms.ConsoleModel;
import org.ovirt.engine.ui.uicommon.models.vms.ErrorCodeEventArgs;
import org.ovirt.engine.ui.uicommon.models.vms.SpiceConsoleModel;
import org.ovirt.engine.ui.uicompat.EnumTranslator;
import org.ovirt.engine.ui.uicompat.Translator;
import org.ovirt.engine.ui.userportal.client.common.Severity;
import org.ovirt.engine.ui.userportal.client.components.GridElement;
import org.ovirt.engine.ui.userportal.client.components.UPLabel;
import org.ovirt.engine.ui.userportal.client.modalpanels.ConsoleEditPanel;
import org.ovirt.engine.ui.userportal.client.modalpanels.MessageDialog;
import org.ovirt.engine.ui.userportal.client.protocols.ConsoleUtils;
import org.ovirt.engine.ui.userportal.client.protocols.Protocol;
import org.ovirt.engine.ui.userportal.client.protocols.ProtocolOptionContainer;
import org.ovirt.engine.ui.userportal.client.uicommonext.RDPInterfaceImpl;
import org.ovirt.engine.ui.userportal.client.uicommonext.SpiceInterfaceImpl;
import org.ovirt.engine.ui.userportal.client.util.UserPortalTools;
import org.ovirt.engine.ui.userportal.client.views.extended.maingrid.UserPortalItemsGrid;
import com.smartgwt.client.types.ImageStyle;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.ImgButton;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.MouseOutEvent;
import com.smartgwt.client.widgets.events.MouseOutHandler;
import com.smartgwt.client.widgets.events.MouseOverEvent;
import com.smartgwt.client.widgets.events.MouseOverHandler;
import com.smartgwt.client.widgets.layout.HLayout;
public class MainGridItem extends HLayout implements GridElement<UserPortalItemModel>, ProtocolOptionContainer {
public static final int MAIN_GRID_ITEM_HEIGHT = 50;
private Img vmImage;
private Img vmImageDisabledMask;
private UPLabel nameLabel;
private UPLabel descriptionLabel;
private Img statusImage;
private ActionButton runButton;
private ActionButton shutdownButton;
private ActionButton suspendButton;
private ActionButton powerButton;
private ImgButton consoleButton;
private ImgButton consoleEditButton;
private UserPortalItemModel currentItem;
private MainGridItem mainGridItem = this;
private Object entityGuid;
private static final int VM_IMAGE_WIDTH = 51;
private static final int VM_IMAGE_HEIGHT = 41;
private static final int STATUS_IMAGE_WIDTH = 35;
private static final int ACTION_BUTTON_SIZE = 24;
private boolean isSelected = false;
private Translator statusTranslator = EnumTranslator.Create(VMStatus.class);
private Translator osTranslator = EnumTranslator.Create(VmOsType.class);
private UserPortalItemsGrid parent;
private Protocol selectedProtocol;
private String protocolMessage;
private String itemID;
public MainGridItem(UserPortalItemsGrid parent, UserPortalItemModel item) {
this.parent = parent;
setHeight(MAIN_GRID_ITEM_HEIGHT);
setWidth100();
setMembersMargin(1);
setCanHover(true);
setCanFocus(true);
setStyleName("mainGrid-row");
setLayoutLeftMargin(7);
entityGuid = item.getIsPool() ? ((vm_pools)item.getEntity()).getvm_pool_id() : ((VM)item.getEntity()).getvm_guid();
itemID = UserPortalTools.getSafeId(entityGuid.toString());
currentItem = item;
vmImage = new Img();
vmImage.setWidth(VM_IMAGE_WIDTH);
vmImage.setHeight(VM_IMAGE_HEIGHT);
vmImage.setLayoutAlign(VerticalAlignment.CENTER);
vmImage.setBorder("1px solid white");
vmImage.setHoverOpacity(75);
vmImage.setHoverStyle("gridToolTipStyle");
vmImage.setHoverWidth(1);
vmImage.setHoverWrap(false);
vmImage.setHoverDelay(500);
vmImageDisabledMask = new Img("general/tvlayout_disabled_mask.png", VM_IMAGE_WIDTH-2, VM_IMAGE_HEIGHT-2);
vmImageDisabledMask.hide();
vmImage.addChild(vmImageDisabledMask);
nameLabel = new UPLabel("mainGrid-VMname");
nameLabel.setLayoutAlign(VerticalAlignment.CENTER);
nameLabel.setAutoFit(true);
descriptionLabel = new UPLabel("mainGrid-VMdescription");
descriptionLabel.setLayoutAlign(VerticalAlignment.CENTER);
descriptionLabel.setAutoFit(true);
statusImage = new Img();
statusImage.setImageType(ImageStyle.CENTER);
statusImage.setWidth(STATUS_IMAGE_WIDTH);
statusImage.setHoverOpacity(75);
statusImage.setHoverStyle("gridToolTipStyle");
statusImage.setHoverWidth(1);
statusImage.setHoverWrap(false);
statusImage.setHoverDelay(500);
HLayout actionButtonsLayout = new HLayout(3);
actionButtonsLayout.setShowEdges(true);
actionButtonsLayout.setEdgeSize(8);
actionButtonsLayout.setEdgeImage("edges/buttonslayout.png");
actionButtonsLayout.setHeight(40);
actionButtonsLayout.setAutoWidth();
actionButtonsLayout.setLayoutAlign(VerticalAlignment.CENTER);
actionButtonsLayout.setStyleName("mainGrid-actionButtons");
runButton = new ActionButton("actions/play.png", item.getIsPool() ? item.getTakeVmCommand() : item.getRunCommand(), (item.getIsPool() ? "takevm" : "run") + "_button_" + itemID);
shutdownButton = new ActionButton("actions/stop.png", item.getIsPool() ? item.getReturnVmCommand() : item.getShutdownCommand(), (item.getIsPool() ? "returnvm" : "shutdown") + "_button_" + itemID);
suspendButton = new ActionButton("actions/pause.png", item.getPauseCommand(), "pause_button_" + itemID);
powerButton = new ActionButton("actions/power.png", item.getStopCommand(), "stop_button_" + itemID);
actionButtonsLayout.setMembers(runButton, shutdownButton, suspendButton, powerButton);
HLayout nameAndDescriptionLayout = new HLayout(5);
nameAndDescriptionLayout.setMembers(nameLabel, descriptionLabel);
nameAndDescriptionLayout.setWidth(400);
nameAndDescriptionLayout.setOverflow(Overflow.HIDDEN);
addMember(vmImage);
addMember(statusImage);
addMember(nameAndDescriptionLayout);
addMember(actionButtonsLayout);
consoleButton = new ImgButton();
consoleButton.setSrc("actions/console.png");
consoleButton.setWidth(80);
consoleButton.setHeight(27);
consoleButton.setLayoutAlign(VerticalAlignment.CENTER);
consoleButton.setShowDown(false);
consoleButton.addClickHandler(new ConsoleClickHandler());
consoleButton.setHoverOpacity(75);
consoleButton.setHoverStyle("gridToolTipStyle");
consoleButton.setHoverWidth(1);
consoleButton.setHoverWrap(false);
consoleButton.setHoverDelay(500);
consoleButton.setTooltip("Open Console");
consoleButton.setID("openconsole_button_" + itemID);
consoleEditButton = new ImgButton();
consoleEditButton.setSrc("actions/console_edit.png");
consoleEditButton.setWidth(15);
consoleEditButton.setHeight(27);
consoleEditButton.setLayoutAlign(VerticalAlignment.CENTER);
consoleEditButton.setShowDown(false);
consoleEditButton.addClickHandler(new ConsoleEditClickHandler());
consoleEditButton.setHoverOpacity(75);
consoleEditButton.setHoverStyle("gridToolTipStyle");
consoleEditButton.setHoverWidth(1);
consoleEditButton.setHoverWrap(false);
consoleEditButton.setHoverDelay(500);
consoleEditButton.setTooltip("Edit Console Options");
consoleEditButton.setID("editconsole_button_" + itemID);
ConsoleUtils.determineDefaultProtocol(this, item);
if (item.getIsPool()) {
consoleButton.setShowHover(false);
consoleEditButton.setShowHover(false);
consoleButton.setDisabled(true);
consoleEditButton.setDisabled(true);
}
addMember(consoleButton);
addMember(consoleEditButton);
updateValues(item);
addMouseOverHandler(new MouseOverHandler() {
@Override
public void onMouseOver(MouseOverEvent event) {
if (!isSelected)
setStyleName("mainGrid-rowOver");
}
});
addMouseOutHandler(new MouseOutHandler() {
@Override
public void onMouseOut(MouseOutEvent event) {
updateRowColor();
}
});
}
@Override
public void updateValues(UserPortalItemModel item) {
currentItem = item;
statusImage.setTooltip(statusTranslator.get(item.getStatus()));
setImage(item);
setName(item.getName());
setDescription(item.getDescription());
setStatus(item.getStatus());
updateRowColor();
setVmImageMaskVisibility(item);
updateActionsAvailability(item);
updateConsoleOptions(item);
}
public void updateActionsAvailability(UserPortalItemModel item) {
runButton.setDisabled(item.getIsPool() ? !item.getTakeVmCommand().getIsExecutionAllowed() : !item.getRunCommand().getIsExecutionAllowed());
shutdownButton.setDisabled(!item.getShutdownCommand().getIsExecutionAllowed());
suspendButton.setDisabled(!item.getPauseCommand().getIsExecutionAllowed());
powerButton.setDisabled(!item.getStopCommand().getIsExecutionAllowed());
}
public void updateConsoleOptions(UserPortalItemModel item) {
if (selectedProtocol != null) {
switch(selectedProtocol) {
case SPICE:
if (item.getDefaultConsole().getConnectCommand().getIsAvailable() && item.getDefaultConsole().getConnectCommand().getIsExecutionAllowed()) {
enableConsoleButtons();
}
else {
disableConsoleButtons();
}
break;
case RDP:
if (item.getAdditionalConsole().getConnectCommand().getIsAvailable() && item.getAdditionalConsole().getConnectCommand().getIsExecutionAllowed()) {
enableConsoleButtons();
}
else {
disableConsoleButtons();
}
break;
}
}
else {
disableConsoleButtons();
}
}
public void setVmImageMaskVisibility(UserPortalItemModel item) {
if (item.IsVmUp()) {
vmImageDisabledMask.hide();
}
else {
vmImageDisabledMask.show();
}
}
public void updateRowColor() {
if (isSelected) {
setStyleName("mainGrid-rowSelected");
}
else {
setStyleName(currentItem.IsVmUp() ? "mainGrid-rowRunning" : "mainGrid-row");
}
}
public void setImage(UserPortalItemModel item) {
String imageName = "os/large/" + item.getOsType().name() + ".png";
if (!vmImage.getSrc().equals(imageName)) {
vmImage.setTooltip(osTranslator.get(item.getOsType()));
vmImage.setSrc(imageName);
}
}
public void setName(String name) {
nameLabel.setContents(name);
}
public void setDescription(String description) {
if ((description == null || description.isEmpty())) {
descriptionLabel.setContents(null, true);
return;
}
String descriptionString = '(' + description + ')';
descriptionLabel.setContents(descriptionString, true);
}
public void setStatus(VMStatus status) {
StatusIcon statusIcon = STATUS_ICON_MAP.get(status);
String statusImageName = "status/" + statusIcon + ".png";
if (!statusImage.getSrc().equals(statusImageName)) {
statusImage.setSrc(statusImageName);
}
}
@Override
public void select() {
isSelected = true;
setStyleName("mainGrid-rowSelected");
focus();
}
@Override
public void deselect() {
isSelected = false;
updateRowColor();
}
@Override
public void setItemId(Object id) {
entityGuid = id;
}
@Override
public Object getItemId() {
return entityGuid;
}
enum StatusIcon {
PAUSED, RUNNING, STOPPED, WAITING, QUESTIONMARK, STOPPING, STARTING;
}
// A static HashMap that serves as a conversion table between the VM status
// and the corresponding icon
final static Map<VMStatus, StatusIcon> STATUS_ICON_MAP = new HashMap<VMStatus, StatusIcon>() {
private static final long serialVersionUID = -1L;
{
put(VMStatus.Up, StatusIcon.RUNNING);
put(VMStatus.WaitForLaunch, StatusIcon.WAITING);
put(VMStatus.PoweringUp, StatusIcon.STARTING);
put(VMStatus.Paused, StatusIcon.PAUSED);
put(VMStatus.Suspended, StatusIcon.PAUSED);
put(VMStatus.ImageLocked, StatusIcon.WAITING);
put(VMStatus.Unknown, StatusIcon.QUESTIONMARK);
put(VMStatus.MigratingFrom, StatusIcon.WAITING);
put(VMStatus.MigratingTo, StatusIcon.WAITING);
put(VMStatus.RebootInProgress, StatusIcon.STARTING);
put(VMStatus.Unassigned, StatusIcon.STOPPED);
put(VMStatus.ImageIllegal, StatusIcon.STOPPED);
put(VMStatus.Down, StatusIcon.STOPPED);
put(VMStatus.SavingState, StatusIcon.WAITING);
put(VMStatus.RestoringState, StatusIcon.STARTING);
put(VMStatus.PoweringDown, StatusIcon.STOPPING);
put(VMStatus.PoweredDown, StatusIcon.STOPPED);
put(VMStatus.NotResponding, StatusIcon.STOPPED);
}
};
class ActionButton extends ImgButton {
private String commandName;
public ActionButton(String imgName, final UICommand command, String buttonID) {
super();
setSize(ACTION_BUTTON_SIZE);
setSrc(imgName);
setShowRollOver(false);
setTooltip(command.getName());
setHoverOpacity(75);
setHoverStyle("gridToolTipStyle");
setHoverWidth(1);
setHoverWrap(false);
setHoverDelay(500);
setID(buttonID);
commandName = command.getName();
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
GWT.log("Executing " + commandName + " command");
for (UICommand uiCommand : currentItem.getCommands()) {
if (uiCommand.getName().equals(commandName)) {
uiCommand.Execute();
break;
}
}
parent.getMainGrid().gridActionPerformed();
}
});
}
@Override
public void setDisabled(boolean disabled) {
if (getDisabled() != disabled)
super.setDisabled(disabled);
}
}
private static ErrorTranslator consoleErrorsTranslator =
new ErrorTranslator((ConsoleErrors)GWT.create(ConsoleErrors.class));
class ConsoleEditClickHandler implements ClickHandler {
@Override
public void onClick(ClickEvent event) {
ConsoleEditPanel editPanel = new ConsoleEditPanel(currentItem, mainGridItem);
editPanel.draw();
}
}
class ConsoleClickHandler implements ClickHandler {
@Override
public void onClick(ClickEvent event) {
boolean shouldConnectSpice = selectedProtocol.equals(Protocol.SPICE) &&
(currentItem.getDefaultConsole() instanceof SpiceConsoleModel);
boolean shouldConnectRDP = selectedProtocol.equals(Protocol.RDP) ||
(currentItem.getHasAdditionalConsole() && currentItem.getAdditionalConsole().getConnectCommand().getIsAvailable());
if (shouldConnectSpice) {
if (!SpiceInterfaceImpl.isBrowserSupported()) {
showConnectErrorMessage(Protocol.SPICE);
} else {
connectConsole(currentItem.getDefaultConsole());
}
} else if (shouldConnectRDP) {
if (!RDPInterfaceImpl.isBrowserSupported()) {
showConnectErrorMessage(Protocol.RDP);
} else {
connectConsole(currentItem.getAdditionalConsole());
}
}
parent.getMainGrid().gridActionPerformed();
}
public void showConnectErrorMessage(Protocol protocol) {
Message message = new Message("Error Connecting to " + currentItem.getName(), "This browser does not support " + protocol.name() + " protocol");
MessageDialog errorDialog = new MessageDialog("Not Supported", message, Severity.ERROR);
errorDialog.draw();
}
public void showDisconnectErrorMessage(String error) {
Message message = new Message("Virtual Machine connection error: " + error);
MessageDialog errorDialog = new MessageDialog("Console Disconnected", message, Severity.ERROR);
errorDialog.draw();
}
public void connectConsole(final ConsoleModel consoleModel) {
consoleModel.getErrorEvent().addListener(new IEventListener() {
@Override
public void eventRaised(Event ev, Object sender, EventArgs args) {
// Get error code
ErrorCodeEventArgs errorCodeEventArgs = (ErrorCodeEventArgs)args;
int errorCode = errorCodeEventArgs.getErrorCode();
// Translate error using translator and show error dialog
showDisconnectErrorMessage(consoleErrorsTranslator.TranslateErrorTextSingle("E" + errorCode));
consoleModel.getErrorEvent().removeListener(this);
}
});
consoleModel.getConnectCommand().Execute();
}
}
private void disableConsoleButtons() {
consoleButton.setDisabled(true);
consoleEditButton.setDisabled(true);
consoleEditButton.setShowHover(false);
if (getProtocolMessage() == null) {
consoleButton.setShowHover(false);
}
else {
consoleButton.setShowHover(true);
consoleButton.setTooltip(getProtocolMessage());
}
}
private void enableConsoleButtons() {
consoleButton.setShowHover(true);
consoleEditButton.setShowHover(true);
consoleButton.setDisabled(false);
consoleEditButton.setDisabled(false);
}
@Override
public void setProtocol(Protocol protocol) {
this.selectedProtocol = protocol;
}
@Override
public Protocol getProtocol() {
return selectedProtocol;
}
@Override
public void setProtocolMessage(String message) {
this.protocolMessage = message;
}
@Override
public String getProtocolMessage() {
return protocolMessage;
}
}