package org.ovirt.engine.ui.common.view.popup.numa;
import java.util.List;
import org.ovirt.engine.core.common.businessentities.VdsNumaNode;
import org.ovirt.engine.ui.common.CommonApplicationConstants;
import org.ovirt.engine.ui.common.CommonApplicationMessages;
import org.ovirt.engine.ui.common.CommonApplicationResources;
import org.ovirt.engine.ui.common.gin.AssetProvider;
import org.ovirt.engine.ui.common.presenter.popup.numa.NumaVmSelectedEvent;
import org.ovirt.engine.ui.common.presenter.popup.numa.UpdatedVnumaEvent;
import org.ovirt.engine.ui.common.widget.MenuBar;
import org.ovirt.engine.ui.common.widget.PopupPanel;
import org.ovirt.engine.ui.uicommonweb.models.hosts.numa.VNodeModel;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ContextMenuEvent;
import com.google.gwt.event.dom.client.DragStartEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
public class DraggableVirtualNumaPanel extends Composite implements HasHandlers {
interface WidgetUiBinder extends UiBinder<Widget, DraggableVirtualNumaPanel> {
WidgetUiBinder uiBinder = GWT.create(WidgetUiBinder.class);
}
interface Style extends CssResource {
String panelOver();
}
static final PopupPanel menuPopup = new PopupPanel(true);
@UiField
FocusPanel container;
@UiField(provided=true)
VirtualNumaPanel numaPanel;
@UiField
Image dragHandle;
@UiField
Style style;
private VNodeModel nodeModel;
private final EventBus eventBus;
private HandlerRegistration contextMenuHandlerRegistration;
private MenuBar menuBar;
private boolean dragEnabled;
private static final CommonApplicationResources resources = AssetProvider.getResources();
private static final CommonApplicationConstants constants = AssetProvider.getConstants();
private static final CommonApplicationMessages messages = AssetProvider.getMessages();
@Inject
public DraggableVirtualNumaPanel(EventBus gwtEventBus, VirtualNumaPanel virtualNumaPanel) {
numaPanel = virtualNumaPanel;
initWidget(WidgetUiBinder.uiBinder.createAndBindUi(this));
initializeResouceIcons();
this.eventBus = gwtEventBus;
enableDrag(true);
}
@Override
public void onLoad() {
super.onLoad();
if (!dragEnabled) {
return;
}
contextMenuHandlerRegistration = numaPanel.addDomHandler(event -> {
NativeEvent nativeEvent = event.getNativeEvent();
showContextMenu(nativeEvent.getClientX(), nativeEvent.getClientY());
event.stopPropagation();
event.preventDefault();
}, ContextMenuEvent.getType());
}
@Override
public void onUnload() {
super.onUnload();
if (!dragEnabled) {
return;
}
contextMenuHandlerRegistration.removeHandler();
}
private void initializeResouceIcons() {
numaPanel.setPinnedPartialVNumaIcon(resources.pinnedPartialVNumaIcon());
numaPanel.setPinnedVNumaIcon(resources.pinnedVNumaIcon());
numaPanel.setPartialVNumaIcon(resources.partialVNumaIcon());
numaPanel.setvNumaIcon(resources.vNumaIcon());
}
@UiHandler("container")
void handleMouseOver(MouseOverEvent event) {
if (!dragEnabled) {
return;
}
container.addStyleName(style.panelOver());
dragHandle.setVisible(true);
}
@UiHandler("container")
void handleMouseOut(MouseOutEvent event) {
if (!dragEnabled) {
return;
}
container.removeStyleName(style.panelOver());
dragHandle.setVisible(false);
}
@UiHandler("container")
void onDragStart(DragStartEvent event) {
if (!dragEnabled) {
return;
}
event.setData("VM_GID", nodeModel.getVm().getId().toString()); //$NON-NLS-1$
event.setData("PINNED", String.valueOf(nodeModel.isPinned())); //$NON-NLS-1$
event.setData("INDEX", String.valueOf(nodeModel.getIndex())); //$NON-NLS-1$
// show a ghost of the widget under cursor.
NativeEvent nativeEvent = event.getNativeEvent();
int x = nativeEvent.getClientX() - getAbsoluteLeft();
int y = nativeEvent.getClientY() - getAbsoluteTop();
event.getDataTransfer().setDragImage(getElement(), x, y);
}
@UiHandler("container")
void onFocus(FocusEvent event) {
NumaVmSelectedEvent.fire(this, this.nodeModel);
}
protected void showContextMenu(int clientX, int clientY) {
menuPopup.setWidget(menuBar);
menuPopup.setPopupPosition(clientX, clientY);
menuPopup.show();
}
/**
* Dragging is enabled by default, if you want to alter that behavior, call this method with false.
*
* @param dragEnabled
* Enabled or disable dragging of this panel.
*/
public void enableDrag(boolean dragEnabled) {
this.dragEnabled = dragEnabled;
if (dragEnabled) {
getElement().setDraggable(Element.DRAGGABLE_TRUE);
} else {
getElement().setDraggable(Element.DRAGGABLE_FALSE);
}
}
@Override
public void setStyleName(String className) {
container.setStyleName(className);
}
public void setModel(VNodeModel nodeModel, List<VdsNumaNode> numaNodeList) {
numaPanel.setModel(nodeModel);
this.nodeModel = nodeModel;
if (nodeModel.isLocked()) {
enableDrag(false);
} else {
createMenu(numaNodeList, nodeModel.getIndex());
}
}
private void createMenu(final List<VdsNumaNode> numaNodeList, int indexToSkip) {
menuBar = new MenuBar(true);
for (final VdsNumaNode numaNode : numaNodeList) {
final int nodeIndex = numaNode.getIndex();
menuBar.addItem(messages.numaNode(nodeIndex), () -> {
UpdatedVnumaEvent.fire(DraggableVirtualNumaPanel.this, nodeModel.getVm().getId(),
true, nodeModel.getIndex(), nodeIndex);
menuPopup.hide();
});
}
if (nodeModel.isPinned()) {
menuBar.addSeparator();
menuBar.addItem(constants.unPinNode(), () -> {
UpdatedVnumaEvent.fire(DraggableVirtualNumaPanel.this, nodeModel.getVm().getId(),
false, nodeModel.getIndex(), -1);
menuPopup.hide();
});
}
}
@Override
public void fireEvent(GwtEvent<?> event) {
eventBus.fireEvent(event);
}
}