package com.netifera.platform.ui.tasks.output; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.viewers.AbstractTableViewer; import org.eclipse.jface.viewers.ILazyContentProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import com.netifera.platform.api.events.IEvent; import com.netifera.platform.api.events.IEventHandler; import com.netifera.platform.api.tasks.ITaskOutput; import com.netifera.platform.api.tasks.ITaskOutputEvent; import com.netifera.platform.api.tasks.ITaskRecord; import com.netifera.platform.ui.updater.TableUpdater; public class TaskOutputContentProvider implements ILazyContentProvider, IStructuredContentProvider { private final IEventHandler taskOutputHandler; private ITaskRecord focusedTask; private List<ITaskOutput> input; private AbstractTableViewer viewer; private TableUpdater updater; // if ascending false updateElement requested indexes are reversed private volatile boolean ascending = true; private List<Object> filteredElements; TaskOutputContentProvider() { taskOutputHandler = new IEventHandler() { public void handleEvent(IEvent event) { if (event instanceof ITaskOutputEvent) { handleTaskOutput((ITaskOutputEvent) event); } } }; } private void handleTaskOutput(ITaskOutputEvent event) { ITaskOutput message = event.getMessage(); if ((focusedTask != null) && (focusedTask.getTaskId() == message.getTaskId())) { updateFilters(viewer.getFilters()); addFiltered(message); updater.setItemCount(inputSize()); } } public void dispose() { if(focusedTask != null) { focusedTask.removeTaskOutputListener(taskOutputHandler); } } public void updateElement(int index) { if (viewer != null && input != null) { int inputSize = inputSize(); /* * this is a hack? if the virtual table is empty as a result of * being filtered then when the filters are removed the table is not * updated and remains empty. */ if (inputSize == 0) { updater.setItemCount(1); return; } updater.setItemCount(inputSize()); if (index < inputSize) { updater.replace(getElement(index), index); } } } /** * @param virtualIndex * the index in the virtual table * @return the element in the given index after sorting and filtering */ private Object getElement(int virtualIndex) { int index = ascending ? virtualIndex : (inputSize() - virtualIndex - 1); /* if not filtered input return input element */ if (filteredElements == null) { return input.get(index); } /* get filters from viewer */ ViewerFilter[] filters = viewer.getFilters(); if (filters == null || filters.length == 0) { /* if no filters then forget about filtering */ filteredElements = null; return input.get(index); } return filteredElements.get(index); } private boolean updateFilters(ViewerFilter[] filters) { /* check if filter configuration changed */ for (ViewerFilter filter : filters) { /* it is an innocent hack */ if (filter.isFilterProperty(null, null)) { /* filter again */ filteredElements = filteredElements(); return true; } } return false; } private boolean isFiltered(Object element) { ViewerFilter[] filters = viewer.getFilters(); if (filters == null || filters.length == 0) { return false; } for (ViewerFilter filter : filters) { if (!filter.select(viewer, null, element)) { return true; } } return false; } protected List<Object> filteredElements() { ViewerFilter[] filters = viewer.getFilters(); if (filters != null && filters.length > 0) { ArrayList<Object> filtered = new ArrayList<Object>(input.size()); for (Object element : input.toArray()) { boolean selected = true; for (ViewerFilter filter : filters) { selected = filter.select(viewer, null, element); if (!selected) { break; } } if (selected) { filtered.add(element); } } return filtered; } return null; } protected void addFiltered(Object element) { if (filteredElements != null && !isFiltered(element)) { filteredElements.add(element); } } private int inputSize() { if (filteredElements != null) { updateFilters(viewer.getFilters()); return filteredElements.size(); } return input == null ? 0 : input.size(); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if ((newInput == oldInput) || viewer == null) { return; } if (this.viewer != viewer) { if (!(viewer instanceof AbstractTableViewer)) { throw new IllegalArgumentException( "TaskOutputContentProvider should be used with AbstractTableViewer viewers only"); } this.viewer = (AbstractTableViewer) viewer; /* get update wrapper for the viewer, creating it the first time */ updater = TableUpdater.get(this.viewer); } /* if input is null or not task record clear viewer */ if (!(newInput instanceof ITaskRecord)) { input = null; filteredElements = null; updater.clear(); return; } if(focusedTask != null) { focusedTask.removeTaskOutputListener(taskOutputHandler); focusedTask = null; } focusedTask = (ITaskRecord) newInput; focusedTask.addTaskOutputListener(taskOutputHandler); setTaskOutput(focusedTask.getTaskOutput()); updater.setItemCount(inputSize()); } private void setTaskOutput(List<ITaskOutput> input) { this.input = input; filteredElements = filteredElements(); } public Object[] getElements(Object inputElement) { if (inputElement instanceof List) { return ((List<?>) inputElement).toArray(); } return new Object[0]; } /* * cheap viewer sorting. This method gets called when the user clicks a * table column header */ public void setAscending(boolean ascending) { this.ascending = ascending; if (updater != null) { updater.refresh(); } } }