KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > tags > TagSelectionArea


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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  * Brock Janiczak <brockj@tpg.com.au> - Bug 182267 "Add Date..." button shouldn't be visible in merge wizard
11  *******************************************************************************/

12 package org.eclipse.team.internal.ccvs.ui.tags;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Arrays JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18
19 import org.eclipse.jface.action.*;
20 import org.eclipse.jface.dialogs.Dialog;
21 import org.eclipse.jface.operation.IRunnableContext;
22 import org.eclipse.jface.viewers.*;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.*;
26 import org.eclipse.swt.layout.GridData;
27 import org.eclipse.swt.widgets.*;
28 import org.eclipse.team.internal.ccvs.core.CVSTag;
29 import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
30 import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
31 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
32 import org.eclipse.team.internal.ccvs.ui.repo.NewDateTagAction;
33 import org.eclipse.team.internal.ccvs.ui.repo.RepositoryManager;
34 import org.eclipse.team.internal.ccvs.ui.tags.TagSourceWorkbenchAdapter.ProjectElementComparator;
35 import org.eclipse.team.internal.ui.PixelConverter;
36 import org.eclipse.team.internal.ui.SWTUtils;
37 import org.eclipse.team.internal.ui.actions.TeamAction;
38 import org.eclipse.team.internal.ui.dialogs.DialogArea;
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.model.WorkbenchContentProvider;
41 import org.eclipse.ui.model.WorkbenchLabelProvider;
42 import org.eclipse.ui.part.PageBook;
43
44 /**
45  * A dialog area that displays a list of tags for selection and supports
46  * filtering of the displayed tags.
47  */

48 public class TagSelectionArea extends DialogArea {
49     
50     private static int COLUMN_TRIM = "carbon".equals(SWT.getPlatform()) ? 24 : 3; //$NON-NLS-1$
51

52     private static int ICON_WIDTH = 40;
53     
54     /*
55      * Please see bug 184660
56      */

57     private static final int SAFETY_MARGIN = 50;
58     
59     /*
60      * Property constant which identifies the selected tag or
61      * null if no tag is selected
62      */

63     public static final String JavaDoc SELECTED_TAG = "selectedTag"; //$NON-NLS-1$
64

65     /*
66      * Property constant which indicates that a tag has been selected in such
67      * a way as to indicate that this is the desired tag (e.g double-click)
68      */

69     public static final String JavaDoc OPEN_SELECTED_TAG = "openSelectedTag"; //$NON-NLS-1$
70

71     /*
72      * Constants used to configure which tags are shown
73      */

74     public static final int INCLUDE_HEAD_TAG = TagSourceWorkbenchAdapter.INCLUDE_HEAD_TAG;
75     public static final int INCLUDE_BASE_TAG = TagSourceWorkbenchAdapter.INCLUDE_BASE_TAG;
76     public static final int INCLUDE_BRANCHES = TagSourceWorkbenchAdapter.INCLUDE_BRANCHES;
77     public static final int INCLUDE_VERSIONS = TagSourceWorkbenchAdapter.INCLUDE_VERSIONS;
78     public static final int INCLUDE_DATES = TagSourceWorkbenchAdapter.INCLUDE_DATES;
79     public static final int INCLUDE_ALL_TAGS = TagSourceWorkbenchAdapter.INCLUDE_ALL_TAGS;
80     
81     private String JavaDoc tagAreaLabel;
82     private final int includeFlags;
83     private CVSTag selection;
84     private String JavaDoc helpContext;
85     private Text filterText;
86     private TagSource tagSource;
87     private final Shell shell;
88     private TagRefreshButtonArea tagRefreshArea;
89     private final TagSource.ITagSourceChangeListener listener = new TagSource.ITagSourceChangeListener() {
90         public void tagsChanged(TagSource source) {
91             Shell shell = getShell();
92             if (!shell.isDisposed()) {
93                 shell.getDisplay().syncExec(new Runnable JavaDoc() {
94                     public void run() {
95                         refresh();
96                     }
97                 });
98             }
99         }
100     };
101     private final DisposeListener disposeListener = new DisposeListener() {
102         public void widgetDisposed(DisposeEvent e) {
103             if (tagSource != null)
104                 tagSource.removeListener(listener);
105         }
106     };
107
108     private PageBook switcher;
109     private TreeViewer tagTree;
110     private TableViewer tagTable;
111     private boolean treeVisible = true;
112     private boolean includeFilterInputArea = true;
113     private String JavaDoc filterPattern = ""; //$NON-NLS-1$
114

115     private IRunnableContext context;
116     
117     public TagSelectionArea(Shell shell, TagSource tagSource, int includeFlags, String JavaDoc helpContext) {
118         this.shell = shell;
119         this.includeFlags = includeFlags;
120         this.helpContext = helpContext;
121         this.tagSource = tagSource;
122         setSelection(null);
123     }
124
125     /* (non-Javadoc)
126      * @see org.eclipse.team.internal.ui.dialogs.DialogArea#createArea(org.eclipse.swt.widgets.Composite)
127      */

128     public void createArea(Composite parent) {
129         initializeDialogUnits(parent);
130         Dialog.applyDialogFont(parent);
131         final PixelConverter converter= new PixelConverter(parent);
132         
133         // Create a composite for the entire area
134
Composite composite= new Composite(parent, SWT.NONE);
135         composite.setLayoutData(SWTUtils.createHVFillGridData());
136         composite.setLayout(SWTUtils.createGridLayout(1, converter, SWTUtils.MARGINS_NONE));
137         
138         // Add F1 help
139
if (helpContext != null) {
140             PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, helpContext);
141         }
142         
143         // Create the tree area and refresh buttons with the possibility to add stuff in between
144
createTagDisplayArea(composite);
145         createCustomArea(composite);
146         createRefreshButtons(composite);
147         
148         Dialog.applyDialogFont(parent);
149         updateTagDisplay(true);
150     }
151
152     private void createTagDisplayArea(Composite parent) {
153         Composite inner = createGrabbingComposite(parent, 1);
154         if (isIncludeFilterInputArea()) {
155             createFilterInput(inner);
156             createWrappingLabel(inner, CVSUIMessages.TagSelectionArea_0, 1);
157         } else {
158             createWrappingLabel(inner, NLS.bind(CVSUIMessages.TagSelectionArea_1, new String JavaDoc[] { getTagAreaLabel() }), 1);
159         }
160         switcher = new PageBook(inner, SWT.NONE);
161         GridData gridData = new GridData(GridData.FILL_BOTH);
162         gridData.heightHint = 0;
163         gridData.widthHint = 0;
164         switcher.setLayoutData(gridData);
165         tagTree = createTree(switcher);
166         tagTable = createTable(switcher);
167     }
168
169     private void createFilterInput(Composite inner) {
170         createWrappingLabel(inner, NLS.bind(CVSUIMessages.TagSelectionArea_2, new String JavaDoc[] { getTagAreaLabel() }), 1);
171         filterText = createText(inner, 1);
172         filterText.addModifyListener(new ModifyListener() {
173             public void modifyText(ModifyEvent e) {
174                 setFilter(filterText.getText());
175             }
176         });
177         filterText.addKeyListener(new KeyListener() {
178             public void keyPressed(KeyEvent e) {
179                 if (e.keyCode == SWT.ARROW_DOWN && e.stateMask == 0) {
180                     tagTable.getControl().setFocus();
181                 }
182             }
183             public void keyReleased(KeyEvent e) {
184                 // Ignore
185
}
186         });
187     }
188
189     /**
190      * Return the label that should be used for the tag area.
191      * It should not have any trailing punctuations as the tag area
192      * may position it differently depending on whether the filter
193      * text input is included in the area.
194      * @return the tag area label
195      */

196     public String JavaDoc getTagAreaLabel() {
197         if (tagAreaLabel == null)
198             tagAreaLabel = CVSUIMessages.TagSelectionArea_3;
199         return tagAreaLabel;
200     }
201
202     /**
203      * Set the label that should be used for the tag area.
204      * It should not have any trailing punctuations as the tag area
205      * may position it differently depending on whether the filter
206      * text input is included in the area.
207      * @param tagAreaLabel the tag area label
208      */

209     public void setTagAreaLabel(String JavaDoc tagAreaLabel) {
210         this.tagAreaLabel = tagAreaLabel;
211     }
212     
213     /**
214      * Update the tag display to show the tags that match the
215      * include flags and the filter entered by the user.
216      */

217     protected void updateTagDisplay(boolean firstTime) {
218         String JavaDoc filter = getFilterString();
219         if ((filter != null && filter.length() > 0) || isTableOnly()) {
220             // Show the table and filter it accordingly
221
try {
222                 switcher.setRedraw(false);
223                 treeVisible = false;
224                 switcher.showPage(tagTable.getControl());
225                 FilteredTagList list = (FilteredTagList)tagTable.getInput();
226                 list.setPattern(filter);
227                 tagTable.refresh();
228                 int maxWidth = getMaxWidth(list.getChildren(null));
229                 if (maxWidth > 0) {
230                     maxWidth = maxWidth + ICON_WIDTH + COLUMN_TRIM + SAFETY_MARGIN; /* space for the tag icon */
231                     tagTable.getTable().getColumn(0).setWidth(maxWidth);
232                 }
233                 if (filterText == null || filter == null || filter.length() == 0) {
234                     setSelection(selection);
235                 } else {
236                     // Only set the top selection if there is a filter from the filter text
237
// of this area. This is done to avoid selection loops
238
selectTopElement();
239                 }
240             } finally {
241                 switcher.setRedraw(true);
242             }
243         } else {
244             // Show the tree
245
if (!isTreeVisible() || firstTime) {
246                 try {
247                     switcher.setRedraw(false);
248                     treeVisible = true;
249                     switcher.showPage(tagTree.getControl());
250                     tagTree.refresh();
251                     setSelection(selection);
252                 } finally {
253                     switcher.setRedraw(true);
254                 }
255             }
256         }
257     }
258     
259     private int getMaxWidth(Object JavaDoc[] children) {
260         PixelConverter converter = new PixelConverter(tagTable.getTable());
261         int maxWidth = 0;
262         for (int i = 0; i < children.length; i++) {
263             Object JavaDoc object = children[i];
264             if (object instanceof TagElement) {
265                 TagElement tag = (TagElement) object;
266                 int width = tag.getTag().getName().length();
267                 if (width > maxWidth) {
268                     maxWidth = width;
269                 }
270             }
271         }
272         return converter.convertWidthInCharsToPixels(maxWidth);
273     }
274
275     /**
276      * Return whether only a table should be used
277      * @return whether only a table should be used
278      */

279     protected boolean isTableOnly() {
280         return (includeFlags == INCLUDE_VERSIONS) || (includeFlags == INCLUDE_BRANCHES);
281     }
282
283     private String JavaDoc getFilterString() {
284         return filterPattern;
285     }
286
287     /*
288      * Select the top element in the tag table
289      */

290     private void selectTopElement() {
291         if (tagTable.getTable().getItemCount() > 0) {
292             TableItem item = tagTable.getTable().getItem(0);
293             tagTable.getTable().setSelection(new TableItem[] { item });
294             tagTable.setSelection(tagTable.getSelection());
295         }
296     }
297
298     private FilteredTagList createFilteredInput() {
299         return new FilteredTagList(tagSource, TagSource.convertIncludeFlaqsToTagTypes(includeFlags));
300     }
301     
302     private Text createText(Composite parent, int horizontalSpan) {
303         Text text = new Text(parent, SWT.SEARCH);
304         GridData data = new GridData();
305         data.horizontalSpan = horizontalSpan;
306         data.horizontalAlignment = GridData.FILL;
307         data.grabExcessHorizontalSpace = true;
308         data.widthHint= 0;
309         text.setLayoutData(data);
310         return text;
311     }
312
313     protected void createRefreshButtons(Composite parent) {
314         tagSource.addListener(listener);
315         parent.addDisposeListener(disposeListener);
316         Listener listener = null;
317         if ((includeFlags & TagSourceWorkbenchAdapter.INCLUDE_DATES) != 0) {
318             listener = new Listener() {
319                 public void handleEvent(Event event) {
320                     CVSTag dateTag = NewDateTagAction.getDateTag(getShell(), getLocation());
321                     addDateTag(dateTag);
322                 }
323             };
324         }
325         tagRefreshArea = new TagRefreshButtonArea(shell, tagSource, listener);
326         if (context != null)
327             tagRefreshArea.setRunnableContext(context);
328         tagRefreshArea.createArea(parent);
329     }
330
331     protected void createTreeMenu(TreeViewer tagTree) {
332         if ((includeFlags & TagSourceWorkbenchAdapter.INCLUDE_DATES) != 0) {
333             // Create the popup menu
334
MenuManager menuMgr = new MenuManager();
335             Tree tree = tagTree.getTree();
336             Menu menu = menuMgr.createContextMenu(tree);
337             menuMgr.addMenuListener(new IMenuListener() {
338                 public void menuAboutToShow(IMenuManager manager) {
339                     addMenuItemActions(manager);
340                 }
341     
342             });
343             menuMgr.setRemoveAllWhenShown(true);
344             tree.setMenu(menu);
345         }
346     }
347
348     /**
349      * Create aq custom area that is below the tag selection area but above the refresh busson group
350      * @param parent
351      */

352     protected void createCustomArea(Composite parent) {
353         // No default custom area
354
}
355     
356     protected TreeViewer createTree(Composite parent) {
357         Tree tree = new Tree(parent, SWT.SINGLE | SWT.BORDER);
358         GridData data = new GridData(GridData.FILL_BOTH);
359         tree.setLayoutData(data);
360         TreeViewer result = new TreeViewer(tree);
361         initialize(result);
362         result.getControl().addKeyListener(new KeyListener() {
363             public void keyPressed(KeyEvent event) {
364                 handleKeyPressed(event);
365             }
366             public void keyReleased(KeyEvent event) {
367                 handleKeyReleased(event);
368             }
369         });
370         result.setInput(createUnfilteredInput());
371         createTreeMenu(result);
372         return result;
373     }
374
375     protected TableViewer createTable(Composite parent) {
376         Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
377         GridData data = new GridData(GridData.FILL_BOTH);
378         table.setLayoutData(data);
379         TableLayout layout = new TableLayout();
380         layout.addColumnData(new ColumnWeightData(100));
381         table.setLayout(layout);
382         new TableColumn(table, SWT.NONE);
383         TableViewer viewer = new TableViewer(table);
384         initialize(viewer);
385         viewer.setInput(createFilteredInput());
386         return viewer;
387
388     }
389
390     private void initialize(StructuredViewer viewer) {
391         viewer.setContentProvider(new WorkbenchContentProvider());
392         viewer.setLabelProvider(new WorkbenchLabelProvider());
393         viewer.setComparator(new ProjectElementComparator());
394         viewer.addSelectionChangedListener(new ISelectionChangedListener() {
395             public void selectionChanged(SelectionChangedEvent event) {
396                 handleSelectionChange();
397             }
398         });
399         // select and close on double click
400
// To do: use defaultselection instead of double click
401
viewer.getControl().addMouseListener(new MouseAdapter() {
402             public void mouseDoubleClick(MouseEvent e) {
403                 CVSTag tag = internalGetSelectedTag();
404                 if (tag != null) {
405                     firePropertyChangeChange(OPEN_SELECTED_TAG, null, tag);
406                 }
407             }
408         });
409     }
410
411     private Object JavaDoc createUnfilteredInput() {
412         return TagSourceWorkbenchAdapter.createInput(tagSource, includeFlags);
413     }
414
415     public void handleKeyPressed(KeyEvent event) {
416         if (event.character == SWT.DEL && event.stateMask == 0) {
417             deleteDateTag();
418         }
419     }
420     private void deleteDateTag() {
421         TagElement[] selectedDateTagElements = getSelectedDateTagElement();
422         if (selectedDateTagElements.length == 0) return;
423         for(int i = 0; i < selectedDateTagElements.length; i++){
424             RepositoryManager mgr = CVSUIPlugin.getPlugin().getRepositoryManager();
425             CVSTag tag = selectedDateTagElements[i].getTag();
426             if(tag.getType() == CVSTag.DATE){
427                 mgr.removeDateTag(getLocation(),tag);
428             }
429         }
430         tagTree.refresh();
431         handleSelectionChange();
432     }
433     
434     /**
435      * Returns the selected date tag elements
436      */

437     private TagElement[] getSelectedDateTagElement() {
438         ArrayList JavaDoc dateTagElements = null;
439         IStructuredSelection selection = (IStructuredSelection)tagTree.getSelection();
440         if (selection!=null && !selection.isEmpty()) {
441             dateTagElements = new ArrayList JavaDoc();
442             Iterator JavaDoc elements = selection.iterator();
443             while (elements.hasNext()) {
444                 Object JavaDoc next = TeamAction.getAdapter(elements.next(), TagElement.class);
445                 if (next instanceof TagElement) {
446                     if(((TagElement)next).getTag().getType() == CVSTag.DATE){
447                         dateTagElements.add(next);
448                     }
449                 }
450             }
451         }
452         if (dateTagElements != null && !dateTagElements.isEmpty()) {
453             TagElement[] result = new TagElement[dateTagElements.size()];
454             dateTagElements.toArray(result);
455             return result;
456         }
457         return new TagElement[0];
458     }
459     private void addDateTag(CVSTag tag){
460         if(tag == null) return;
461         List JavaDoc dateTags = new ArrayList JavaDoc();
462         ICVSRepositoryLocation location = getLocation();
463         dateTags.addAll(Arrays.asList(CVSUIPlugin.getPlugin().getRepositoryManager().getDateTags(location)));
464         if(!dateTags.contains( tag)){
465             CVSUIPlugin.getPlugin().getRepositoryManager().addDateTag(location, tag);
466         }
467         try {
468             tagTree.getControl().setRedraw(false);
469             tagTree.refresh();
470             setSelection(tag);
471         } finally {
472             tagTree.getControl().setRedraw(true);
473         }
474         handleSelectionChange();
475     }
476     private void addMenuItemActions(IMenuManager manager) {
477         manager.add(new Action(CVSUIMessages.TagSelectionDialog_0) {
478             public void run() {
479                 CVSTag dateTag = NewDateTagAction.getDateTag(getShell(), getLocation());
480                 addDateTag(dateTag);
481             }
482         });
483         if(getSelectedDateTagElement().length > 0){
484             manager.add(new Action(CVSUIMessages.TagSelectionDialog_1) {
485                 public void run() {
486                     deleteDateTag();
487                 }
488             });
489         }
490     }
491
492     protected void handleKeyReleased(KeyEvent event) {
493     }
494     
495     /**
496      * handle a selection change event from the visible tag display
497      * (which could be either the table or the tree).
498      */

499     protected void handleSelectionChange() {
500         CVSTag newSelection = internalGetSelectedTag();
501         if (selection != null && newSelection != null && selection.equals(newSelection)) {
502             // the selection hasn't change so return
503
return;
504         }
505         CVSTag oldSelection = selection;
506         selection = newSelection;
507         firePropertyChangeChange(SELECTED_TAG, oldSelection, selection);
508     }
509     
510     private CVSTag internalGetSelectedTag() {
511         IStructuredSelection selection;
512         if (isTreeVisible()) {
513             selection = (IStructuredSelection)tagTree.getSelection();
514         } else {
515             selection = (IStructuredSelection)tagTable.getSelection();
516         }
517         Object JavaDoc o = selection.getFirstElement();
518         if (o instanceof TagElement)
519             return ((TagElement)o).getTag();
520         return null;
521     }
522     
523     private boolean isTreeVisible() {
524         return treeVisible;
525     }
526
527     private ICVSRepositoryLocation getLocation(){
528         return tagSource.getLocation();
529     }
530     public CVSTag getSelection() {
531         return selection;
532     }
533     public Shell getShell() {
534         return shell;
535     }
536
537     /**
538      * Set the focus to the filter text widget
539      */

540     public void setFocus() {
541         if (filterText != null)
542             filterText.setFocus();
543         else if (switcher != null)
544             switcher.setFocus();
545             
546         // Refresh in case tags were added since the last time the area had focus
547
refresh();
548     }
549
550     /**
551      * Select the given tag
552      * @param selectedTag the tag to be selected
553      */

554     public void setSelection(CVSTag selectedTag) {
555         if (isTreeVisible())
556             if (tagTree != null && !tagTree.getControl().isDisposed()) {
557                 // TODO: Hack to instantiate the model before revealing the selection
558
tagTree.expandToLevel(2);
559                 tagTree.collapseAll();
560                 // Reveal the selection
561
tagTree.reveal(new TagElement(selectedTag));
562                 tagTree.setSelection(new StructuredSelection(new TagElement(selectedTag)));
563             }
564         else
565             if (tagTable != null && !tagTable.getControl().isDisposed()) {
566                 tagTable.setSelection(new StructuredSelection(new TagElement(selectedTag)));
567             }
568     }
569
570     /**
571      * Refresh the state of the tag selection area
572      */

573     public void refresh() {
574         if (isTreeVisible()) {
575             if (tagTree != null && !tagTree.getControl().isDisposed()) {
576                 tagTree.refresh();
577             }
578         } else {
579             if (tagTable != null && !tagTable.getControl().isDisposed()) {
580                 tagTable.refresh();
581             }
582         }
583     }
584     
585     public void refreshTagList() {
586         tagRefreshArea.refresh(true);
587     }
588
589     /**
590      * Set the enablement state of the area
591      * @param enabled the enablement state
592      */

593     public void setEnabled(boolean enabled) {
594         if (filterText != null)
595             filterText.setEnabled(enabled);
596         tagTree.getControl().setEnabled(enabled);
597         tagTable.getControl().setEnabled(enabled);
598     }
599     
600     /**
601      * Set the tag source from which the displayed tags are determined
602      * @param tagSource the source of the tags being displayed
603      */

604     public void setTagSource(TagSource tagSource) {
605         if (this.tagSource != null) {
606             this.tagSource.removeListener(listener);
607         }
608         this.tagSource = tagSource;
609         this.tagSource.addListener(listener);
610         tagRefreshArea.setTagSource(this.tagSource);
611         setTreeAndTableInput();
612     }
613
614     private void setTreeAndTableInput() {
615         if (tagTree != null) {
616             tagTree.setInput(createUnfilteredInput());
617         }
618         if (tagTable != null) {
619             tagTable.setInput(createFilteredInput());
620         }
621         
622     }
623
624     /**
625      * Set whether the input filter text is to be included in the tag selection area.
626      * If excluded, clientscan still set the filter text directly using
627      * <code>setFilter</code>.
628      * @param include whether filter text input should be included
629      */

630     public void setIncludeFilterInputArea(boolean include) {
631         includeFilterInputArea = include;
632     }
633     
634     /**
635      * Return whether the input filter text is to be included in the tag selection area.
636      * If excluded, clientscan still set the filter text directly using
637      * <code>setFilter</code>.
638      * @return whether filter text input should be included
639      */

640     public boolean isIncludeFilterInputArea() {
641         return includeFilterInputArea;
642     }
643
644     /**
645      * Set the text used to filter the tag list.
646      * @param filter the filter pattern
647      */

648     public void setFilter(String JavaDoc filter) {
649         this.filterPattern = filter;
650         updateTagDisplay(false);
651     }
652     
653     public void setRunnableContext(IRunnableContext context) {
654         this.context = context;
655         if (tagRefreshArea != null)
656             tagRefreshArea.setRunnableContext(context);
657     }
658 }
659
Popular Tags