001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Sebastian Davids <sdavids@gmx.de>
011: * - Fix for Bug 109361 [Markers] Multiselection in problems view yields invalid status message
012: *******************************************************************************/package org.eclipse.ui.views.markers.internal;
013:
014: import com.ibm.icu.text.MessageFormat;
015: import java.util.ArrayList;
016: import java.util.Collection;
017: import java.util.Iterator;
018:
019: import org.eclipse.core.resources.IMarker;
020: import org.eclipse.core.runtime.IProgressMonitor;
021: import org.eclipse.core.runtime.IStatus;
022: import org.eclipse.core.runtime.Status;
023: import org.eclipse.core.runtime.jobs.Job;
024: import org.eclipse.jface.action.Action;
025: import org.eclipse.jface.action.IAction;
026: import org.eclipse.jface.action.IMenuManager;
027: import org.eclipse.jface.action.IToolBarManager;
028: import org.eclipse.jface.action.MenuManager;
029: import org.eclipse.jface.action.Separator;
030: import org.eclipse.jface.commands.ActionHandler;
031: import org.eclipse.jface.dialogs.IDialogSettings;
032: import org.eclipse.jface.viewers.ColumnLayoutData;
033: import org.eclipse.jface.viewers.IStructuredSelection;
034: import org.eclipse.jface.viewers.TableLayout;
035: import org.eclipse.jface.viewers.ViewerComparator;
036: import org.eclipse.osgi.util.NLS;
037: import org.eclipse.swt.widgets.Composite;
038: import org.eclipse.ui.IActionBars;
039: import org.eclipse.ui.IMemento;
040: import org.eclipse.ui.PlatformUI;
041: import org.eclipse.ui.XMLMemento;
042: import org.eclipse.ui.activities.ActivityManagerEvent;
043: import org.eclipse.ui.activities.IActivityManagerListener;
044: import org.eclipse.ui.handlers.IHandlerActivation;
045: import org.eclipse.ui.handlers.IHandlerService;
046: import org.eclipse.ui.internal.ide.IDEInternalPreferences;
047: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
048: import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
049:
050: /**
051: * The ProblemView is the view that displays problem markers.
052: *
053: */
054: public class ProblemView extends MarkerView {
055:
056: private final static String[] ROOT_TYPES = { IMarker.PROBLEM };
057:
058: private final static String TAG_DIALOG_SECTION = "org.eclipse.ui.views.problem"; //$NON-NLS-1$
059:
060: private static final String TAG_SYSTEM_FILTER_ENTRY = "systemFilter";//$NON-NLS-1$
061:
062: private ActionResolveMarker resolveMarkerAction;
063:
064: private IHandlerService handlerService;
065:
066: private IHandlerActivation resolveMarkerHandlerActivation;
067:
068: private IActivityManagerListener activityManagerListener;
069:
070: private IField severityAndMessage = new FieldSeverityAndMessage();
071:
072: private IField folder = new FieldFolder();
073:
074: private IField resource = new FieldResource();
075:
076: private IField lineNumber = new FieldLineNumber();
077:
078: private IField creationTime = new FieldCreationTime();
079:
080: // Add the marker ID so the table sorter won't reduce
081: // errors on the same line bug 82502
082: private static IField id = new FieldId();
083:
084: private class GroupingAction extends Action {
085:
086: IField groupingField;
087:
088: ProblemView problemView;
089:
090: /**
091: * Create a new instance of the receiver.
092: *
093: * @param label
094: * @param field
095: * @param view
096: */
097: public GroupingAction(String label, IField field,
098: ProblemView view) {
099: super (label, IAction.AS_RADIO_BUTTON);
100:
101: groupingField = field;
102: problemView = view;
103: IField categoryField = view.getMarkerAdapter()
104: .getCategorySorter().getCategoryField();
105: if (categoryField == null) {
106: setChecked(groupingField == null);
107: } else {
108: setChecked(categoryField.equals(groupingField));
109: }
110: }
111:
112: /*
113: * (non-Javadoc)
114: *
115: * @see org.eclipse.jface.action.Action#run()
116: */
117: public void run() {
118:
119: if (isChecked()) {
120: Job categoryJob = new Job(
121: MarkerMessages.ProblemView_UpdateCategoryJob) {
122: /*
123: * (non-Javadoc)
124: *
125: * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
126: */
127: protected IStatus run(IProgressMonitor monitor) {
128: try {
129: markerProcessJob.join();
130: } catch (InterruptedException e) {
131: return Status.CANCEL_STATUS;
132: }
133: problemView.selectCategoryField(groupingField,
134: problemView.getMarkerAdapter()
135: .getCategorySorter());
136:
137: getMarkerAdapter().getCategorySorter()
138: .saveState(getDialogSettings());
139: return Status.OK_STATUS;
140: }
141: };
142: categoryJob.setSystem(true);
143: problemView.preserveSelection();
144:
145: IWorkbenchSiteProgressService progressService = getProgressService();
146: if (progressService == null)
147: categoryJob.schedule();
148: else
149: getProgressService().schedule(categoryJob);
150:
151: }
152:
153: }
154: }
155:
156: /**
157: * Return a new instance of the receiver.
158: */
159: public ProblemView() {
160: super ();
161: creationTime.setShowing(false);
162: }
163:
164: /*
165: * (non-Javadoc)
166: *
167: * @see org.eclipse.ui.views.markers.internal.MarkerView#dispose()
168: */
169: public void dispose() {
170: if (resolveMarkerAction != null) {
171: resolveMarkerAction.dispose();
172: }
173: if (resolveMarkerHandlerActivation != null
174: && handlerService != null) {
175: handlerService
176: .deactivateHandler(resolveMarkerHandlerActivation);
177: }
178:
179: PlatformUI.getWorkbench().getActivitySupport()
180: .getActivityManager().removeActivityManagerListener(
181: activityManagerListener);
182: super .dispose();
183: }
184:
185: /*
186: * (non-Javadoc)
187: *
188: * @see org.eclipse.ui.views.markers.internal.TableView#getSortingFields()
189: */
190: protected IField[] getSortingFields() {
191: return new IField[] { severityAndMessage, folder, resource,
192: lineNumber, creationTime,
193: // Add the marker ID so the table sorter won't reduce
194: // errors on the same line bug 82502
195: id };
196: }
197:
198: /*
199: * (non-Javadoc)
200: *
201: * @see org.eclipse.ui.views.markers.internal.TableView#getDialogSettings()
202: */
203: protected IDialogSettings getDialogSettings() {
204: IDialogSettings workbenchSettings = IDEWorkbenchPlugin
205: .getDefault().getDialogSettings();
206: IDialogSettings settings = workbenchSettings
207: .getSection(TAG_DIALOG_SECTION);
208:
209: if (settings == null) {
210: settings = workbenchSettings
211: .addNewSection(TAG_DIALOG_SECTION);
212: }
213:
214: return settings;
215: }
216:
217: /*
218: * (non-Javadoc)
219: *
220: * @see org.eclipse.ui.views.markers.internal.TableView#createActions()
221: */
222: protected void createActions() {
223: super .createActions();
224: propertiesAction = new ActionProblemProperties(this ,
225: getViewer());
226: resolveMarkerAction = new ActionResolveMarker(this , getViewer());
227: }
228:
229: /*
230: * (non-Javadoc)
231: *
232: * @see org.eclipse.ui.views.internal.tableview.TableView#registerGlobalActions(org.eclipse.ui.IActionBars)
233: */
234: protected void registerGlobalActions(IActionBars actionBars) {
235: super .registerGlobalActions(actionBars);
236:
237: String quickFixId = "org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals"; //$NON-NLS-1$
238: resolveMarkerAction.setActionDefinitionId(quickFixId);
239:
240: handlerService = (IHandlerService) getViewSite().getService(
241: IHandlerService.class);
242: if (handlerService != null) {
243: resolveMarkerHandlerActivation = handlerService
244: .activateHandler(quickFixId, new ActionHandler(
245: resolveMarkerAction));
246: }
247: }
248:
249: /*
250: * (non-Javadoc)
251: *
252: * @see org.eclipse.ui.views.markers.internal.MarkerView#fillContextMenuAdditions(org.eclipse.jface.action.IMenuManager)
253: */
254: protected void fillContextMenuAdditions(IMenuManager manager) {
255: manager.add(new Separator());
256: manager.add(resolveMarkerAction);
257: }
258:
259: protected String[] getRootTypes() {
260: return ROOT_TYPES;
261: }
262:
263: /*
264: * (non-Javadoc)
265: *
266: * @see org.eclipse.ui.views.markers.internal.TableView#getAllFields()
267: */
268: protected IField[] getAllFields() {
269:
270: // Add the marker ID so the table sorter won't reduce
271: // errors on the same line bug 82502
272: return new IField[] { severityAndMessage, resource, folder,
273: lineNumber, creationTime };
274: }
275:
276: void updateTitle() {
277: MarkerList visibleMarkers = getVisibleMarkers();
278: String breakdown = formatSummaryBreakDown(visibleMarkers);
279: int filteredCount = visibleMarkers.getItemCount();
280: int totalCount = getTotalMarkers();
281: if (filteredCount != totalCount) {
282: breakdown = NLS.bind(
283: MarkerMessages.problem_filter_matchedMessage,
284: new Object[] { breakdown,
285: new Integer(filteredCount),
286: new Integer(totalCount) });
287: }
288: setContentDescription(breakdown);
289: }
290:
291: private String formatSummaryBreakDown(MarkerList visibleMarkers) {
292: return MessageFormat.format(
293: MarkerMessages.problem_statusSummaryBreakdown,
294: new Object[] { new Integer(visibleMarkers.getErrors()),
295: new Integer(visibleMarkers.getWarnings()),
296: new Integer(visibleMarkers.getInfos()) });
297: }
298:
299: private String getSummary(MarkerList markers) {
300: String message = MessageFormat.format(
301: MarkerMessages.marker_statusSummarySelected,
302: new Object[] { new Integer(markers.getItemCount()),
303: formatSummaryBreakDown(markers) });
304: return message;
305: }
306:
307: /**
308: * Retrieves statistical information (the total number of markers with each
309: * severity type) for the markers contained in the selection passed in. This
310: * information is then massaged into a string which may be displayed by the
311: * caller.
312: *
313: * @param selection
314: * a valid selection or <code>null</code>
315: * @return a message ready for display
316: */
317: protected String updateSummarySelected(
318: IStructuredSelection selection) {
319: Collection selectionList;
320:
321: selectionList = new ArrayList();
322: Iterator selectionIterator = selection.iterator();
323: while (selectionIterator.hasNext()) {
324: MarkerNode next = (MarkerNode) selectionIterator.next();
325: if (next.isConcrete()) {
326: selectionList.add(next);
327: }
328: }
329:
330: return getSummary(new MarkerList(selectionList));
331: }
332:
333: /*
334: * (non-Javadoc)
335: *
336: * @see org.eclipse.ui.views.markers.internal.MarkerView#getMarkerTypes()
337: */
338: protected String[] getMarkerTypes() {
339: return new String[] { IMarker.PROBLEM };
340: }
341:
342: protected String getStaticContextId() {
343: return PlatformUI.PLUGIN_ID + ".problem_view_context";//$NON-NLS-1$
344: }
345:
346: /*
347: * (non-Javadoc)
348: *
349: * @see org.eclipse.ui.views.markers.internal.MarkerView#createFiltersDialog()
350: */
351: protected DialogMarkerFilter createFiltersDialog() {
352:
353: MarkerFilter[] filters = getUserFilters();
354: ProblemFilter[] problemFilters = new ProblemFilter[filters.length];
355: System.arraycopy(filters, 0, problemFilters, 0, filters.length);
356: return new DialogProblemFilter(getSite().getShell(),
357: problemFilters);
358: }
359:
360: /*
361: * (non-Javadoc)
362: *
363: * @see org.eclipse.ui.views.markers.internal.MarkerView#createFilter(java.lang.String)
364: */
365: protected MarkerFilter createFilter(String name) {
366: return new ProblemFilter(name);
367: }
368:
369: /*
370: * (non-Javadoc)
371: *
372: * @see org.eclipse.ui.views.markers.internal.MarkerView#getSectionTag()
373: */
374: protected String getSectionTag() {
375: return TAG_DIALOG_SECTION;
376: }
377:
378: /*
379: * (non-Javadoc)
380: *
381: * @see org.eclipse.ui.views.markers.internal.MarkerView#getMarkerEnablementPreferenceName()
382: */
383: String getMarkerEnablementPreferenceName() {
384: return IDEInternalPreferences.LIMIT_PROBLEMS;
385: }
386:
387: /*
388: * (non-Javadoc)
389: *
390: * @see org.eclipse.ui.views.markers.internal.MarkerView#getMarkerLimitPreferenceName()
391: */
392: String getMarkerLimitPreferenceName() {
393: return IDEInternalPreferences.PROBLEMS_LIMIT;
394: }
395:
396: /*
397: * (non-Javadoc)
398: *
399: * @see org.eclipse.ui.views.markers.internal.MarkerView#getFiltersPreferenceName()
400: */
401: String getFiltersPreferenceName() {
402: return IDEInternalPreferences.PROBLEMS_FILTERS;
403: }
404:
405: /*
406: * (non-Javadoc)
407: *
408: * @see org.eclipse.ui.views.markers.internal.MarkerView#getAllFilters()
409: */
410: MarkerFilter[] getAllFilters() {
411: MarkerFilter[] userFilters = super .getAllFilters();
412: Collection declaredFilters = MarkerSupportRegistry
413: .getInstance().getRegisteredFilters();
414: Iterator iterator = declaredFilters.iterator();
415:
416: MarkerFilter[] allFilters = new MarkerFilter[userFilters.length
417: + declaredFilters.size()];
418: System.arraycopy(userFilters, 0, allFilters, 0,
419: userFilters.length);
420: int index = userFilters.length;
421:
422: while (iterator.hasNext()) {
423: allFilters[index] = (MarkerFilter) iterator.next();
424: index++;
425: }
426: return allFilters;
427:
428: }
429:
430: /*
431: * (non-Javadoc)
432: *
433: * @see org.eclipse.ui.views.markers.internal.MarkerView#addDropDownContributions(org.eclipse.jface.action.IMenuManager)
434: */
435: void addDropDownContributions(IMenuManager menu) {
436:
437: MenuManager groupByMenu = new MenuManager(
438: MarkerMessages.ProblemView_GroupByMenu);
439:
440: Iterator definedGroups = MarkerSupportRegistry.getInstance()
441: .getMarkerGroups().iterator();
442:
443: while (definedGroups.hasNext()) {
444: MarkerGroup group = (MarkerGroup) definedGroups.next();
445: groupByMenu.add(new GroupingAction(group.getField()
446: .getDescription(), group.getField(), this ));
447: }
448:
449: groupByMenu.add(new GroupingAction(
450: MarkerMessages.ProblemView_None, null, this ));
451: menu.add(groupByMenu);
452:
453: super .addDropDownContributions(menu);
454: }
455:
456: /**
457: * Resize the category column in the table.
458: */
459: protected void regenerateLayout() {
460: TableLayout layout = new TableLayout();
461: getViewer().getTree().setLayout(layout);
462:
463: ColumnLayoutData[] columnWidths = getDefaultColumnLayouts();
464: for (int i = 0; i < columnWidths.length; i++) {
465: layout.addColumnData(columnWidths[i]);
466:
467: }
468: getViewer().getTree().layout(true);
469:
470: }
471:
472: /*
473: * (non-Javadoc)
474: *
475: * @see org.eclipse.ui.views.markers.internal.TableView#setSorter(org.eclipse.ui.views.markers.internal.TableSorter)
476: */
477: void setComparator(TableComparator sorter2) {
478: getMarkerAdapter().getCategorySorter().setTableSorter(sorter2);
479: getMarkerAdapter().getCategorySorter().saveState(
480: getDialogSettings());
481: updateForNewComparator(sorter2);
482:
483: }
484:
485: /*
486: * (non-Javadoc)
487: *
488: * @see org.eclipse.ui.views.markers.internal.MarkerView#getTableSorter()
489: */
490: public TableComparator getTableSorter() {
491: return ((CategoryComparator) getViewer().getComparator()).innerSorter;
492: }
493:
494: /*
495: * (non-Javadoc)
496: *
497: * @see org.eclipse.ui.views.markers.internal.MarkerView#createPartControl(org.eclipse.swt.widgets.Composite)
498: */
499: public void createPartControl(Composite parent) {
500: super .createPartControl(parent);
501: createActivityManagerListener();
502: PlatformUI.getWorkbench().getActivitySupport()
503: .getActivityManager().addActivityManagerListener(
504: activityManagerListener);
505: }
506:
507: /**
508: * Create a new listener for activity changes.
509: */
510: private void createActivityManagerListener() {
511: activityManagerListener = new IActivityManagerListener() {
512: /*
513: * (non-Javadoc)
514: *
515: * @see org.eclipse.ui.activities.IActivityManagerListener#activityManagerChanged(org.eclipse.ui.activities.ActivityManagerEvent)
516: */
517: public void activityManagerChanged(
518: ActivityManagerEvent activityManagerEvent) {
519: clearEnabledFilters();
520: refreshViewer();
521: }
522: };
523:
524: }
525:
526: /**
527: * Return the field whose description matches description.
528: *
529: * @param description
530: * @return IField
531: */
532: public IField findField(String description) {
533: IField[] fields = getSortingFields();
534: for (int i = 0; i < fields.length; i++) {
535: if (fields[i].getDescription().equals(description)) {
536: return fields[i];
537: }
538: }
539: return null;
540: }
541:
542: /*
543: * (non-Javadoc)
544: *
545: * @see org.eclipse.ui.views.markers.internal.TableView#buildComparator()
546: */
547: protected ViewerComparator buildComparator() {
548:
549: TableComparator sorter = createTableComparator();
550: CategoryComparator category = new CategoryComparator(sorter);
551: category.restoreState(getDialogSettings(), this );
552: return category;
553: }
554:
555: /*
556: * (non-Javadoc)
557: *
558: * @see org.eclipse.ui.views.markers.internal.MarkerView#canBeEditable()
559: */
560: boolean canBeEditable() {
561: return false;
562: }
563:
564: /*
565: * (non-Javadoc)
566: *
567: * @see org.eclipse.ui.views.markers.internal.MarkerView#initToolBar(org.eclipse.jface.action.IToolBarManager)
568: */
569: protected void initToolBar(IToolBarManager tbm) {
570: tbm.add(getFilterAction());
571: tbm.update(false);
572: }
573:
574: /**
575: * Select the category for the receiver.
576: *
577: * @param description
578: * @param sorter -
579: * the sorter to select for
580: */
581: public void selectCategory(String description,
582: CategoryComparator sorter) {
583:
584: if (description == null)
585: selectCategoryField(null, sorter);
586:
587: Iterator definedGroups = MarkerSupportRegistry.getInstance()
588: .getMarkerGroups().iterator();
589: while (definedGroups.hasNext()) {
590: MarkerGroup group = (MarkerGroup) definedGroups.next();
591: if (group.getField().getDescription().equals(description)) {
592: selectCategoryField(group.getField(), sorter);
593: return;
594: }
595: }
596: selectCategoryField(null, sorter);
597:
598: }
599:
600: /**
601: * Select the field groupingField.
602: *
603: * @param groupingField
604: * @param sorter
605: */
606: void selectCategoryField(IField groupingField,
607: CategoryComparator sorter) {
608: sorter.setCategoryField(groupingField);
609:
610: // Do not refresh if the input has not been set yet
611: if (getMarkerAdapter() != null) {
612: getMarkerAdapter().getCurrentMarkers().clearGroups();
613: refreshViewer();
614: }
615: }
616:
617: /*
618: * (non-Javadoc)
619: *
620: * @see org.eclipse.ui.views.markers.internal.MarkerView#writeFiltersSettings(org.eclipse.ui.XMLMemento)
621: */
622: protected void writeFiltersSettings(XMLMemento memento) {
623: super .writeFiltersSettings(memento);
624:
625: // Add the system filters
626: Iterator filters = MarkerSupportRegistry.getInstance()
627: .getRegisteredFilters().iterator();
628:
629: while (filters.hasNext()) {
630: MarkerFilter filter = (MarkerFilter) filters.next();
631: IMemento child = memento.createChild(
632: TAG_SYSTEM_FILTER_ENTRY, filter.getName());
633: child.putString(MarkerFilter.TAG_ENABLED, String
634: .valueOf(filter.isEnabled()));
635: }
636:
637: }
638:
639: /*
640: * (non-Javadoc)
641: *
642: * @see org.eclipse.ui.views.markers.internal.MarkerView#restoreFilters(org.eclipse.ui.IMemento)
643: */
644: void restoreFilters(IMemento memento) {
645:
646: super .restoreFilters(memento);
647:
648: if (memento == null)
649: return;
650:
651: IMemento[] sections = memento
652: .getChildren(TAG_SYSTEM_FILTER_ENTRY);
653:
654: Collection registered = MarkerSupportRegistry.getInstance()
655: .getRegisteredFilters();
656: MarkerFilter[] filters = new MarkerFilter[registered.size()];
657: registered.toArray(filters);
658:
659: if (sections != null) {
660:
661: for (int i = 0; i < sections.length; i++) {
662: String filterName = sections[i].getID();
663: boolean enabled = Boolean
664: .valueOf(
665: sections[i]
666: .getString(MarkerFilter.TAG_ENABLED))
667: .booleanValue();
668: setEnablement(filterName, enabled, filters);
669:
670: }
671: }
672:
673: }
674:
675: /**
676: * Set the enablement state of the filter called filterName to enabled.
677: *
678: * @param filterName
679: * @param enabled
680: * @param filters
681: */
682: private void setEnablement(String filterName, boolean enabled,
683: MarkerFilter[] filters) {
684: for (int i = 0; i < filters.length; i++) {
685: if (filters[i].getName().equals(filterName)) {
686: filters[i].setEnabled(enabled);
687: return;
688: }
689: }
690:
691: }
692:
693: /*
694: * (non-Javadoc)
695: *
696: * @see org.eclipse.ui.views.markers.internal.MarkerView#getMarkerName()
697: */
698: protected String getMarkerName() {
699: return MarkerMessages.problem_title;
700: }
701: }
|