de.dentrassi.eclipse.rpm.editor.HeaderTable.java Source code

Java tutorial

Introduction

Here is the source code for de.dentrassi.eclipse.rpm.editor.HeaderTable.java

Source

/*******************************************************************************
 * Copyright (c) 2016 IBH SYSTEMS GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBH SYSTEMS GmbH - initial API and implementation
 *******************************************************************************/
package de.dentrassi.eclipse.rpm.editor;

import static java.util.Optional.empty;
import static java.util.Optional.of;

import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.jface.layout.AbstractColumnLayout;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreePathContentProvider;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.packagedrone.utils.rpm.Rpms;
import org.eclipse.packagedrone.utils.rpm.parse.HeaderValue;
import org.eclipse.packagedrone.utils.rpm.parse.InputHeader;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;

public class HeaderTable {
    private static class Entry implements Comparable<Entry> {

        private final int key;
        private final HeaderValue value;

        public Entry(final int key, final HeaderValue value) {
            this.key = key;
            this.value = value;
        }

        public int getKey() {
            return this.key;
        }

        public HeaderValue getValue() {
            return this.value;
        }

        @Override
        public int compareTo(final Entry other) {
            return Integer.compare(this.key, other.key);
        }
    }

    private final TreeViewer viewer;
    private final Composite wrapper;
    private Function<Integer, Object> tagNameProvider;

    public HeaderTable(final Composite parent, final Function<Integer, Object> tagNameProvider) {
        this.tagNameProvider = tagNameProvider;
        this.wrapper = new Composite(parent, SWT.NO_BACKGROUND);
        parent.setLayout(new FillLayout());

        this.viewer = new TreeViewer(this.wrapper, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);

        final TreeColumnLayout layout = new TreeColumnLayout();

        createColumn(layout, "Tag ID", 1, entry -> String.format("%d", entry.getKey()));
        createColumnCell(layout, "Tag Name", 2, (entry, cell) -> {
            makeTagName(entry).ifPresent(cell::setText);
        });

        createStyledColumn(layout, "Type", 1, entry -> makeType(entry));
        createColumn(layout, "Count", 1, entry -> String.format("%d", entry.getValue().getCount()));
        createColumn(layout, "Index", 1, entry -> String.format("%d", entry.getValue().getIndex()));
        createColumnCell(layout, "Value", 10, HeaderTable::updateCellValue);

        this.wrapper.setLayout(layout);
        this.viewer.getTree().setHeaderVisible(true);
        this.viewer.addDoubleClickListener(this::handleDoubleClick);

        final ITreePathContentProvider p = new ITreePathContentProvider() {

            @Override
            public boolean hasChildren(final TreePath path) {
                final Object[] children = getChildren(path);
                return children != null && children.length > 0;
            }

            @Override
            public TreePath[] getParents(final Object element) {
                return new TreePath[0];
            }

            @Override
            public Object[] getElements(final Object inputElement) {
                if (inputElement instanceof Object[]) {
                    return (Object[]) inputElement;
                } else if (inputElement instanceof Entry) {
                    final Entry entry = (Entry) inputElement;
                    final Object value = entry.getValue().getValue();
                    final Object[] childs = makeObjects(value).map(Stream::toArray).orElse(null);
                    if (childs != null && childs.length <= 1) {
                        return null;
                    }
                    return childs;
                }
                return null;
            }

            @Override
            public Object[] getChildren(final TreePath parentPath) {
                return getElements(parentPath.getLastSegment());
            }
        };
        this.viewer.setContentProvider(p);
    }

    private Optional<String> makeTagName(final Entry entry) {
        final Object name = this.tagNameProvider.apply(entry.getKey());
        if (name == null) {
            return Optional.empty();
        }
        return Optional.of(name.toString());
    }

    private StyledString makeType(final Entry entry) {
        final Object val = entry.getValue().getValue();

        final StyledString sb = new StyledString();

        sb.append(Integer.toString(entry.getValue().getType()));

        if (val != null) {
            sb.append(" ");
            sb.append(val.getClass().getSimpleName(), StyledString.QUALIFIER_STYLER);
        }

        return sb;
    }

    private void handleDoubleClick(final DoubleClickEvent dce) {
        if (dce.getSelection().isEmpty() || !(dce.getSelection() instanceof IStructuredSelection)) {
            return;
        }
        final IStructuredSelection sel = (IStructuredSelection) dce.getSelection();
        for (final Object o : (Iterable<?>) sel::iterator) {
            if (o instanceof Entry) {
                final Entry e = (Entry) o;
                final String s = makeString(e);
                final String name = makeTagName(e).orElse(Integer.toString(e.getKey()));
                new TextDialog(() -> this.viewer.getControl().getShell(), name, s).open();
            }
        }
    }

    private static Optional<Stream<?>> makeObjects(final Object value) {
        if (value instanceof Short[]) {
            return of(Arrays.stream((Short[]) value));
        } else if (value instanceof Integer[]) {
            return of(Arrays.stream((Integer[]) value));
        } else if (value instanceof Long[]) {
            return of(Arrays.stream((Long[]) value));
        } else if (value instanceof String[]) {
            return of(Arrays.stream((String[]) value));
        }

        return empty();
    }

    private static void updateCellValue(final ViewerCell cell) {

        final Object ele = cell.getElement();

        if (ele instanceof Entry) {
            final Entry entry = (Entry) ele;
            final String s = cut(makeString(entry), 200);
            cell.setText(s);

        } else if (ele != null) {
            cell.setText(ele.toString());
        }
    }

    private static String makeString(final Entry entry) {
        final Object value = entry.getValue().getValue();
        if (value instanceof byte[]) {
            final byte[] data = (byte[]) value;
            return Rpms.toHex(data);
        } else if (value != null) {
            final Optional<Stream<?>> os = makeObjects(value);
            if (os.isPresent()) {
                final Stream<?> s = os.get();
                return s.map(Object::toString).collect(Collectors.joining(", "));
            } else {
                return value.toString();
            }
        }
        return null;
    }

    private static String cut(final String string, final int maxLength) {
        if (string == null || maxLength <= 0 || string.length() <= maxLength) {
            return string;
        }

        return string.substring(0, maxLength - 1) + "";
    }

    private void createColumn(final AbstractColumnLayout layout, final String name, final int weight,
            final Function<Entry, String> label) {
        createColumnCell(layout, name, weight, (entry, cell) -> {
            final String s = label.apply(entry);
            if (s != null) {
                cell.setText(s);
            }
        });
    }

    private void createStyledColumn(final AbstractColumnLayout layout, final String name, final int weight,
            final Function<Entry, StyledString> label) {
        createColumnCell(layout, name, weight, (entry, cell) -> {
            final StyledString s = label.apply(entry);
            if (s != null) {
                cell.setText(s.getString());
                cell.setStyleRanges(s.getStyleRanges());
            }
        });
    }

    private void createColumnCell(final AbstractColumnLayout layout, final String name, final int weight,
            final Consumer<ViewerCell> cellUpdater) {
        final TreeViewerColumn col = new TreeViewerColumn(this.viewer, SWT.NONE);
        col.setLabelProvider(new StyledCellLabelProvider() {

            @Override
            public void update(final ViewerCell cell) {
                cellUpdater.accept(cell);
            }
        });
        col.getColumn().setText(name);
        layout.setColumnData(col.getColumn(), new ColumnWeightData(weight));
    }

    private void createColumnCell(final AbstractColumnLayout layout, final String name, final int weight,
            final BiConsumer<Entry, ViewerCell> cellUpdater) {

        createColumnCell(layout, name, weight, cell -> {
            if (cell.getElement() instanceof Entry) {
                final Entry entry = (Entry) cell.getElement();
                cellUpdater.accept(entry, cell);
            }
        });
    }

    public void setInformation(final InputHeader<?> header) {
        this.viewer.setInput(header.getRawTags().entrySet().stream().map(HeaderTable::toEntry).toArray());
        this.viewer.getTree().layout();
    }

    private static Entry toEntry(final Map.Entry<Integer, HeaderValue> entry) {
        final Entry result = new Entry(entry.getKey(), entry.getValue());
        return result;
    }

    public Control getContainer() {
        return this.wrapper;
    }

}