eu.stratosphere.addons.visualization.swt.SWTFailureEventTable.java Source code

Java tutorial

Introduction

Here is the source code for eu.stratosphere.addons.visualization.swt.SWTFailureEventTable.java

Source

/***********************************************************************************************************************
 * Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
 *
 * 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 eu.stratosphere.addons.visualization.swt;

import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import eu.stratosphere.util.StringUtils;

public final class SWTFailureEventTable extends Composite {

    private static final Log LOG = LogFactory.getLog(SWTFailureEventTable.class);

    private static final int DEFAULT_ICON_SIZE = 16;

    private static final int ICON_COLUMN_WIDTH = 20;

    private static final int TEXT_COLUMN_WIDTH = 200;

    private static Image TASK_ICON = null;

    private static Image INSTANCE_ICON = null;

    private final Table failureEventTable;

    private final Set<String> nameSuggestions;

    private JobFailurePattern selectedFailurePattern = null;

    public SWTFailureEventTable(final Composite parent, final int style, final Set<String> nameSuggestions) {
        super(parent, SWT.NONE);

        // Load images
        synchronized (SWTFailureEventTable.class) {

            if (TASK_ICON == null) {
                TASK_ICON = loadIcon("/eu/stratosphere/nephele/visualization/swt/taskicon.png");
            }

            if (INSTANCE_ICON == null) {
                INSTANCE_ICON = loadIcon("/eu/stratosphere/nephele/visualization/swt/nodeicon.png");
            }
        }

        this.nameSuggestions = nameSuggestions;

        setLayout(new FillLayout());

        this.failureEventTable = new Table(this, style);
        this.failureEventTable.setHeaderVisible(true);
        this.failureEventTable.setLinesVisible(true);

        final TableColumn iconColumn = new TableColumn(this.failureEventTable, SWT.NONE);
        final TableColumn nameColumn = new TableColumn(this.failureEventTable, SWT.NONE);
        nameColumn.setText("Name");
        final TableColumn intervalColumn = new TableColumn(this.failureEventTable, SWT.NONE);
        intervalColumn.setText("Interval");

        for (int i = 0; i < this.failureEventTable.getColumnCount(); ++i) {
            if (i == 0) {
                this.failureEventTable.getColumn(i).setWidth(ICON_COLUMN_WIDTH);
            } else {
                this.failureEventTable.getColumn(i).setWidth(TEXT_COLUMN_WIDTH);
            }
        }

        // Implement listener to add and update events
        this.failureEventTable.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseDoubleClick(final MouseEvent arg0) {

                final TableItem ti = failureEventTable.getItem(new Point(arg0.x, arg0.y));

                if (selectedFailurePattern == null) {
                    return;
                }

                addOrEditTableItem(ti);
            }
        });

        // Implement sorting of columns
        final Listener sortListener = new Listener() {

            @Override
            public void handleEvent(final Event arg0) {

                final TableColumn sortColumn = failureEventTable.getSortColumn();
                final TableColumn currentColumn = (TableColumn) arg0.widget;
                int dir = failureEventTable.getSortDirection();
                if (sortColumn == currentColumn) {
                    dir = (dir == SWT.UP) ? SWT.DOWN : SWT.UP;
                } else {
                    failureEventTable.setSortColumn(currentColumn);
                    dir = SWT.UP;
                }

                final int direction = dir;
                final AbstractFailureEvent[] failureEvents = new AbstractFailureEvent[failureEventTable
                        .getItemCount()];
                for (int i = 0; i < failureEventTable.getItemCount(); ++i) {
                    failureEvents[i] = (AbstractFailureEvent) failureEventTable.getItem(i).getData();
                }
                Arrays.sort(failureEvents, new Comparator<AbstractFailureEvent>() {

                    @Override
                    public int compare(final AbstractFailureEvent o1, AbstractFailureEvent o2) {

                        if (o1 == null) {
                            return -1;
                        }

                        if (o2 == null) {
                            return 1;
                        }

                        if (currentColumn == iconColumn) {

                            final int v1 = (o1 instanceof VertexFailureEvent) ? 0 : 1;
                            final int v2 = (o2 instanceof VertexFailureEvent) ? 0 : 1;
                            return (direction == SWT.UP) ? (v1 - v2) : (v2 - v1);

                        } else if (currentColumn == nameColumn) {

                            if (direction == SWT.UP) {
                                return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName());
                            } else {
                                return String.CASE_INSENSITIVE_ORDER.compare(o2.getName(), o1.getName());
                            }

                        } else {

                            if (direction == SWT.UP) {
                                return (o1.getInterval() - o2.getInterval());
                            } else {
                                return (o2.getInterval() - o1.getInterval());
                            }
                        }
                    }
                });

                failureEventTable.removeAll();
                for (int i = 0; i < failureEvents.length; ++i) {
                    updateTableItem(null, failureEvents[i]);
                }

                failureEventTable.setSortColumn(currentColumn);
                failureEventTable.setSortDirection(direction);
            }
        };

        iconColumn.addListener(SWT.Selection, sortListener);
        nameColumn.addListener(SWT.Selection, sortListener);
        intervalColumn.addListener(SWT.Selection, sortListener);

        // Implement keyboard commands
        this.failureEventTable.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(final KeyEvent arg0) {

                if (arg0.keyCode == SWT.DEL) {
                    removeSelectedTableItems();
                } else if (arg0.keyCode == SWT.CR) {
                    addOrEditSelectedTableItems();
                }
            }
        });

        // Set the menu
        this.failureEventTable.setMenu(createTableContextMenu());
    }

    private Image loadIcon(final String path) {

        final Display display = getDisplay();
        final InputStream in = getClass().getResourceAsStream(path);
        try {
            return new Image(display, in);
        } catch (Exception e) {
            LOG.warn(StringUtils.stringifyException(e));
        }

        final Image image = new Image(display, DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
        final GC gc = new GC(image);
        gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
        gc.fillRectangle(image.getBounds());
        gc.dispose();

        return image;
    }

    private void updateTableItem(TableItem ti, final AbstractFailureEvent event) {

        boolean newItemCreated = false;

        if (ti == null) {

            final int index = (failureEventTable.getItemCount() == 0) ? 0
                    : (this.failureEventTable.getItemCount() - 1);

            ti = new TableItem(this.failureEventTable, SWT.NONE, index);
            newItemCreated = true;
        }

        if (event != null) {
            if (event instanceof VertexFailureEvent) {
                ti.setImage(TASK_ICON);
            } else {
                ti.setImage(INSTANCE_ICON);
            }

            ti.setText(1, event.getName());
            ti.setText(2, Integer.toString(event.getInterval()));
        }

        // Add new blank item if the old one has been used to create the new event
        if (ti.getData() == null && !newItemCreated) {
            new TableItem(this.failureEventTable, SWT.NONE);
        }

        ti.setData(event);
    }

    private Menu createTableContextMenu() {

        final Menu tableContextMenu = new Menu(getShell());

        final MenuItem addItem = new MenuItem(tableContextMenu, SWT.PUSH);
        addItem.setText("Add...");
        addItem.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent arg0) {
                addOrEditSelectedTableItems();
            }

        });

        final MenuItem editItem = new MenuItem(tableContextMenu, SWT.PUSH);
        editItem.setText("Edit...");
        editItem.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent arg0) {
                addOrEditSelectedTableItems();
            }

        });

        final MenuItem removeItem = new MenuItem(tableContextMenu, SWT.PUSH);
        removeItem.setText("Remove...");
        removeItem.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent arg0) {
                removeSelectedTableItems();
            }
        });

        tableContextMenu.addMenuListener(new MenuAdapter() {

            @Override
            public void menuShown(final MenuEvent arg0) {

                TableItem[] selectedItems = failureEventTable.getSelection();
                if (selectedItems == null) {

                    return;
                }

                if (selectedItems.length == 0) {

                    editItem.setEnabled(false);
                    removeItem.setEnabled(false);

                    return;
                }

                if (selectedItems[0].getData() == null) {

                    editItem.setEnabled(false);
                    removeItem.setEnabled(false);

                    return;
                }

                editItem.setEnabled(true);
                removeItem.setEnabled(true);
            }
        });

        return tableContextMenu;
    }

    private void addOrEditSelectedTableItems() {

        final TableItem[] selectedItems = this.failureEventTable.getSelection();
        if (selectedItems == null) {
            return;
        }

        for (final TableItem selectedItem : selectedItems) {
            addOrEditTableItem(selectedItem);
        }
    }

    private void addOrEditTableItem(final TableItem ti) {

        AbstractFailureEvent oldEvent = null;
        if (ti != null) {
            oldEvent = (AbstractFailureEvent) ti.getData();
        }

        final SWTFailureEventEditor editor = new SWTFailureEventEditor(getShell(), nameSuggestions, oldEvent);

        final AbstractFailureEvent newEvent = editor.showDialog();
        if (newEvent == null) {
            return;
        }

        if (oldEvent != null) {
            selectedFailurePattern.removeEvent(oldEvent);
        }
        selectedFailurePattern.addEvent(newEvent);

        updateTableItem(ti, newEvent);

    }

    private void removeSelectedTableItems() {

        final TableItem[] selectedItems = this.failureEventTable.getSelection();
        if (selectedItems == null) {
            return;
        }

        for (final TableItem selectedItem : selectedItems) {
            removeTableItem(selectedItem);
        }
    }

    private void removeTableItem(final TableItem ti) {

        final AbstractFailureEvent event = (AbstractFailureEvent) ti.getData();
        if (event == null) {
            return;
        }

        final MessageBox messageBox = new MessageBox(getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
        messageBox.setText("Confirm removal");
        messageBox.setMessage("Do you really want to remove the event '" + event.getName() + "'");
        if (messageBox.open() == SWT.YES) {
            ti.dispose();
        }

        this.selectedFailurePattern.removeEvent(event);
    }

    public void showFailurePattern(final JobFailurePattern jobFailurePattern) {

        // Clear old content from event table
        this.failureEventTable.removeAll();

        if (jobFailurePattern == null) {
            this.failureEventTable.setEnabled(false);
            return;
        }

        this.failureEventTable.setEnabled(true);

        final Iterator<AbstractFailureEvent> it = jobFailurePattern.iterator();
        while (it.hasNext()) {

            final AbstractFailureEvent event = it.next();
            final TableItem ti = new TableItem(this.failureEventTable, SWT.NONE);
            ti.setData(event);
            updateTableItem(ti, event);
        }

        // Finally, add item to create new entry in both tables
        new TableItem(this.failureEventTable, SWT.NONE);

        this.selectedFailurePattern = jobFailurePattern;
    }
}