package org.intrace.client.gui.helper; import java.io.IOException; import java.util.ArrayList; import java.util.regex.Pattern; import net.miginfocom.swt.MigLayout; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.List; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import org.intrace.client.gui.helper.InTraceUI.UIMode; import org.intrace.client.gui.helper.InTraceUI.UIModeData; public class IncludeExcludeWindow { public final Shell sWindow; private final TabFolder tabs; private final CTabFolder ctabs; private final PatternInputCallback callback; private PatternInput patterns; private final SaveCancelButtons saveCancelButtons; private final Pattern allowedStrings; private final UIModeData modedata; public IncludeExcludeWindow(String windowTitle, String helpText, UIMode mode, UIModeData modedata, PatternInputCallback callback, java.util.List<String> initIncludePatterns, java.util.List<String> initExcludePatterns, Pattern allowedStrings) { this.modedata = modedata; this.callback = callback; this.allowedStrings = allowedStrings; MigLayout windowLayout = new MigLayout("fill", "[grow][100][100][grow]", "[grow][25]"); if (initExcludePatterns == null) { windowLayout.setRowConstraints("[grow][25]"); } sWindow = new Shell(SWT.APPLICATION_MODAL | SWT.CLOSE | SWT.TITLE | SWT.RESIZE); try { Display display = sWindow.getDisplay(); Image[] icons = InTraceUI.getIcons(display); sWindow.setImages(icons); } catch (IOException ex) { // Ignore } sWindow.setText(windowTitle); sWindow.setLayout(windowLayout); sWindow.setSize(new Point(400, 400)); sWindow.setMinimumSize(new Point(400, 400)); sWindow.addListener(SWT.Traverse, new Listener() { @Override public void handleEvent(Event event) { switch (event.detail) { case SWT.TRAVERSE_ESCAPE: sWindow.close(); event.detail = SWT.TRAVERSE_NONE; event.doit = false; break; } } }); if (mode == UIMode.STANDALONE) { ctabs = null; tabs = new TabFolder(sWindow, SWT.NONE); tabs.setLayoutData("grow,wrap,wmin 0,hmin 0,spanx 4"); fillTabs(tabs, initIncludePatterns, initExcludePatterns, helpText); } else { tabs = null; ctabs = new CTabFolder(sWindow, SWT.TOP | SWT.BORDER); ctabs.setSimple(false); ctabs.setLayoutData("grow,wrap,wmin 0,hmin 0,wmin 0,spanx 4"); fillCTabs(ctabs, initIncludePatterns, initExcludePatterns, helpText); ctabs.setSelection(0); if (this.modedata != null) { ctabs.setSelectionBackground( new Color[]{this.modedata.activeColorOne, this.modedata.activeColorTwo}, new int[]{100}, true); } } saveCancelButtons = new SaveCancelButtons(sWindow); // Focus on text input patterns.newPattern.patternInput.setFocus(); } private void fillTabs(TabFolder tabFolder, java.util.List<String> initIncludePatterns, java.util.List<String> initExcludePatterns, String helpText) { TabItem patternsTabItem = new TabItem(tabFolder, SWT.NONE); patternsTabItem.setText("Include/Exclude"); patterns = new PatternInput(tabFolder, initIncludePatterns, initExcludePatterns); patternsTabItem.setControl(patterns.patternInputComp); TabItem helpTabItem = new TabItem(tabFolder, SWT.NONE); helpTabItem.setText("Help"); HelpOutputTab helpOutputTab = new HelpOutputTab(tabFolder, helpText); helpTabItem.setControl(helpOutputTab.composite); } private void fillCTabs(CTabFolder tabFolder, java.util.List<String> initIncludePatterns, java.util.List<String> initExcludePatterns, String helpText) { CTabItem patternsTabItem = new CTabItem(tabFolder, SWT.NONE); patternsTabItem.setText("Include/Exclude"); patterns = new PatternInput(tabFolder, initIncludePatterns, initExcludePatterns); patternsTabItem.setControl(patterns.patternInputComp); CTabItem helpTabItem = new CTabItem(tabFolder, SWT.NONE); helpTabItem.setText("Help"); HelpOutputTab helpOutputTab = new HelpOutputTab(tabFolder, helpText); helpTabItem.setControl(helpOutputTab.composite); } private class HelpOutputTab { final StyledText textOutput; final Composite composite; private HelpOutputTab(Composite parent, String helpStr) { MigLayout windowLayout = new MigLayout("fill,wmin 0,hmin 0", "[grow]", "[grow]"); composite = new Composite(parent, SWT.NONE); composite.setLayout(windowLayout); textOutput = new StyledText(composite, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER | SWT.WRAP); textOutput.setEditable(false); textOutput.setLayoutData("spanx,grow,wmin 0,hmin 0"); textOutput.setBackground(Display.getCurrent().getSystemColor( SWT.COLOR_WHITE)); textOutput.setText(helpStr); } } private class PatternInput { private final NewPattern newPattern; private final PatternList patternList; private final Composite patternInputComp; private IncludeExcludeHeaders model; public PatternInput(Composite parent, java.util.List<String> initIncludePatterns, java.util.List<String> initExcludePatterns) { patternInputComp = new Composite(parent, SWT.NONE); MigLayout inputLayout = new MigLayout("fill", "[grow]", "[25][grow]"); patternInputComp.setLayout(inputLayout); patternInputComp.setLayoutData("grow,wrap,spanx,hmin 0,wmin 0"); newPattern = new NewPattern(patternInputComp); patternList = new PatternList(patternInputComp); model = new IncludeExcludeHeaders(new IncludeExcludeHeaders.IncludeExcludeList() { @Override public void remove(int xiIndex) { patternList.patternSet.remove(xiIndex); } @Override public String[] getItems() { return patternList.patternSet.getItems(); } @Override public void add(String xiItem, int xiIndex) { patternList.patternSet.add(xiItem, xiIndex); } @Override public void add(String xiItem) { patternList.patternSet.add(xiItem); } }); parsePatternSet(true, initIncludePatterns); parsePatternSet(false, initExcludePatterns); } private void parsePatternSet(boolean xiInclude, java.util.List<String> initPattern) { for (String pattern : initPattern) { parsePattern(xiInclude, pattern); } } private void parsePattern(boolean xiInclude, String pattern) { if ((pattern != null) && (pattern.length() > 0) && (!pattern.equals(TraceFilterThread.MATCH_ALL))) { model.addItem(xiInclude, pattern); } } private class NewPattern { private final Text patternInput; private final Button includeButton; private final Button excludeButton; private NewPattern(Composite parent) { Group newPatternGroup = new Group(parent, SWT.SHADOW_ETCHED_IN); newPatternGroup.setLayoutData("grow,wrap"); MigLayout newPatternLayout = new MigLayout("fill", "[][grow][60][60]", "[][]"); newPatternGroup.setLayout(newPatternLayout); newPatternGroup.setText("New Pattern"); includeButton = new Button(newPatternGroup, SWT.RADIO); includeButton.setText("Include"); includeButton.setSelection(true); excludeButton = new Button(newPatternGroup, SWT.RADIO); excludeButton.setText("Exclude"); excludeButton.setLayoutData("wrap"); patternInput = new Text(newPatternGroup, SWT.BORDER); patternInput.setLayoutData("grow,spanx 2"); final Button addButton = new Button(newPatternGroup, SWT.PUSH); addButton.setText("Add"); addButton.setAlignment(SWT.CENTER); addButton.setLayoutData("grow"); Button removeButton = new Button(newPatternGroup, SWT.PUSH); removeButton.setText("Remove"); removeButton.setAlignment(SWT.CENTER); removeButton.setLayoutData("grow,wrap"); addButton .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { patternList.addItem(); } }); removeButton .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { patternList.removeItem(); } }); patternInput .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { @Override public void widgetDefaultSelected(SelectionEvent arg0) { patternList.addItem(); saveCancelButtons.saveButton.setFocus(); } }); patternInput.addVerifyListener(new VerifyListener() { @Override public void verifyText(VerifyEvent event) { String str = event.text; if (str.length() > 0) { String existingStr = newPattern.patternInput.getText(); String newStr = existingStr + str; if (newStr.contains("|") && !allowedStrings.matcher("|").matches()) { String[] parts = newStr.split("\\|"); boolean allowed = true; for (String part : parts) { allowed = allowed && allowedStrings.matcher(part).matches(); } event.doit = allowed; } else { event.doit = allowedStrings.matcher(newStr).matches(); } } } }); sWindow.addListener(SWT.Traverse, new Listener() { @Override public void handleEvent(Event event) { switch (event.detail) { case SWT.TRAVERSE_ESCAPE: sWindow.close(); event.detail = SWT.TRAVERSE_NONE; event.doit = false; break; } } }); } } private class PatternList { private final List patternSet; private PatternList(Composite parent) { Group patternGroup = new Group(parent, SWT.SHADOW_ETCHED_IN); patternGroup.setLayoutData("grow,hmin 0,wmin 0"); MigLayout patternLayout = new MigLayout("fill"); patternGroup.setLayout(patternLayout); patternGroup.setText("Patterns (Double click to Edit)"); patternSet = new List(patternGroup, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); patternSet.setLayoutData("grow,hmin 0,wmin 0"); patternSet.addMouseListener(new org.eclipse.swt.events.MouseAdapter() { @Override public void mouseDoubleClick(MouseEvent mouseevent) { editItem(); } }); } private void addItem() { String newItem = newPattern.patternInput.getText(); if (newItem.length() > 0) { boolean includeItem = newPattern.includeButton.getSelection(); if (newItem.contains("|") && !allowedStrings.matcher("|").matches()) { String[] parts = newItem.split("\\|"); for (String part : parts) { if (part.length() > 0) { model.addItem(includeItem, part); } } newPattern.patternInput.setText(""); } else { model.addItem(includeItem, newItem); newPattern.patternInput.setText(""); } } } private void removeItem() { int[] selectedItems = patternSet.getSelectionIndices(); if (selectedItems.length == 1) { int selectedItem = selectedItems[0]; model.removeIndex(selectedItem); } else if (newPattern.patternInput.getText().length() > 0) { newPattern.patternInput.setText(""); } } private void editItem() { int[] selectedItems = patternSet.getSelectionIndices(); if (selectedItems.length == 1) { int selectedItem = selectedItems[0]; String item = patternSet.getItem(selectedItem).trim(); if (model.removeIndex(selectedItem)) { newPattern.patternInput.setText(item); newPattern.patternInput.setFocus(); newPattern.patternInput .setSelection(newPattern.patternInput .getText() .length()); } } } } private java.util.List<String> getIncludePattern() { java.util.List<String> includes = new ArrayList<String>(); includes.addAll(model.getIncludePattern()); if (newPattern.includeButton.getSelection()) { String newPatternStr = newPattern.patternInput.getText(); if (newPatternStr.length() > 0) { includes.add(newPatternStr); } } return includes; } private java.util.List<String> getExcludePattern() { java.util.List<String> excludes = new ArrayList<String>(); excludes.addAll(model.getExcludePattern()); if (newPattern.excludeButton.getSelection()) { String newPatternStr = newPattern.patternInput.getText(); if (newPatternStr.length() > 0) { excludes.add(newPatternStr); } } return excludes; } } private class SaveCancelButtons { final Button saveButton; private SaveCancelButtons(Composite sParent) { saveButton = new Button(sParent, SWT.PUSH); saveButton.setText("Apply Changes"); saveButton.setAlignment(SWT.CENTER); saveButton.setLayoutData("skip,grow"); Button discardButton = new Button(sParent, SWT.PUSH); discardButton.setText("Discard Changes"); discardButton.setAlignment(SWT.CENTER); discardButton.setLayoutData("grow"); saveButton .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { callback.setIncludePattern(patterns.getIncludePattern()); callback.setExcludePattern(patterns.getExcludePattern()); sWindow.close(); } }); discardButton .addSelectionListener(new org.eclipse.swt.events.SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { sWindow.close(); } }); } } public static interface PatternInputCallback { public void setIncludePattern(java.util.List<String> newIncludePattern); public void setExcludePattern(java.util.List<String> newExcludePattern); } /** * Class which managed the presence of include/exclude headers * within a list of items. */ public static class IncludeExcludeHeaders { public static interface IncludeExcludeList { public void add(String xiItem); public void add(String xiItem, int xiIndex); public void remove(int xiIndex); public String[] getItems(); } private static final String INCLUDE_TITLE = "Include:"; private static final String EXCLUDE_TITLE = "Exclude:"; private int includeIndex = -1; private int excludeIndex = -1; private final IncludeExcludeList list; public IncludeExcludeHeaders(IncludeExcludeList view) { this.list = view; } public void addItem(boolean xiInclude, String newItem) { boolean addItem = true; // Add headers if (xiInclude && (includeIndex == -1)) { list.add(INCLUDE_TITLE, 0); includeIndex = 0; if (excludeIndex > -1) { // Include header was already added excludeIndex++; // Add spacer list.add("", 1); excludeIndex++; } } else if (!xiInclude && (excludeIndex == -1)) { if (includeIndex > -1) { list.add(""); } list.add(EXCLUDE_TITLE); excludeIndex = list.getItems().length - 1; } String[] currentItems = list.getItems(); int startItem, endItem; if (xiInclude) { startItem = 1; if (excludeIndex == -1) { endItem = currentItems.length; } else { endItem = excludeIndex - 1; } } else { startItem = excludeIndex + 1; endItem = currentItems.length; } for (int ii = startItem; ii < endItem; ii++) { String item = currentItems[ii].trim(); if (item.equals(newItem)) { addItem = false; break; } } if (addItem) { list.add(" " + newItem, endItem); if ((excludeIndex != -1) && (endItem < excludeIndex)) { excludeIndex++; } } } public boolean removeIndex(int index) { if ((index == includeIndex) || (index == excludeIndex) || (index == (excludeIndex - 1))) { // Ignore return false; } // Remove item list.remove(index); // Check if we removed an included item when we already // had an excluded item int count = list.getItems().length; if ((excludeIndex != -1) && (index < excludeIndex)) { // Removed an item above the exclude header excludeIndex--; } if ((includeIndex != -1) && ((excludeIndex == 2) || (count == 1))) { // We need to remove the include header // as we have no include items left list.remove(includeIndex); includeIndex = -1; if (excludeIndex > -1) { // We need to remove the spacer above // the exclude header // Include element was removed excludeIndex--; // Remove spacer element list.remove(0); excludeIndex--; } } if ((excludeIndex != -1) && (excludeIndex == (count - 1))) { // We need to remove the exclude header // as we have no exclude items left if (includeIndex != -1) { // We need to remove the spacer above // the exclude header list.remove(excludeIndex - 1); excludeIndex--; } list.remove(excludeIndex); excludeIndex = -1; } return true; } public java.util.List<String> getIncludePattern() { java.util.List<String> includes = new ArrayList<String>(); if (includeIndex != -1) { String[] items = list.getItems(); int endIndex = items.length; if (excludeIndex != -1) { endIndex = excludeIndex - 1; } for (int ii = 1; ii < endIndex; ii++) { String item = items[ii].trim(); includes.add(item); } } return includes; } public java.util.List<String> getExcludePattern() { java.util.List<String> excludes = new ArrayList<String>(); if (excludeIndex != -1) { String[] items = list.getItems(); int endIndex = items.length; for (int ii = (excludeIndex + 1); ii < endIndex; ii++) { String item = items[ii].trim(); excludes.add(item); } } return excludes; } } }