1414
1515package org .eclipse .ui .internal ;
1616
17+ import java .util .Arrays ;
18+ import java .util .Collection ;
19+ import java .util .Collections ;
20+ import java .util .List ;
21+ import java .util .stream .Collectors ;
1722import org .eclipse .core .commands .ExecutionEvent ;
1823import org .eclipse .core .commands .ExecutionException ;
1924import org .eclipse .core .expressions .EvaluationResult ;
2025import org .eclipse .core .expressions .Expression ;
2126import org .eclipse .core .expressions .ExpressionInfo ;
2227import org .eclipse .core .expressions .IEvaluationContext ;
28+ import org .eclipse .e4 .ui .model .application .MApplication ;
29+ import org .eclipse .e4 .ui .model .application .ui .basic .MPart ;
30+ import org .eclipse .e4 .ui .workbench .IWorkbench ;
31+ import org .eclipse .e4 .ui .workbench .modeling .EModelService ;
32+ import org .eclipse .e4 .ui .workbench .modeling .EPartService ;
2333import org .eclipse .ui .IEditorReference ;
2434import org .eclipse .ui .ISources ;
2535import org .eclipse .ui .IWorkbenchPage ;
2636import org .eclipse .ui .IWorkbenchPart ;
2737import org .eclipse .ui .IWorkbenchWindow ;
2838import org .eclipse .ui .handlers .HandlerUtil ;
39+ import org .eclipse .ui .internal .e4 .compatibility .CompatibilityEditor ;
40+ import org .osgi .framework .BundleContext ;
41+ import org .osgi .framework .FrameworkUtil ;
42+ import org .osgi .framework .ServiceReference ;
2943
3044/**
3145 * Closes all active editors
@@ -48,6 +62,25 @@ public Object execute(ExecutionEvent event) throws ExecutionException {
4862 IWorkbenchPage page = window .getActivePage ();
4963 if (page != null ) {
5064 page .closeAllEditors (true );
65+
66+ // close parts representing editors which were contributed via
67+ // eg. model fragment(s)
68+ Collection <MPart > partsTaggedAsEditor = getContributedPartsTaggedAsEditor ();
69+ if (!partsTaggedAsEditor .isEmpty ()) {
70+ MApplication application = getApplicationModel ();
71+ EPartService partService = application .getContext ().get (EPartService .class );
72+ if (partService != null ) {
73+ for (MPart part : partsTaggedAsEditor ) {
74+ if (partService .savePart (part , true )) {
75+ partService .hidePart (part );
76+ }
77+ }
78+ // ensure the EnabledWhenExpression evaluation is performed
79+ // otherwise the 'Close All Editors' will still appear enabled until
80+ // the user clicks/selects a different part
81+ getEvaluationService ().requestEvaluation (ISources .ACTIVE_PART_NAME );
82+ }
83+ }
5184 }
5285
5386 return null ;
@@ -69,6 +102,12 @@ public EvaluationResult evaluate(IEvaluationContext context) {
69102 if (refArray != null && refArray .length > 0 ) {
70103 return EvaluationResult .TRUE ;
71104 }
105+
106+ // determine if we have any part contributions via model fragment
107+ // which were tagged as being an 'Editor' (and which are to be rendered)
108+ if (!getContributedPartsTaggedAsEditor ().isEmpty ()) {
109+ return EvaluationResult .TRUE ;
110+ }
72111 }
73112 }
74113 return EvaluationResult .FALSE ;
@@ -83,4 +122,35 @@ public void collectExpressionInfo(ExpressionInfo info) {
83122 }
84123 return enabledWhen ;
85124 }
125+
126+ /**
127+ * Collects part contributions from the application model which are not
128+ * associated with compatibility layer editors, and are instead parts
129+ * contributed via eg. model fragment, and which were tagged as representing an
130+ * Editor, via the {@link Workbench#EDITOR_TAG} tag.
131+ *
132+ * @return a collection of (closable) part contributions from the application
133+ * model, tagged as 'Editor' and not containing the parts associated
134+ * with compatibility layer editors. Returns an empty collection if none
135+ * are found
136+ */
137+ private Collection <MPart > getContributedPartsTaggedAsEditor () {
138+ MApplication application = getApplicationModel ();
139+ EModelService modelService = application .getContext ().get (EModelService .class );
140+
141+ List <MPart > partsTaggedAsEditor = modelService != null
142+ ? modelService .findElements (application , null , MPart .class , Arrays .asList (Workbench .EDITOR_TAG ))
143+ : Collections .emptyList ();
144+
145+ // remove parts which we wish to ignore: compatibility layer editors,
146+ // non-closable parts, non-rendered parts
147+ return partsTaggedAsEditor .stream ().filter (p -> !CompatibilityEditor .MODEL_ELEMENT_ID .equals (p .getElementId ())
148+ && p .isCloseable () && p .isToBeRendered ()).collect (Collectors .toSet ());
149+ }
150+
151+ private MApplication getApplicationModel () {
152+ BundleContext bundleContext = FrameworkUtil .getBundle (IWorkbench .class ).getBundleContext ();
153+ ServiceReference <IWorkbench > reference = bundleContext .getServiceReference (IWorkbench .class );
154+ return bundleContext .getService (reference ).getApplication ();
155+ }
86156}
0 commit comments