KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > presentations > AbstractTableInformationControl


1 /*******************************************************************************
2  * Copyright (c) 2003, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.presentations;
12
13 import org.eclipse.core.runtime.Platform;
14 import org.eclipse.jface.viewers.ILabelProvider;
15 import org.eclipse.jface.viewers.IStructuredSelection;
16 import org.eclipse.jface.viewers.StructuredSelection;
17 import org.eclipse.jface.viewers.TableViewer;
18 import org.eclipse.jface.viewers.Viewer;
19 import org.eclipse.jface.viewers.ViewerFilter;
20 import org.eclipse.swt.SWT;
21 import org.eclipse.swt.events.DisposeListener;
22 import org.eclipse.swt.events.FocusListener;
23 import org.eclipse.swt.events.KeyEvent;
24 import org.eclipse.swt.events.KeyListener;
25 import org.eclipse.swt.events.ModifyEvent;
26 import org.eclipse.swt.events.ModifyListener;
27 import org.eclipse.swt.events.MouseAdapter;
28 import org.eclipse.swt.events.MouseEvent;
29 import org.eclipse.swt.events.MouseMoveListener;
30 import org.eclipse.swt.events.SelectionAdapter;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.events.SelectionListener;
33 import org.eclipse.swt.graphics.Color;
34 import org.eclipse.swt.graphics.FontMetrics;
35 import org.eclipse.swt.graphics.GC;
36 import org.eclipse.swt.graphics.Point;
37 import org.eclipse.swt.graphics.Rectangle;
38 import org.eclipse.swt.layout.GridData;
39 import org.eclipse.swt.layout.GridLayout;
40 import org.eclipse.swt.widgets.Composite;
41 import org.eclipse.swt.widgets.Control;
42 import org.eclipse.swt.widgets.Display;
43 import org.eclipse.swt.widgets.Item;
44 import org.eclipse.swt.widgets.Label;
45 import org.eclipse.swt.widgets.Layout;
46 import org.eclipse.swt.widgets.Menu;
47 import org.eclipse.swt.widgets.MenuItem;
48 import org.eclipse.swt.widgets.Shell;
49 import org.eclipse.swt.widgets.Table;
50 import org.eclipse.swt.widgets.TableItem;
51 import org.eclipse.swt.widgets.Text;
52 import org.eclipse.ui.internal.WorkbenchMessages;
53 import org.eclipse.ui.internal.misc.StringMatcher;
54 import org.eclipse.ui.internal.presentations.defaultpresentation.DefaultTabItem;
55
56 /**
57  * @since 3.0
58  */

59 public abstract class AbstractTableInformationControl {
60
61     /**
62      * The NamePatternFilter selects the elements which match the given string
63      * patterns.
64      */

65     protected class NamePatternFilter extends ViewerFilter {
66
67         public NamePatternFilter() {
68             //no-op
69
}
70
71         /*
72          * (non-Javadoc) Method declared on ViewerFilter.
73          */

74         public boolean select(Viewer viewer, Object JavaDoc parentElement,
75                 Object JavaDoc element) {
76             StringMatcher matcher = getMatcher();
77             if (matcher == null || !(viewer instanceof TableViewer)) {
78                 return true;
79             }
80             TableViewer tableViewer = (TableViewer) viewer;
81
82             String JavaDoc matchName = ((ILabelProvider) tableViewer.getLabelProvider())
83                     .getText(element);
84             
85             if(matchName == null) {
86                 return false;
87             }
88             // A dirty editor's label will start with dirty prefix, this prefix
89
// should not be taken in consideration when matching with a pattern
90
String JavaDoc prefix = DefaultTabItem.DIRTY_PREFIX;
91             if (matchName.startsWith(prefix)) {
92                 matchName = matchName.substring(prefix.length());
93             }
94             return matchName != null && matcher.match(matchName);
95         }
96     }
97
98     private static class BorderFillLayout extends Layout {
99
100         /** The border widths. */
101         final int fBorderSize;
102
103         /**
104          * Creates a fill layout with a border.
105          */

106         public BorderFillLayout(int borderSize) {
107             if (borderSize < 0) {
108                 throw new IllegalArgumentException JavaDoc();
109             }
110             fBorderSize = borderSize;
111         }
112
113         /**
114          * Returns the border size.
115          */

116         public int getBorderSize() {
117             return fBorderSize;
118         }
119
120         /*
121          * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite,
122          * int, int, boolean)
123          */

124         protected Point computeSize(Composite composite, int wHint, int hHint,
125                 boolean flushCache) {
126
127             Control[] children = composite.getChildren();
128             Point minSize = new Point(0, 0);
129
130             if (children != null) {
131                 for (int i = 0; i < children.length; i++) {
132                     Point size = children[i].computeSize(wHint, hHint,
133                             flushCache);
134                     minSize.x = Math.max(minSize.x, size.x);
135                     minSize.y = Math.max(minSize.y, size.y);
136                 }
137             }
138
139             minSize.x += fBorderSize * 2 + RIGHT_MARGIN;
140             minSize.y += fBorderSize * 2;
141
142             return minSize;
143         }
144
145         /*
146          * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite,
147          * boolean)
148          */

149         protected void layout(Composite composite, boolean flushCache) {
150
151             Control[] children = composite.getChildren();
152             Point minSize = new Point(composite.getClientArea().width,
153                     composite.getClientArea().height);
154
155             if (children != null) {
156                 for (int i = 0; i < children.length; i++) {
157                     Control child = children[i];
158                     child.setSize(minSize.x - fBorderSize * 2, minSize.y
159                             - fBorderSize * 2);
160                     child.setLocation(fBorderSize, fBorderSize);
161                 }
162             }
163         }
164     }
165
166     /** Border thickness in pixels. */
167     private static final int BORDER = 1;
168
169     /** Right margin in pixels. */
170     private static final int RIGHT_MARGIN = 3;
171
172     /** The control's shell */
173     private Shell fShell;
174
175     /** The composite */
176     protected Composite fComposite;
177
178     /** The control's text widget */
179     private Text fFilterText;
180
181     /** The control's table widget */
182     private TableViewer fTableViewer;
183
184     /** The control width constraint */
185     //private int fMaxWidth= -1;
186
/** The control height constraint */
187     //private int fMaxHeight= -1;
188
/** The current string matcher */
189     private StringMatcher fStringMatcher;
190
191     /**
192      * Creates an information control with the given shell as parent. The given
193      * styles are applied to the shell and the table widget.
194      *
195      * @param parent
196      * the parent shell
197      * @param shellStyle
198      * the additional styles for the shell
199      * @param controlStyle
200      * the additional styles for the control
201      */

202     public AbstractTableInformationControl(Shell parent, int shellStyle,
203             int controlStyle) {
204         fShell = new Shell(parent, shellStyle);
205         Display display = fShell.getDisplay();
206         fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
207
208         // Composite for filter text and viewer
209

210         fComposite = new Composite(fShell, SWT.RESIZE);
211         GridLayout layout = new GridLayout(1, false);
212         fComposite.setLayout(layout);
213         // fComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
214

215         createFilterText(fComposite);
216
217         fTableViewer = createTableViewer(fComposite, controlStyle);
218
219         final Table table = fTableViewer.getTable();
220         table.addKeyListener(new KeyListener() {
221             public void keyPressed(KeyEvent e) {
222                 if (e.character == SWT.ESC) {
223                     dispose();
224                 } else if (e.character == SWT.DEL) {
225                     removeSelectedItems();
226                     e.character = SWT.NONE;
227                     e.doit = false;
228                 }
229             }
230
231             public void keyReleased(KeyEvent e) {
232                 // do nothing
233
}
234         });
235
236         table.addSelectionListener(new SelectionListener() {
237             public void widgetSelected(SelectionEvent e) {
238                 // do nothing;
239
}
240
241             public void widgetDefaultSelected(SelectionEvent e) {
242                 gotoSelectedElement();
243             }
244         });
245
246         /*
247          * Bug in GTK, see SWT bug: 62405 Editor drop down performance slow on
248          * Linux-GTK on mouse move.
249          * Rather then removing the support altogether this feature has been
250          * worked around for GTK only as we expect that newer versions of GTK
251          * will no longer exhibit this quality and we will be able to have the
252          * desired support running on all platforms. See
253          * comment https://bugs.eclipse.org/bugs/show_bug.cgi?id=62405#c22
254          * TODO: remove this code once bug 62405 is fixed for the mainstream GTK
255          * version
256          */

257         final int ignoreEventCount = Platform.getWS().equals(Platform.WS_GTK) ? 4 : 1;
258     
259         table.addMouseMoveListener(new MouseMoveListener() {
260             TableItem fLastItem = null;
261             int lastY = 0;
262             int itemHeightdiv4 = table.getItemHeight() / 4;
263             int tableHeight = table.getBounds().height;
264             Point tableLoc = table.toDisplay(0,0);
265             int divCount = 0;
266             public void mouseMove(MouseEvent e) {
267                 if (divCount == ignoreEventCount) {
268                     divCount = 0;
269                 }
270                 if (table.equals(e.getSource()) & ++divCount == ignoreEventCount) {
271                     Object JavaDoc o = table.getItem(new Point(e.x, e.y));
272                     if (o instanceof TableItem && lastY != e.y) {
273                         lastY = e.y;
274                         if (!o.equals(fLastItem)) {
275                             fLastItem = (TableItem) o;
276                             table.setSelection(new TableItem[] { fLastItem });
277                         } else if (e.y < itemHeightdiv4) {
278                             // Scroll up
279
Item item = fTableViewer.scrollUp(e.x + tableLoc.x, e.y + tableLoc.y);
280                             if (item instanceof TableItem) {
281                                 fLastItem = (TableItem) item;
282                                 table.setSelection(new TableItem[] { fLastItem });
283                             }
284                         } else if (e.y > tableHeight - itemHeightdiv4) {
285                             // Scroll down
286
Item item = fTableViewer.scrollDown(e.x + tableLoc.x, e.y + tableLoc.y);
287                             if (item instanceof TableItem) {
288                                 fLastItem = (TableItem) item;
289                                 table.setSelection(new TableItem[] { fLastItem });
290                             }
291                         }
292                     }
293                 }
294             }
295         });
296     
297         table.addMouseListener(new MouseAdapter() {
298             public void mouseUp(MouseEvent e) {
299                 if (table.getSelectionCount() < 1) {
300                     return;
301                 }
302
303                 if (e.button == 1) {
304                     if (table.equals(e.getSource())) {
305                         Object JavaDoc o = table.getItem(new Point(e.x, e.y));
306                         TableItem selection = table.getSelection()[0];
307                         if (selection.equals(o)) {
308                             gotoSelectedElement();
309                         }
310                     }
311                 }
312                 if (e.button == 3) {
313                     TableItem tItem = fTableViewer.getTable().getItem(
314                             new Point(e.x, e.y));
315                     if (tItem != null) {
316                         Menu menu = new Menu(fTableViewer.getTable());
317                         MenuItem mItem = new MenuItem(menu, SWT.NONE);
318                         mItem.setText(WorkbenchMessages.PartPane_close);
319                         mItem.addSelectionListener(new SelectionAdapter() {
320                             public void widgetSelected(
321                                     SelectionEvent selectionEvent) {
322                                 removeSelectedItems();
323                             }
324                         });
325                         menu.setVisible(true);
326                     }
327                 }
328             }
329         });
330
331         int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
332         fShell.setLayout(new BorderFillLayout(border));
333
334         setInfoSystemColor();
335         installFilter();
336     }
337
338     /**
339      * Removes the selected items from the list and closes their corresponding tabs
340      * Selects the next item in the list or disposes it if its presentation is disposed
341      */

342     protected void removeSelectedItems() {
343         int selInd = fTableViewer.getTable().getSelectionIndex();
344         if (deleteSelectedElements()) {
345             return;
346         }
347         fTableViewer.refresh();
348         if (selInd >= fTableViewer.getTable().getItemCount()) {
349             selInd = fTableViewer.getTable().getItemCount() - 1;
350         }
351         if (selInd >= 0) {
352             fTableViewer.getTable().setSelection(selInd);
353         }
354     }
355
356     protected abstract TableViewer createTableViewer(Composite parent, int style);
357
358     public TableViewer getTableViewer() {
359         return fTableViewer;
360     }
361
362     protected Text createFilterText(Composite parent) {
363         fFilterText = new Text(parent, SWT.NONE);
364
365         GridData data = new GridData();
366         GC gc = new GC(parent);
367         gc.setFont(parent.getFont());
368         FontMetrics fontMetrics = gc.getFontMetrics();
369         gc.dispose();
370
371         data.heightHint = org.eclipse.jface.dialogs.Dialog
372                 .convertHeightInCharsToPixels(fontMetrics, 1);
373         data.horizontalAlignment = GridData.FILL;
374         data.verticalAlignment = GridData.BEGINNING;
375         fFilterText.setLayoutData(data);
376
377         fFilterText.addKeyListener(new KeyListener() {
378             public void keyPressed(KeyEvent e) {
379                 if (e.keyCode == 0x0D) {
380                     gotoSelectedElement();
381                 }
382                 if (e.keyCode == SWT.ARROW_DOWN) {
383                     fTableViewer.getTable().setFocus();
384                     fTableViewer.getTable().setSelection(0);
385                 }
386                 if (e.keyCode == SWT.ARROW_UP) {
387                     fTableViewer.getTable().setFocus();
388                     fTableViewer.getTable().setSelection(
389                             fTableViewer.getTable().getItemCount() - 1);
390                 }
391                 if (e.character == 0x1B) {
392                     dispose();
393                 }
394             }
395
396             public void keyReleased(KeyEvent e) {
397                 // do nothing
398
}
399         });
400
401         // Horizontal separator line
402
Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL
403                 | SWT.LINE_DOT);
404         separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
405
406         return fFilterText;
407     }
408
409     private void setInfoSystemColor() {
410         Display display = fShell.getDisplay();
411         setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
412         setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
413     }
414
415     private void installFilter() {
416         fFilterText.setText(""); //$NON-NLS-1$
417

418         fFilterText.addModifyListener(new ModifyListener() {
419             public void modifyText(ModifyEvent e) {
420                 String JavaDoc text = ((Text) e.widget).getText();
421                 int length = text.length();
422                 if (length > 0 && text.charAt(length - 1) != '*') {
423                     text = text + '*';
424                 }
425                 setMatcherString(text);
426             }
427         });
428     }
429
430     /**
431      * The string matcher has been modified. The default implementation
432      * refreshes the view and selects the first macthed element
433      */

434     protected void stringMatcherUpdated() {
435         // refresh viewer to refilter
436
fTableViewer.getControl().setRedraw(false);
437         fTableViewer.refresh();
438         selectFirstMatch();
439         fTableViewer.getControl().setRedraw(true);
440     }
441
442     /**
443      * Sets the patterns to filter out for the receiver.
444      * <p>
445      * The following characters have special meaning: ? => any character * =>
446      * any string
447      * </p>
448      */

449     protected void setMatcherString(String JavaDoc pattern) {
450         if (pattern.length() == 0) {
451             fStringMatcher = null;
452         } else {
453             boolean ignoreCase = pattern.toLowerCase().equals(pattern);
454             fStringMatcher = new StringMatcher(pattern, ignoreCase, false);
455         }
456         stringMatcherUpdated();
457     }
458
459     protected StringMatcher getMatcher() {
460         return fStringMatcher;
461     }
462
463     /**
464      * Implementers can modify
465      */

466     protected Object JavaDoc getSelectedElement() {
467         return ((IStructuredSelection) fTableViewer.getSelection())
468                 .getFirstElement();
469     }
470
471     /**
472      * Implementers can modify
473      */

474     protected IStructuredSelection getSelectedElements() {
475         return (IStructuredSelection) fTableViewer.getSelection();
476     }
477
478     protected abstract void gotoSelectedElement();
479
480     /**
481      * Delete all selected elements.
482      *
483      * @return <code>true</code> if there are no elements left after deletion.
484      */

485     protected abstract boolean deleteSelectedElements();
486
487     /**
488      * Selects the first element in the table which matches the current filter
489      * pattern.
490      */

491     protected void selectFirstMatch() {
492         Table table = fTableViewer.getTable();
493         Object JavaDoc element = findElement(table.getItems());
494         if (element != null) {
495             fTableViewer.setSelection(new StructuredSelection(element), true);
496         } else {
497             fTableViewer.setSelection(StructuredSelection.EMPTY);
498         }
499     }
500
501     private Object JavaDoc findElement(TableItem[] items) {
502         ILabelProvider labelProvider = (ILabelProvider) fTableViewer
503                 .getLabelProvider();
504         for (int i = 0; i < items.length; i++) {
505             Object JavaDoc element = items[i].getData();
506             if (fStringMatcher == null) {
507                 return element;
508             }
509
510             if (element != null) {
511                 String JavaDoc label = labelProvider.getText(element);
512                 if(label == null) {
513                     return null;
514                 }
515                 // remove the dirty prefix from the editor's label
516
String JavaDoc prefix = DefaultTabItem.DIRTY_PREFIX;
517                 if (label.startsWith(prefix)) {
518                     label = label.substring(prefix.length());
519                 }
520                 if (fStringMatcher.match(label)) {
521                     return element;
522                 }
523             }
524         }
525         return null;
526     }
527
528     public abstract void setInput(Object JavaDoc information);
529
530     protected void inputChanged(Object JavaDoc newInput, Object JavaDoc newSelection) {
531         fFilterText.setText(""); //$NON-NLS-1$
532
fTableViewer.setInput(newInput);
533
534         // Resize the table's height accordingly to the new input
535
Table viewerTable = fTableViewer.getTable();
536         Point tableSize = viewerTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
537         int tableMaxHeight = fComposite.getDisplay().getBounds().height / 2;
538         // removes padding if necessary
539
int tableHeight = (tableSize.y <= tableMaxHeight) ? tableSize.y
540                 - viewerTable.getItemHeight() - viewerTable.getItemHeight() / 2
541                 : tableMaxHeight;
542         ((GridData) viewerTable.getLayoutData()).heightHint = tableHeight;
543         Point fCompSize = fComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
544         fComposite.setSize(fCompSize);
545         fComposite.getShell().setSize(fCompSize);
546     }
547
548     public void setVisible(boolean visible) {
549         fShell.setVisible(visible);
550     }
551
552     public void dispose() {
553         if (fShell != null) {
554             if (!fShell.isDisposed()) {
555                 fShell.dispose();
556             }
557             fShell = null;
558             fTableViewer = null;
559             fComposite = null;
560             fFilterText = null;
561         }
562     }
563
564     public boolean hasContents() {
565         return fTableViewer != null && fTableViewer.getInput() != null;
566     }
567
568     public void setSizeConstraints(int maxWidth, int maxHeight) {
569         //fMaxWidth= maxWidth;
570
//fMaxHeight= maxHeight;
571
}
572
573     public Point computeSizeHint() {
574         return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
575     }
576
577     public void setLocation(Point location) {
578         Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
579         Point textLocation = fComposite.getLocation();
580         location.x += trim.x - textLocation.x;
581         location.y += trim.y - textLocation.y;
582         fShell.setLocation(location);
583     }
584
585     public void setSize(int width, int height) {
586         fShell.setSize(width, height);
587     }
588
589     public void addDisposeListener(DisposeListener listener) {
590         fShell.addDisposeListener(listener);
591     }
592
593     public void removeDisposeListener(DisposeListener listener) {
594         fShell.removeDisposeListener(listener);
595     }
596
597     public void setForegroundColor(Color foreground) {
598         fTableViewer.getTable().setForeground(foreground);
599         fFilterText.setForeground(foreground);
600         fComposite.setForeground(foreground);
601     }
602
603     public void setBackgroundColor(Color background) {
604         fTableViewer.getTable().setBackground(background);
605         fFilterText.setBackground(background);
606         fComposite.setBackground(background);
607     }
608
609     public boolean isFocusControl() {
610         return fTableViewer.getControl().isFocusControl()
611                 || fFilterText.isFocusControl();
612     }
613
614     public void setFocus() {
615         fShell.forceFocus();
616         fFilterText.setFocus();
617     }
618
619     public void addFocusListener(FocusListener listener) {
620         fShell.addFocusListener(listener);
621     }
622
623     public void removeFocusListener(FocusListener listener) {
624         fShell.removeFocusListener(listener);
625     }
626 }
627
Popular Tags