/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) ESO - European Southern Observatory, 2013
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
package alma.acs.eventbrowser.parts;
import java.util.Locale;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.core.services.statusreporter.StatusReporter;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.e4.ui.workbench.swt.modeling.EMenuService;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import alma.acs.nsstatistics.EventData;
import alma.acs.nsstatistics.EventModel;
import alma.acs.eventbrowser.status.StatusLineWriter;
/**
* TODO: check http://tomsondev.bestsolution.at/2011/10/07/jface-viewer-and-eclipse-databinding-with-10-000-objects/
*/
public class EventListPart implements IEventListPart {
/**
* We publish a single selected table row to be used by the event details part.
*/
@Inject
private ESelectionService selectionService;
@Inject
private UISynchronize uiSync;
private TableViewer viewer;
private ViewerFilter tableFilter;
private EventModel em;
private PopulateEventList pel;
private Logger logger;
/**
* Blocking (popup) status report.
*/
@Inject
private StatusReporter statusReporter;
private Thread eventListThread;
/**
* The constructor.
*/
public EventListPart() {
}
/**
*/
@PostConstruct
public void postConstruct(Composite parent, final IEclipseContext context, IEventBroker eventBroker, EMenuService menuService) {
try {
em = EventModel.getInstance();
} catch (Throwable thr) {
thr.printStackTrace();
IStatus someStatus = statusReporter.newStatus(IStatus.ERROR, "Connection with NCs failed.", thr);
statusReporter.report(someStatus, StatusReporter.SHOW);
throw new RuntimeException(thr);
}
logger = em.getLogger();
GridLayout gridLayout = new GridLayout();
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
gridLayout.verticalSpacing = 0;
parent.setLayout(gridLayout);
// TODO: We currently have the filter text control in the regular view toolbar.
// The e3 eventGUI had a "custom tool bar" inserted here.
// We should decide which way it's better.
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
Table table = viewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
/*
* "Time "+timeStamp+" "+m_channelName+" "+component+" "+count+"
* "+channelEventCount+" " +" "+evtTypeName+"
* "+evtCounter.get(evtTypeName)
*/
TableViewerColumn tvcol = new TableViewerColumn(viewer, SWT.NONE, 0);
tvcol.setLabelProvider(new TimeStampLabelProvider());
TableColumn col = tvcol.getColumn();
col.setText("Timestamp");
col.setWidth(180);
col.setAlignment(SWT.LEFT);
tvcol = new TableViewerColumn(viewer, SWT.NONE, 1);
tvcol.setLabelProvider(new EventSourceLabelProvider());
col = tvcol.getColumn();
col.setText("Event source");
col.setWidth(150);
col.setAlignment(SWT.LEFT);
tvcol = new TableViewerColumn(viewer, SWT.NONE, 2);
tvcol.setLabelProvider(new CountLabelProvider());
col = tvcol.getColumn();
col.setText("# Events in channel");
col.setWidth(50);
col.setAlignment(SWT.LEFT);
tvcol = new TableViewerColumn(viewer, SWT.NONE, 3);
tvcol.setLabelProvider(new EventTypeLabelProvider());
col = tvcol.getColumn();
col.setText("Event type");
col.setWidth(150);
col.setAlignment(SWT.LEFT);
tvcol = new TableViewerColumn(viewer, SWT.NONE, 4);
tvcol.setLabelProvider(new EventTypeCountLabelProvider());
col = tvcol.getColumn();
col.setText("# Events this type");
col.setWidth(50);
col.setAlignment(SWT.LEFT);
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getTable());
viewer.setContentProvider(new EventListViewContentProvider(em));
// Attach a selection listener to our event list that will post the selected event for the event details list
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
if (selection.size() == 1) {
selectionService.setSelection(selection.getFirstElement());
}
}
});
viewer.setInput(new Object());
hookContextMenu(menuService);
pel = new PopulateEventList(logger, viewer, new StatusLineWriter(eventBroker), em.getEventQueue(), "NC Events");
eventListThread = pel.getThreadForEventList();
eventListThread.start();
}
/**
* @see alma.acs.eventGui2.parts.IEventListPart#notifyEventTypeFilterChange(java.lang.String)
*/
@Override
public void notifyEventTypeFilterChanged(final String filterText) {
// System.out.println("EventListPart#notifyEventTypeFilterChange : " + filterText);
if (tableFilter != null) {
viewer.removeFilter(tableFilter);
}
tableFilter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
if (filterText.equals("")) {
return true;
}
EventData row = (EventData)element;
String column = row.getEventTypeName();
if (column.toUpperCase(Locale.ENGLISH).contains(filterText.toUpperCase(Locale.ENGLISH))) {
return true;
}
return false;
}
};
viewer.addFilter(tableFilter);
viewer.refresh();
}
private void hookContextMenu(EMenuService menuService) {
// For the case of popup (mouse) menues we actually reference the menu ID from the Application.e4xmi
MPopupMenu menu = menuService.registerContextMenu(viewer.getTable(), "alma.acs.eventgui.popupmenu.eventlist");
if (menu == null) {
System.out.println("EventListPart popup menu is null!");
}
}
@Override
public void clearList() {
// TODO: This asyncExec from the e3 impl is suspicious. Probably should run this as a Job in a non-UI thread and from there update the UI
uiSync.asyncExec(new Runnable() {
public void run() {
viewer.getTable().removeAll();
viewer.refresh();
};
});
}
@Focus
public void setFocus() {
viewer.getTable().setFocus();
}
@PreDestroy
public void preDestroy() {
eventListThread.interrupt();
}
}