blob: d5a9d1bdfbfab4bb4d88c39fb69ef3eb6ad43540 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Boeing.
* 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:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.ote.ui.message.search;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.ui.swt.Displays;
import org.eclipse.osee.framework.ui.swt.Widgets;
import org.eclipse.ote.message.lookup.MessageInput;
import org.eclipse.ote.message.lookup.MessageInputItem;
import org.eclipse.ote.message.lookup.MessageInputUtil;
import org.eclipse.ote.message.lookup.MessageLookup;
import org.eclipse.ote.ui.message.search.internal.MessageInputComponent;
import org.eclipse.ote.ui.message.search.internal.MessageViewServiceUtility;
import org.eclipse.ote.ui.message.util.CheckedSelectionDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
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.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.part.ViewPart;
public class MessageSearchView extends ViewPart implements MessageInfoSelectionListener {
public static final String VIEW_ID = "org.eclipse.ote.ui.message.search.MessageSearchView";
public static final String PLUGIN_ID = "org.eclipse.ote.ui.message.search";
protected static final String SEARCHING_ALL_TYPES = "Current Filter:\nSearching All Message Types";
private TreeViewer treeViewer;
private Text searchText;
private Action expandAction, collapseAction, filterAction;
private Label startLabel;
private Composite parentComposite;
private Button searchButton;
private Map<String, Boolean> filters;
private MessageInfoComposite infoComposite;
public MessageSearchView() {
super();
filters = new HashMap<String, Boolean>();
}
@Override
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
SashForm sash = new SashForm(parent, SWT.HORIZONTAL);
Composite left = new Composite(sash, SWT.NONE);
left.setLayout(new FillLayout());
createSearchControl(left);
Composite right = new Composite(sash, SWT.NONE);
right.setLayout(new FillLayout());
infoComposite = new MessageInfoComposite(right);
infoComposite.setSelectionListener(this);
}
public void createSearchControl(Composite parent) {
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.verticalSpacing = 0;
layout.marginWidth = 0;
layout.marginHeight = 0;
parent.setLayout(layout);
parentComposite = new Composite(parent, SWT.NONE);
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
parentComposite.setLayoutData(layoutData);
Widgets.setFormLayout(parentComposite, 5, 5);
startLabel = new Label(parentComposite, SWT.LEFT);
Widgets.attachToParent(startLabel, SWT.TOP, 0, 0);
Widgets.attachToParent(startLabel, SWT.LEFT, 0, 0);
Widgets.attachToParent(startLabel, SWT.RIGHT, 50, 0);
// Create the tree treeViewer as a child of the composite parent
treeViewer = new TreeViewer(parentComposite);
final Tree tree = treeViewer.getTree();
Widgets.attachToControl(tree, startLabel, SWT.TOP, SWT.BOTTOM, 5);
Widgets.attachToParent(tree, SWT.BOTTOM, 100, -50);
Widgets.attachToParent(tree, SWT.LEFT, 0, 0);
Widgets.attachToParent(tree, SWT.RIGHT, 100, 0);
treeViewer.setUseHashlookup(true);
treeViewer.setContentProvider(new MessageSearchViewContentProvider());
treeViewer.setLabelProvider(new MessageSearchViewLabelProvider());
tree.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (e.button == 3) {
Point p = new Point(e.x, e.y);
final Menu contextMenu = getPopupMenu(tree.getParent());
if (contextMenu != null) {
p = tree.toDisplay(p);
contextMenu.setLocation(p);
contextMenu.setVisible(true);
}
}
}
});
tree.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem[] selection = tree.getSelection();
if (selection.length == 1) {
if (selection[0].getData() instanceof MessageInputItem) {
String classname = ((MessageInputItem)selection[0].getData()).getMessageClass();
infoComposite.search(classname);
}
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
/*
* Create a text field to be used for filtering the elements displayed by the tree treeViewer
*/
Group grp = new Group(parentComposite, SWT.NONE);
Widgets.attachToControl(grp, tree, SWT.TOP, SWT.BOTTOM, 5);
Widgets.attachToParent(grp, SWT.LEFT, 0, 0);
Widgets.attachToParent(grp, SWT.RIGHT, 100, 0);
layout = new GridLayout();
layout.numColumns = 3;
grp.setLayout(layout);
Label l = new Label(grp, SWT.NULL);
l.setText("Search:");
l.setToolTipText("Enter a search string.\n* is the wildcard.\nAn integer will search message ids.\n* will return all messages.\n** will return all messages that have elements.\nPUB:<SU> SUB:<SU> to find who uses a message.");
searchText = new Text(grp, SWT.SINGLE | SWT.BORDER);
searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
searchText.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent event) {
if (event.detail == SWT.TRAVERSE_RETURN) {
search(searchText.getText());
}
}
});
searchText.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
e.text = e.text.toUpperCase();
}
});
searchButton = new Button(grp, SWT.PUSH);
searchButton.setText("Go");
searchButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
@Override
public void widgetSelected(SelectionEvent e) {
search(searchText.getText());
}
});
// Create menu, toolbars, filters, sorters.
createActions();
createMenus();
createToolbar();
treeViewer.expandToLevel(0);
}
/**
* sets the filter for searches
*/
private void search(final String searchPattern) {
final Color bgColor = treeViewer.getTree().getBackground();
treeViewer.getTree().setBackground(Displays.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
searchText.setEnabled(false);
searchButton.setEnabled(false);
final Job searchJob = new Job("Searching Messages") {
@Override
public IStatus run(IProgressMonitor monitor) {
try {
String searchTxt = searchPattern.trim();
if (searchPattern.equals("")) {
return new Status(IStatus.OK, PLUGIN_ID, "Empty Search String");
}
MessageLookup messageLookup = MessageViewServiceUtility.getService(MessageLookup.class);
if(messageLookup != null){
final List<MessageInputItem> results;
List<String> searchFilters = new ArrayList<String>();
for(Entry<String, Boolean> entry:filters.entrySet()){
if(entry.getValue()){
searchFilters.add(entry.getKey());
}
}
if(isFiltered() && searchFilters.size() > 0){
results = MessageInputUtil.messageLookupResultToMessageInputItem( messageLookup.lookup(searchTxt, searchFilters.toArray(new String[0])));
} else {
results = MessageInputUtil.messageLookupResultToMessageInputItem( messageLookup.lookup(searchTxt));
}
Displays.ensureInDisplayThread(new Runnable() {
@Override
public void run() {
treeViewer.setInput(results);
}
});
}
return new Status(IStatus.OK, PLUGIN_ID, IStatus.OK, "", null);
} catch (Throwable t) {
OseeLog.log(MessageSearchView.class, Level.SEVERE, "exception during search operation", t);
return new Status(IStatus.CANCEL, PLUGIN_ID, IStatus.CANCEL, "", t);
} finally {
Displays.pendInDisplayThread(new Runnable() {
@Override
public void run() {
treeViewer.getTree().setBackground(bgColor);
searchText.setEnabled(true);
searchButton.setEnabled(true);
}
});
}
}
};
searchJob.setUser(true);
searchJob.schedule();
}
private Menu getPopupMenu(final Composite composite) {
final IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
MessageInputComponent messageInputComponent = MessageViewServiceUtility.getService(MessageInputComponent.class);
if(selection.isEmpty() || messageInputComponent.getMessageInputs().size() == 0){
return null;
}
List<MessageInputItem> selectedItems = getSelectedItems(selection);
boolean includesElements = false;
for (MessageInputItem item : selectedItems) {
if (item.getChildren().isEmpty()) {
includesElements = true;
break;
}
}
final Menu previewMenu = new Menu(composite);
for(final MessageInput messageInput: messageInputComponent.getMessageInputs()){
if (includesElements && messageInput.messagesOnly()) {
continue;
}
MenuItem item = new MenuItem(previewMenu, SWT.CASCADE);
item.setText("Add to " + messageInput.getLabel());
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
List<MessageInputItem> selectedItems = getSelectedItems(selection);
messageInput.add(selectedItems);
}
});
}
return previewMenu;
}
private List<MessageInputItem> getSelectedItems(final IStructuredSelection selection) {
List<MessageInputItem> selectedItems = new ArrayList<MessageInputItem>();
@SuppressWarnings("rawtypes")
Iterator it = selection.iterator();
while(it.hasNext()){
Object selectedItem = it.next();
if(selectedItem instanceof MessageInputItem){
selectedItems.add((MessageInputItem)selectedItem);
}
}
return selectedItems;
}
private void createActions() {
final TreeViewer ftv = treeViewer;
expandAction = new Action("Expand All") {
@Override
public void run() {
treeViewer.getTree().setRedraw(false);
ftv.expandAll();
treeViewer.getTree().setRedraw(true);
}
};
expandAction.setImageDescriptor(OteMessageViewImage.EXPAND_STATE.createImageDescriptor());
expandAction.setToolTipText("Expand All");
collapseAction = new Action("Collapse All") {
@Override
public void run() {
treeViewer.getTree().setRedraw(false);
ftv.collapseAll();
treeViewer.getTree().setRedraw(true);
}
};
collapseAction.setImageDescriptor(OteMessageViewImage.COLLAPSE_STATE.createImageDescriptor());
collapseAction.setToolTipText("Collapse All");
filterAction = new Action("Search Filters"){
@Override
public void run() {
Shell shell = Displays.getActiveShell();
MessageLookup messageLookup = MessageViewServiceUtility.getService(MessageLookup.class);
for(String filter:messageLookup.getAvailableMessageTypes()){
Boolean val = filters.get(filter);
if(val == null){
filters.put(filter, true);
} else {
filters.put(filter, val);
}
}
CheckedSelectionDialog msgSelectionDialog = new CheckedSelectionDialog(shell, "Message Types To Search", filters);
if (msgSelectionDialog.open() == Window.OK) {
if(allOff()){
selectAllMemTypes();
}
filterAction.setToolTipText(getFilterTooltip(filters));
}
}
private String getFilterTooltip(Map<String, Boolean> filters) {
if(isFiltered()){
StringBuilder sb = new StringBuilder();
sb.append("Current Filter:\n");
List<String> keys = new ArrayList<String>();
keys.addAll(filters.keySet());
Collections.sort(keys);
for(String key:keys){
if(filters.get(key)){
sb.append("Searching ");
sb.append(key);
sb.append(" Message Type\n");
}
}
sb.append("---------------------------\n");
for(String key:keys){
if(!filters.get(key)){
sb.append("Ignoring ");
sb.append(key);
sb.append(" Message Type\n");
}
}
return sb.toString();
} else {
return SEARCHING_ALL_TYPES;
}
}
};
filterAction.setToolTipText(SEARCHING_ALL_TYPES);
}
private void selectAllMemTypes(){
for(Entry<String, Boolean> entry:filters.entrySet()){
entry.setValue(true);
}
}
private boolean isFiltered(){
boolean allOn = true;
for(Boolean selected:filters.values()){
if(!selected){
allOn = false;
break;
}
}
return !allOn;
}
private boolean allOff(){
boolean allOff = true;
for(Boolean selected:filters.values()){
if(selected){
allOff = false;
break;
}
}
return allOff;
}
private void createMenus() {
if (getViewSite() != null) {
IMenuManager rootMenuManager = getViewSite().getActionBars().getMenuManager();
rootMenuManager.setRemoveAllWhenShown(true);
rootMenuManager.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager mgr) {
fillMenu(mgr);
}
});
fillMenu(rootMenuManager);
}
}
private void fillMenu(IMenuManager rootMenuManager) {
rootMenuManager.add(expandAction);
rootMenuManager.add(collapseAction);
}
private void createToolbar() {
if (getViewSite() != null) {
IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager();
toolbarManager.add(filterAction);
toolbarManager.add(expandAction);
toolbarManager.add(collapseAction);
}
}
/*
* @see IWorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
parentComposite.setFocus();
}
@Override
public void dispose() {
super.dispose();
}
@Override
public void associatedClassSelected(String classname) {
classname = classname.substring(classname.lastIndexOf('.')+1);
searchText.setText(classname);
search(classname);
}
@Override
public String getAssociatedToolTip() {
return "Click to search for the selected message";
}
public static void main(String[] args) {
Display display = new Display ();
Shell shell = new Shell (display);
shell.setText ("Shell");
shell.setLayout(new FormLayout());
final MessageSearchView view = new MessageSearchView();
view.createPartControl(shell);
shell.pack();
shell.open ();
shell.setSize (600, 400);
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}