com.jitlogic.zico.client.views.hosts.HostListPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.jitlogic.zico.client.views.hosts.HostListPanel.java

Source

/**
 * Copyright 2012-2015 Rafal Lewczuk <rafal.lewczuk@jitlogic.com>
 * <p/>
 * This is free software. You can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * <p/>
 * This software is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * <p/>
 * You should have received a copy of the GNU General Public License
 * along with this software. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jitlogic.zico.client.views.hosts;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.ValueUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
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.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy;
import com.google.gwt.user.cellview.client.IdentityColumn;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.inject.Inject;
import com.jitlogic.zico.client.api.HostService;
import com.jitlogic.zico.client.views.Shell;
import com.jitlogic.zico.client.resources.Resources;
import com.jitlogic.zico.client.inject.PanelFactory;
import com.jitlogic.zico.client.views.traces.TraceSearchPanel;
import com.jitlogic.zico.shared.data.HostInfo;
import com.jitlogic.zico.shared.data.HostListObject;
import com.jitlogic.zico.widgets.client.*;
import com.jitlogic.zico.widgets.client.MenuItem;
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.MethodCallback;

import javax.inject.Provider;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class HostListPanel extends Composite {
    interface HostListPanelUiBinder extends UiBinder<Widget, HostListPanel> {
    }

    private static HostListPanelUiBinder ourUiBinder = GWT.create(HostListPanelUiBinder.class);

    @UiField
    DockLayoutPanel panel;

    @UiField
    HorizontalPanel toolbar;

    @UiField(provided = true)
    Resources resources;

    @UiField
    ToolButton btnRefresh;

    @UiField
    ToolButton btnAddHost;

    @UiField
    ToolButton btnRemoveHost;

    @UiField
    ToolButton btnEditHost;

    @UiField
    ToolButton btnDisableHost;

    @UiField
    ToolButton btnEnableHost;

    @UiField
    ToolButton btnListTraces;

    @UiField
    ToolButton btnStatTraces;

    @UiField(provided = true)
    DataGrid<HostListObject> hostGrid;

    private Provider<Shell> shell;
    private PanelFactory panelFactory;

    private HostService hostService;

    private ListDataProvider<HostListObject> hostGridStore;
    private SingleSelectionModel<HostListObject> selectionModel;

    private Map<String, HostGroup> hostGroups = new TreeMap<String, HostGroup>();

    private MenuItem mnuRefresh, mnuAddHost, mnuRemoveHost, mnuEditHost, mnuListTraces, mnuDisableHost,
            mnuEnableHost, mnuStatTraces;

    private boolean selectionDependentControlsEnabled = true;

    private boolean adminMode = false;
    private PopupMenu contextMenu;

    private MessageDisplay md;

    private static final String MDS = "HostListPanel";

    @Inject
    public HostListPanel(Provider<Shell> shell, PanelFactory panelFactory, HostService hostService,
            MessageDisplay md) {

        this.shell = shell;
        this.panelFactory = panelFactory;
        this.hostService = hostService;
        this.md = md;
        this.resources = Resources.INSTANCE;

        createHostGrid();

        ourUiBinder.createAndBindUi(this);

        createContextMenu();

        enableSelectionDependentControls(null);

        initWidget(panel);

        refresh(null);
    }

    public void setAdminMode(boolean adminMode) {
        this.adminMode = adminMode;
        enableSelectionDependentControls(null);
    }

    private void enableSelectionDependentControls(HostListObject hostInfo) {
        boolean enabled = hostInfo != null;
        boolean hostDisabled = hostInfo != null && !hostInfo.isEnabled();
        if (selectionDependentControlsEnabled != enabled) {
            btnRemoveHost.setEnabled(enabled && adminMode);
            btnEditHost.setEnabled(enabled && adminMode);
            btnListTraces.setEnabled(enabled);
            btnStatTraces.setEnabled(enabled);
            mnuRemoveHost.setEnabled(enabled && adminMode);
            mnuEditHost.setEnabled(enabled && adminMode);
            mnuListTraces.setEnabled(enabled);
            mnuStatTraces.setEnabled(enabled);
            selectionDependentControlsEnabled = enabled;
        }

        btnDisableHost.setEnabled(enabled && !hostDisabled && adminMode);
        btnEnableHost.setEnabled(hostDisabled && adminMode);
        mnuDisableHost.setEnabled(enabled && !hostDisabled && adminMode);
        mnuEnableHost.setEnabled(hostDisabled && adminMode);

        btnAddHost.setEnabled(adminMode);
        mnuAddHost.setEnabled(adminMode);
    }

    private static final ProvidesKey<HostListObject> KEY_PROVIDER = new ProvidesKey<HostListObject>() {
        @Override
        public Object getKey(HostListObject item) {
            return item.getName();
        }
    };

    private static final String PLUS_HTML = AbstractImagePrototype.create(Resources.INSTANCE.treePlusSlimIcon())
            .getHTML();
    private static final String MINUS_HTML = AbstractImagePrototype.create(Resources.INSTANCE.treeMinusSlimIcon())
            .getHTML();

    private final Cell<HostListObject> EXPAND_CELL = new AbstractCell<HostListObject>("click") {
        @Override
        public void render(Context context, HostListObject v, SafeHtmlBuilder sb) {
            if (v instanceof HostGroup) {
                HostGroup hg = (HostGroup) v;
                sb.appendHtmlConstant("<span style=\"cursor: pointer;\">");
                sb.appendHtmlConstant(hg.isExpanded() ? MINUS_HTML : PLUS_HTML);
                sb.appendHtmlConstant("</span>");
            } else {
                sb.appendHtmlConstant("<div/>");
            }
        }

        @Override
        public void onBrowserEvent(Context context, Element parent, HostListObject v, NativeEvent event,
                ValueUpdater<HostListObject> valueUpdater) {
            super.onBrowserEvent(context, parent, v, event, valueUpdater);
            EventTarget eventTarget = event.getEventTarget();
            if (v instanceof HostGroup && Element.is(eventTarget)) {
                Element target = eventTarget.cast();
                if ("IMG".equalsIgnoreCase(target.getTagName())) {
                    ((HostGroup) v).toggleExpanded();
                    redrawHostList();
                }
            }
        }
    };

    private static final Cell<HostListObject> NAME_CELL = new AbstractCell<HostListObject>() {
        @Override
        public void render(Context context, HostListObject host, SafeHtmlBuilder sb) {
            if (host instanceof HostInfo) {
                String color = (host.isEnabled()) ? "black" : "gray";
                sb.appendHtmlConstant("<span style=\"color: " + color + ";\">");
                sb.append(SafeHtmlUtils.fromString(host.getName()));
                sb.appendHtmlConstant("</span>");
            } else {
                sb.appendHtmlConstant("<span style=\"font-weight: bold;\">");
                sb.append(SafeHtmlUtils.fromString(host.getName()));
                sb.appendHtmlConstant("</span>");
            }
        }
    };

    private static final Cell<HostListObject> ADDRESS_CELL = new AbstractCell<HostListObject>() {
        @Override
        public void render(Context context, HostListObject host, SafeHtmlBuilder sb) {
            String color = (host.isEnabled()) ? "black" : "gray";
            sb.appendHtmlConstant("<span style=\"color: " + color + ";\">");
            sb.append(SafeHtmlUtils.fromString(host.getAddr()));
            sb.appendHtmlConstant("</span>");
        }
    };

    private void createHostGrid() {

        hostGrid = new DataGrid<HostListObject>(1024 * 1024, ZicoDataGridResources.INSTANCE, KEY_PROVIDER);
        selectionModel = new SingleSelectionModel<HostListObject>(KEY_PROVIDER);
        hostGrid.setSelectionModel(selectionModel);

        Column<HostListObject, HostListObject> colExpand = new IdentityColumn<HostListObject>(EXPAND_CELL);
        hostGrid.addColumn(colExpand, new ResizableHeader<HostListObject>("#", hostGrid, colExpand));
        hostGrid.setColumnWidth(colExpand, 36, Style.Unit.PX);

        Column<HostListObject, HostListObject> colName = new IdentityColumn<HostListObject>(NAME_CELL);
        hostGrid.addColumn(colName, new ResizableHeader<HostListObject>("Name", hostGrid, colName));
        hostGrid.setColumnWidth(colName, 140, Style.Unit.PX);

        Column<HostListObject, HostListObject> colAddr = new IdentityColumn<HostListObject>(ADDRESS_CELL);
        hostGrid.addColumn(colAddr, "Address");
        hostGrid.setColumnWidth(colAddr, 60, Style.Unit.PCT);

        hostGrid.setSkipRowHoverStyleUpdate(true);
        hostGrid.setSkipRowHoverFloatElementCheck(true);
        hostGrid.setSkipRowHoverCheck(true);
        hostGrid.setKeyboardSelectionPolicy(HasKeyboardSelectionPolicy.KeyboardSelectionPolicy.DISABLED);

        hostGridStore = new ListDataProvider<HostListObject>();
        hostGridStore.addDataDisplay(hostGrid);

        hostGrid.addCellPreviewHandler(new CellPreviewEvent.Handler<HostListObject>() {
            @Override
            public void onCellPreview(CellPreviewEvent<HostListObject> event) {
                NativeEvent nev = event.getNativeEvent();
                String eventType = nev.getType();
                if ((BrowserEvents.KEYDOWN.equals(eventType) && nev.getKeyCode() == KeyCodes.KEY_ENTER)
                        || BrowserEvents.DBLCLICK.equals(nev.getType())) {
                    selectionModel.setSelected(event.getValue(), true);

                    enableSelectionDependentControls(event.getValue());

                    if (event.getValue() instanceof HostInfo) {
                        listTraces(null);
                    } else {
                        HostGroup hg = (HostGroup) event.getValue();
                        hg.toggleExpanded();
                        redrawHostList();
                    }
                }
                if (BrowserEvents.CONTEXTMENU.equals(eventType)) {
                    selectionModel.setSelected(event.getValue(), true);
                    if (event.getValue() != null) {
                        contextMenu.setPopupPosition(event.getNativeEvent().getClientX(),
                                event.getNativeEvent().getClientY());
                        contextMenu.show();
                    }
                }

                // TODO update toolbar icons and context menu on element selection
            }
        });

        hostGrid.addDomHandler(new DoubleClickHandler() {
            @Override
            public void onDoubleClick(DoubleClickEvent event) {
                event.preventDefault();
            }
        }, DoubleClickEvent.getType());

        hostGrid.addDomHandler(new ContextMenuHandler() {
            @Override
            public void onContextMenu(ContextMenuEvent event) {
                event.preventDefault();
            }
        }, ContextMenuEvent.getType());

        selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
            @Override
            public void onSelectionChange(SelectionChangeEvent event) {
                enableSelectionDependentControls(selectionModel.getSelectedObject());
            }
        });
    }

    private void rebuildHostGroups(List<HostInfo> hlist) {
        for (Map.Entry<String, HostGroup> e : hostGroups.entrySet()) {
            e.getValue().clear();
        }

        for (HostInfo host : hlist) {
            String groupName = host.getGroup().length() > 0 ? host.getGroup() : "(default)";
            if (!hostGroups.containsKey(groupName)) {
                HostGroup hg = new HostGroup(groupName);
                if (host.getGroup().length() == 0) {
                    hg.toggleExpanded();
                }
                hostGroups.put(groupName, hg);
            }
            hostGroups.get(groupName).addHost(host);
        }

        selectionModel.setSelected(selectionModel.getSelectedObject(), false);
        enableSelectionDependentControls(null);

    }

    private void redrawHostList() {
        List<HostListObject> hl = hostGridStore.getList();

        hl.clear();

        for (Map.Entry<String, HostGroup> e : hostGroups.entrySet()) {
            HostGroup hg = e.getValue();

            if (hg.size() > 0) {
                hl.add(hg);
                if (hg.isExpanded()) {
                    hl.addAll(hg.getHosts());
                }
            }
        }
    }

    private void createContextMenu() {
        contextMenu = new PopupMenu();

        mnuRefresh = new MenuItem("Refresh", Resources.INSTANCE.refreshIcon(), new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                refresh(null);
            }
        });
        contextMenu.addItem(mnuRefresh);

        contextMenu.addSeparator();

        mnuAddHost = new MenuItem("New host", Resources.INSTANCE.addIcon(), new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                addHost(null);
            }
        });
        contextMenu.addItem(mnuAddHost);

        mnuRemoveHost = new MenuItem("Remove Host", Resources.INSTANCE.removeIcon(),
                new Scheduler.ScheduledCommand() {
                    @Override
                    public void execute() {
                        removeHost(null);
                    }
                });
        contextMenu.addItem(mnuRemoveHost);

        mnuEditHost = new MenuItem("Edit host", Resources.INSTANCE.editIcon(), new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                editHost(null);
            }
        });
        contextMenu.addItem(mnuEditHost);

        contextMenu.addSeparator();

        mnuDisableHost = new MenuItem("Disable Host", Resources.INSTANCE.disableIcon(),
                new Scheduler.ScheduledCommand() {
                    @Override
                    public void execute() {
                        toggleHost(false);
                    }
                });
        contextMenu.addItem(mnuDisableHost);

        mnuEnableHost = new MenuItem("Enable Host", Resources.INSTANCE.enableIcon(),
                new Scheduler.ScheduledCommand() {
                    @Override
                    public void execute() {
                        toggleHost(true);
                    }
                });
        contextMenu.addItem(mnuEnableHost);

        contextMenu.addSeparator();

        mnuListTraces = new MenuItem("List traces", Resources.INSTANCE.listColumnsIcon(),
                new Scheduler.ScheduledCommand() {
                    @Override
                    public void execute() {
                        listTraces(null);
                    }
                });
        contextMenu.addItem(mnuListTraces);

        mnuStatTraces = new MenuItem("Pivot view", Resources.INSTANCE.filterIcon(),
                new Scheduler.ScheduledCommand() {
                    @Override
                    public void execute() {
                        statTraces(null);
                    }
                });
        contextMenu.addItem(mnuStatTraces);
    }

    private void toggleHost(boolean enabled) {
        HostListObject info = selectionModel.getSelectedObject();
        if (info instanceof HostInfo) {
            md.info(MDS, "Disabling host");
            ((HostInfo) info).setEnabled(enabled);
            hostService.update(info.getName(), (HostInfo) info, new MethodCallback<Void>() {
                @Override
                public void onFailure(Method method, Throwable e) {
                    md.error(MDS, "Error enabling/disabling host", e);
                }

                @Override
                public void onSuccess(Method method, Void response) {
                    refresh(null);
                    md.clear(MDS);
                }
            });
        }
    }

    @UiHandler("btnRefresh")
    void refresh(ClickEvent e) {
        hostGridStore.getList().clear();
        md.info(MDS, "Loading host list ...");
        hostService.list(new MethodCallback<List<HostInfo>>() {
            @Override
            public void onFailure(Method method, Throwable e) {
                md.error(MDS, "Error loading host list.", e);
            }

            @Override
            public void onSuccess(Method method, List<HostInfo> response) {
                md.clear(MDS);
                rebuildHostGroups(response);
                redrawHostList();
            }
        });
    }

    @UiHandler("btnAddHost")
    void addHost(ClickEvent e) {
        new HostEditDialog(hostService, this, null, md).getWindow().show();
    }

    @UiHandler("btnRemoveHost")
    void removeHost(ClickEvent e) {
        // TODO "Are you sure" message box
        final HostListObject hi = selectionModel.getSelectedObject();
        if (hi instanceof HostInfo) {

            ConfirmDialog dialog = new ConfirmDialog("Removing host", "Remove host " + hi.getName() + " ?")
                    .withBtn("Yes", new ClickHandler() {
                        @Override
                        public void onClick(ClickEvent event) {
                            hostGridStore.getList().remove(hi);
                            hostService.delete(hi.getName(), new MethodCallback<Void>() {
                                @Override
                                public void onFailure(Method method, Throwable exception) {

                                }

                                @Override
                                public void onSuccess(Method method, Void response) {

                                }
                            });
                        }
                    }).withBtn("No");
            dialog.show();
        }
    }

    @UiHandler("btnEditHost")
    void editHost(ClickEvent e) {
        HostListObject hostInfo = selectionModel.getSelectedObject();
        if (hostInfo instanceof HostInfo) {
            new HostEditDialog(hostService, this, (HostInfo) hostInfo, md).getWindow().show();
        }
    }

    @UiHandler("btnDisableHost")
    void disableHost(ClickEvent e) {
        toggleHost(false);
    }

    @UiHandler("btnEnableHost")
    void enableHost(ClickEvent e) {
        toggleHost(true);
    }

    @UiHandler("btnListTraces")
    void listTraces(ClickEvent e) {
        HostListObject hostInfo = selectionModel.getSelectedObject();
        GWT.log("Selected host: " + hostInfo);

        if (hostInfo instanceof HostInfo && 0 == (((HostInfo) hostInfo).getFlags() & HostInfo.DISABLED)) {
            TraceSearchPanel searchPanel = panelFactory.traceSearchPanel((HostInfo) hostInfo, null);
            shell.get().addView(searchPanel, hostInfo.getName() + ": traces");
            searchPanel.refresh();
        }
    }

    @UiHandler("btnStatTraces")
    void statTraces(ClickEvent e) {
        HostListObject hostInfo = selectionModel.getSelectedObject();
        GWT.log("Selected host: " + hostInfo);

        if (hostInfo instanceof HostInfo && 0 == (((HostInfo) hostInfo).getFlags() & HostInfo.DISABLED)) {
            shell.get().addView(panelFactory.traceStatsPanel((HostInfo) hostInfo), hostInfo.getName() + ": traces");
        }
    }
}