org.csstudio.trends.databrowser2.search.ArchiveListGUI.java Source code

Java tutorial

Introduction

Here is the source code for org.csstudio.trends.databrowser2.search.ArchiveListGUI.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Oak Ridge National Laboratory.
 * 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
 ******************************************************************************/
package org.csstudio.trends.databrowser2.search;

import java.util.ArrayList;
import java.util.Arrays;

import org.csstudio.apputil.ui.swt.TableColumnSortHelper;
import org.csstudio.archive.reader.ArchiveInfo;
import org.csstudio.trends.databrowser2.Messages;
import org.csstudio.trends.databrowser2.archive.ConnectJob;
import org.csstudio.trends.databrowser2.model.ArchiveDataSource;
import org.csstudio.trends.databrowser2.preferences.ArchiveServerURL;
import org.csstudio.trends.databrowser2.preferences.Preferences;
import org.csstudio.trends.databrowser2.propsheet.AddArchiveAction;
import org.csstudio.trends.databrowser2.ui.TableHelper;
import org.csstudio.ui.util.MinSizeTableColumnLayout;
import org.csstudio.ui.util.dnd.ControlSystemDragSource;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;

/** GUI for basic list of archives: URL of server, list of archives on server
 *  <p>
 *  Used by {@link AddArchiveAction} and {@link SearchView}
 *  @author Kay Kasemir
 *  @author Takashi Nakamoto - added archive server alias
 */
public abstract class ArchiveListGUI {
    // GUI elements
    private Combo urls;
    private Button info;
    private TableViewer archive_table;

    private volatile String server_info = null;

    /** Most recently selected archive URL */
    private String url = null;

    /** Archive servers */
    private final ArchiveServerURL[] server_urls;
    /** Default archives per server if selected */
    private final ArchiveDataSource[] default_archives;

    /** Initialize
     *  @param parent Parent widget
     */
    public ArchiveListGUI(final Composite parent) {
        server_urls = Preferences.getArchiveServerURLs();
        default_archives = Preferences.getArchives();

        createGUI(parent);

        // When URL is selected, connect to server to get info, list of archives
        urls.addSelectionListener(new SelectionListener() {
            @Override
            public void widgetDefaultSelected(final SelectionEvent e) {
                int i = urls.getSelectionIndex();
                if (i >= 0 && i < server_urls.length)
                    connectToArchiveServer(server_urls[i].getURL());
            }

            @Override
            public void widgetSelected(final SelectionEvent e) { // Same response
                widgetDefaultSelected(e);
            }
        });

        // Display info about selected archive
        info.addSelectionListener(new SelectionAdapter() {
            @SuppressWarnings("nls")
            @Override
            public void widgetSelected(final SelectionEvent e) {
                final String copy = server_info;
                if (copy == null)
                    return;
                MessageDialog.openInformation(info.getShell(), "Archive Server Info", copy);
            }
        });

        // Activate the first archive server URL
        if (urls.getEnabled()) {
            int i = urls.getSelectionIndex();
            if (i >= 0 && i < server_urls.length)
                connectToArchiveServer(server_urls[i].getURL());
        }

        // Archive table: Allow dragging of multiple archive data sources
        new ControlSystemDragSource(archive_table.getTable()) {
            @Override
            public Object getSelection() {
                final Object[] objs = ((IStructuredSelection) archive_table.getSelection()).toArray();
                final ArchiveDataSource[] archives = Arrays.copyOf(objs, objs.length, ArchiveDataSource[].class);
                return archives;
            }
        };
    }

    /** Set initial focus */
    public void setFocus() {
        urls.setFocus();
    }

    /** Create GUI elements
     *  @param parent Parent widget
     */
    private void createGUI(final Composite parent) {
        final GridLayout layout = new GridLayout(3, false);
        parent.setLayout(layout);

        // URL:  ___urls___  [info]
        Label l;
        l = new Label(parent, 0);
        l.setText(Messages.Search_URL);
        l.setLayoutData(new GridData());

        urls = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
        urls.setToolTipText(Messages.Search_URL_TT);
        for (ArchiveServerURL url : server_urls)
            urls.add(url.getDisplayName());
        urls.setLayoutData(new GridData(SWT.FILL, 0, true, false));
        if (urls.getItemCount() <= 0) {
            urls.add(Messages.ArchiveListGUI_NoArchives);
            urls.setEnabled(false);
        }
        urls.select(0);

        info = new Button(parent, SWT.PUSH);
        info.setText(Messages.ArchiveServerInfo);
        info.setToolTipText(Messages.ArchiveServerInfoTT);
        info.setEnabled(false);

        // Table for archives, displaying array of ArchiveDataSource entries
        // TableColumnLayout requires table in its own container
        final Composite table_parent = new Composite(parent, 0);
        table_parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, layout.numColumns, 1));
        final TableColumnLayout table_layout = new MinSizeTableColumnLayout(10);
        table_parent.setLayout(table_layout);
        archive_table = new TableViewer(table_parent,
                SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION);
        archive_table.setContentProvider(new ArrayContentProvider());
        TableViewerColumn col = TableHelper.createColumn(table_layout, archive_table, Messages.ArchiveName, 150,
                100);
        col.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {
                final ArchiveDataSource archive = (ArchiveDataSource) cell.getElement();
                cell.setText(archive.getName());
            }
        });
        new TableColumnSortHelper<ArchiveDataSource>(archive_table, col) {
            @Override
            public int compare(final ArchiveDataSource item1, final ArchiveDataSource item2) {
                return item1.getName().compareTo(item2.getName());
            }
        };
        col = TableHelper.createColumn(table_layout, archive_table, Messages.ArchiveDescription, 50, 100);
        col.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {
                final ArchiveDataSource archive = (ArchiveDataSource) cell.getElement();
                cell.setText(archive.getDescription());
            }
        });
        new TableColumnSortHelper<ArchiveDataSource>(archive_table, col) {
            @Override
            public int compare(final ArchiveDataSource item1, final ArchiveDataSource item2) {
                return item1.getDescription().compareTo(item2.getDescription());
            }
        };
        col = TableHelper.createColumn(table_layout, archive_table, Messages.ArchiveKey, 35, 5);
        col.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(final ViewerCell cell) {
                final ArchiveDataSource archive = (ArchiveDataSource) cell.getElement();
                cell.setText(Integer.toString(archive.getKey()));
            }
        });
        new TableColumnSortHelper<ArchiveDataSource>(archive_table, col) {
            @Override
            public int compare(final ArchiveDataSource item1, final ArchiveDataSource item2) {
                return item1.getKey() - item2.getKey();
            }
        };
        final Table table = archive_table.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
    }

    /** @param listener Listener to selections in the archives table of the GUI */
    public void addSelectionListener(final ISelectionChangedListener listener) {
        archive_table.addSelectionChangedListener(listener);
    }

    /** Connect to archive data server.
     *  <p>
     *  On success, set <code>server</code>, update <code>archive_table</code>
     *  @param url Server URL
     */
    private void connectToArchiveServer(final String url) {
        new ConnectJob(url) {
            @Override
            protected void archiveServerConnected(final String server_info, final ArchiveInfo infos[]) {
                ArchiveListGUI.this.server_info = server_info;
                if (urls.isDisposed())
                    return;
                urls.getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (info.isDisposed())
                            return;
                        ArchiveListGUI.this.url = url;

                        final ArrayList<ArchiveDataSource> archives = new ArrayList<ArchiveDataSource>();
                        for (ArchiveInfo info : infos)
                            archives.add(new ArchiveDataSource(url, info.getKey(), info.getName(),
                                    info.getDescription()));
                        archive_table.setInput(archives);
                        // If a default archive engine is set for this URL, select it in the table.
                        for (ArchiveDataSource dataSource : default_archives) {
                            if (dataSource.getUrl().equals(url) && archives.contains(dataSource)) {
                                int selection = archives.indexOf(dataSource);
                                archive_table.setSelection(
                                        new StructuredSelection(archive_table.getElementAt(selection)));
                                break;
                            }
                        }
                        // Enable operations on server resp. archives
                        info.setEnabled(true);
                        handleArchiveUpdate();
                    }
                });
            }

            @Override
            protected void archiveServerError(final String url, final Exception ex) { // Called from non-UI thread
                if (info.isDisposed())
                    return;
                info.getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (info.isDisposed())
                            return;
                        info.setEnabled(false);
                        handleServerError(url, ex);
                    }
                });
            }
        }.schedule();
    }

    /** @return Selected archive data sources or 'all' when nothing selected.
     *          Returns <code>null</code> if user decided not to search 'all',
     *          or if connection to data server is not available.
     */
    @SuppressWarnings("unchecked")
    public ArchiveDataSource[] getSelectedArchives() {
        if (url == null)
            return null;
        final ArrayList<ArchiveDataSource> archives;
        final IStructuredSelection sel = (IStructuredSelection) archive_table.getSelection();
        if (sel.isEmpty()) {
            // Use 'all' archives, but prompt for confirmation
            archives = (ArrayList<ArchiveDataSource>) archive_table.getInput();
            if (archives.size() > 1 && !MessageDialog.openConfirm(archive_table.getTable().getShell(),
                    Messages.Search, NLS.bind(Messages.SearchArchiveConfirmFmt, archives.size())))
                return null;
        } else {
            archives = new ArrayList<ArchiveDataSource>();
            final Object[] objs = sel.toArray();
            for (Object obj : objs)
                archives.add((ArchiveDataSource) obj);
        }
        return (ArchiveDataSource[]) archives.toArray(new ArchiveDataSource[archives.size()]);
    }

    /** Called after receiving error from archive server.
     *  From now on, getServer and getSelectedArchives should function.
     *  @param url Server URL
     *  @param ex Error
     */
    abstract protected void handleServerError(String url, Exception ex);

    /** Called after receiving list of archives from a server.
     *  From now on, getServer and getSelectedArchives will not return
     *  useful data.
     */
    abstract protected void handleArchiveUpdate();
}