Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 246875 | Differences between
and this patch

Collapse All | Expand All

(-)plugin.xml (-10 / +1 lines)
Lines 107-121 Link Here
107
            </command>
107
            </command>
108
                        
108
                        
109
      </menuContribution>
109
      </menuContribution>
110
      <menuContribution
111
            locationURI="menu:help?after=org.eclipse.equinox.p2.ui.sdk.install">
112
            <command
113
                  commandId="org.eclipse.ui.help.installationDialog"
114
            	  mnemonic="%TempInstallView.mnemonic"
115
                  id="org.eclipse.equinox.p2.ui.sdk.tempInstallInfo">
116
            </command>
117
                        
118
      </menuContribution>
119
   </extension>
110
   </extension>
120
   <extension
111
   <extension
121
         point="org.eclipse.ui.activities">
112
         point="org.eclipse.ui.activities">
Lines 153-159 Link Here
153
          <page
144
          <page
154
            name="%installedSoftwarePage"
145
            name="%installedSoftwarePage"
155
            class="org.eclipse.equinox.internal.provisional.p2.ui.dialogs.InstalledSoftwarePage"
146
            class="org.eclipse.equinox.internal.provisional.p2.ui.dialogs.InstalledSoftwarePage"
156
            id="org.eclipse.equinox.internal.p2.ui.sdk.InstalledSoftwarePage">
147
            id="10.org.eclipse.equinox.internal.p2.ui.sdk.InstalledSoftwarePage">
157
          </page>
148
          </page>
158
          <page
149
          <page
159
            name="%installHistoryPage"
150
            name="%installHistoryPage"
(-)plugin.properties (+6 lines)
Lines 284-286 Link Here
284
menu.mnemonic.0 = I
284
menu.mnemonic.0 = I
285
menu.showIn.label = Show In
285
menu.showIn.label = Show In
286
menu.showIn.mnemonic = I
286
menu.showIn.mnemonic = I
287
288
installationPage.feature.name = Features
289
command.installationPageColumns.mnemonic = C
290
command.installationPageLicense.name = License
291
command.installationPageLicense.mnemonic = L
292
command.installationPageLicense.description = Open a browser on the license
(-)plugin.xml (+93 lines)
Lines 2234-2237 Link Here
2234
            type="org.eclipse.core.resources.IMarker">
2234
            type="org.eclipse.core.resources.IMarker">
2235
      </propertyTester>
2235
      </propertyTester>
2236
   </extension>
2236
   </extension>
2237
   <extension
2238
          point="org.eclipse.ui.commands">
2239
          <command
2240
            description="%command.installationPageLicense.description"
2241
            id="org.eclipse.ui.about.featureDialog.openLicense"
2242
            name="%command.installationPageLicense.name"
2243
            defaultHandler="org.eclipse.ui.internal.about.OpenBrowserHandler"/> 
2244
 	 </extension>          
2245
   
2246
      <extension
2247
         point="org.eclipse.ui.installationPages">
2248
          <page
2249
            name="%installationPage.feature.name"
2250
            class="org.eclipse.ui.internal.about.AboutFeaturesPage"
2251
            id="20.FeaturesPage">
2252
          </page>
2253
       </extension>
2254
       <extension
2255
         point="org.eclipse.ui.menus">
2256
      <menuContribution
2257
            locationURI="toolbar:org.eclipse.ui.installationDialog.buttonbar">
2258
         <command
2259
               commandId="org.eclipse.ui.about.columns"
2260
               mnemonic="%command.installationPageColumns.mnemonic"
2261
               style="push">
2262
            <visibleWhen>
2263
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2264
        			<equals value="20.FeaturesPage"/>
2265
      			</with>
2266
    		</visibleWhen>
2267
         </command>
2268
         <command
2269
               commandId="org.eclipse.ui.about.openBrowser"
2270
               label="%command.installationPageLicense.name"
2271
               mnemonic="%command.installationPageLicense.mnemonic"
2272
               style="push">
2273
            <visibleWhen>
2274
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2275
        			<equals value="20.FeaturesPage"/>
2276
      			</with>
2277
    		</visibleWhen>
2278
         </command>
2279
        </menuContribution> 
2280
      <menuContribution
2281
            locationURI="toolbar:org.eclipse.ui.installationDialog.buttonbar.productInfo.features">
2282
         <command
2283
               commandId="org.eclipse.ui.about.columns"
2284
               mnemonic="%command.installationPageColumns.mnemonic"
2285
               style="push">
2286
         </command>
2287
         <command
2288
               commandId="org.eclipse.ui.about.featureDialog.openLicense"
2289
               label="%command.installationPageLicense.name"
2290
               mnemonic="%command.installationPageLicense.mnemonic"
2291
               style="push">
2292
         </command>
2293
        </menuContribution> 
2294
     </extension> 
2295
            <extension
2296
         point="org.eclipse.ui.handlers">
2297
      <handler
2298
            class="org.eclipse.ui.internal.about.OpenBrowserHandler"
2299
            commandId="org.eclipse.ui.about.openBrowser">
2300
         <activeWhen>
2301
            <with
2302
                  variable="org.eclipse.ui.installationPage.activePage.id">
2303
               <equals value="20.FeaturesPage"/>
2304
            </with>
2305
         </activeWhen>
2306
        <enabledWhen>
2307
            <with
2308
                  variable="org.eclipse.ui.installationPage.activePage.selection">
2309
               <count value="1"/>
2310
            </with>
2311
         </enabledWhen>
2312
      </handler>
2313
     <handler
2314
            class="org.eclipse.ui.internal.about.OpenBrowserHandler"
2315
            commandId="org.eclipse.ui.about.featureDialog.openLicense">
2316
         <activeWhen>
2317
             <with
2318
                  variable="org.eclipse.ui.internal.about.activeProductDialogPageId">
2319
               <equals value="productInfo.features"/>
2320
            </with>
2321
         </activeWhen>
2322
        <enabledWhen>
2323
            <with
2324
                  variable="org.eclipse.ui.internal.about.activeProductDialogSelection">
2325
               <count value="1"/>
2326
            </with>
2327
         </enabledWhen>
2328
      </handler>
2329
    </extension>
2237
</plugin>
2330
</plugin>
(-)plugin.xml (+167 lines)
Lines 2221-2224 Link Here
2221
            type="java.lang.Object">
2221
            type="java.lang.Object">
2222
      </propertyTester>
2222
      </propertyTester>
2223
   </extension>
2223
   </extension>
2224
        <extension
2225
         point="org.eclipse.ui.services">
2226
       <sourceProvider
2227
            provider="org.eclipse.ui.internal.about.InstallationDialogSourceProvider">
2228
         <variable
2229
               name="org.eclipse.ui.installationPage.activePage"
2230
               priorityLevel="activeContexts">
2231
         </variable>
2232
         <variable
2233
               name="org.eclipse.ui.installationPage.activePage.id"
2234
               priorityLevel="activeContexts">
2235
         </variable>        
2236
          <variable
2237
               name="org.eclipse.ui.installationPage.activePage.selection"
2238
               priorityLevel="activeContexts">
2239
         </variable>        
2240
         <variable
2241
               name="org.eclipse.ui.internal.about.activeProductDialogPage"
2242
               priorityLevel="activeContexts">
2243
         </variable>        
2244
         <variable
2245
               name="org.eclipse.ui.internal.about.activeProductDialogPageId"
2246
               priorityLevel="activeContexts">
2247
         </variable>        
2248
      </sourceProvider>
2249
   </extension>   
2250
   <extension
2251
         point="org.eclipse.ui.installationPages">
2252
          <page
2253
            name="%installationPage.plugins.name"
2254
            class="org.eclipse.ui.internal.about.AboutPluginsPage"
2255
            id="15.PluginPage">
2256
          </page>        
2257
          <page
2258
            name="%installationPage.system.name"
2259
            class="org.eclipse.ui.internal.about.AboutSystemPage"
2260
            id="16.SystemPage">
2261
          </page>
2262
     </extension>
2263
     <extension
2264
          point="org.eclipse.ui.commands">
2265
          <command
2266
            description="%command.installationPageColumns.description"
2267
            id="org.eclipse.ui.about.columns"
2268
            name="%command.installationPageColumns.name"
2269
            defaultHandler="org.eclipse.ui.internal.about.ConfigureColumnsHandler"/> 
2270
          <command
2271
            description="%command.installationPageOpenBrowser.description"
2272
            id="org.eclipse.ui.about.openBrowser"
2273
            name="%command.installationPageOpenBrowser.name"
2274
            defaultHandler="org.eclipse.ui.internal.about.OpenBrowserHandler"/> 
2275
          <command
2276
            description="%command.installationPageOpenBrowser.description"
2277
            id="org.eclipse.ui.about.pluginsDialog.openLegal"
2278
            name="%command.installationPageOpenBrowser.name"
2279
            defaultHandler="org.eclipse.ui.internal.about.OpenBrowserHandler"/> 
2280
          <command
2281
            description="%command.installationPageViewErrorLog.description"
2282
            id="org.eclipse.ui.about.viewErrorLog"
2283
            name="%command.installationPageViewErrorLog.name"
2284
            defaultHandler="org.eclipse.ui.internal.about.ViewErrorLogHandler"/> 
2285
	 </extension>          
2286
     <extension
2287
         point="org.eclipse.ui.menus">
2288
      <menuContribution
2289
            locationURI="toolbar:org.eclipse.ui.installationDialog.buttonbar">
2290
         <command
2291
               commandId="org.eclipse.ui.edit.copy"
2292
               style="push">
2293
            <visibleWhen>
2294
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2295
        			<equals value="16.SystemPage"/>
2296
      			</with>
2297
    		</visibleWhen>
2298
         </command>
2299
         <command
2300
               commandId="org.eclipse.ui.about.viewErrorLog"
2301
               mnemonic="%command.installationPageViewErrorLog.mnemonic"
2302
               style="push">
2303
            <visibleWhen>
2304
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2305
        			<equals value="16.SystemPage"/>
2306
      			</with>
2307
    		</visibleWhen>
2308
         </command>
2309
         <command
2310
               commandId="org.eclipse.ui.about.columns"
2311
               mnemonic="%command.installationPageColumns.mnemonic"
2312
               style="push">
2313
            <visibleWhen>
2314
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2315
        			<equals value="15.PluginPage"/>
2316
      			</with>
2317
    		</visibleWhen>
2318
         </command>
2319
         <command
2320
               commandId="org.eclipse.ui.about.openBrowser"
2321
               label="%command.installationPageLegalInfo.name"
2322
               mnemonic="%command.installationPageLegalInfo.mnemonic"
2323
               style="push">
2324
            <visibleWhen>
2325
      			<with variable="org.eclipse.ui.installationPage.activePage.id">
2326
        			<equals value="15.PluginPage"/>
2327
      			</with>
2328
    		</visibleWhen>
2329
         </command>
2330
      </menuContribution>    
2331
      <menuContribution
2332
            locationURI="toolbar:org.eclipse.ui.installationDialog.buttonbar.productInfo.plugins">
2333
          <command
2334
               commandId="org.eclipse.ui.about.columns"
2335
               mnemonic="%command.installationPageColumns.mnemonic"
2336
               style="push">
2337
         </command>
2338
         <command
2339
               commandId="org.eclipse.ui.about.pluginsDialog.openLegal"
2340
               label="%command.installationPageLegalInfo.name"
2341
               mnemonic="%command.installationPageLegalInfo.mnemonic"
2342
               style="push">
2343
         </command>
2344
      </menuContribution>    
2345
   </extension>
2346
     <extension
2347
         point="org.eclipse.ui.handlers">
2348
      <handler
2349
            class="org.eclipse.ui.internal.about.CopyHandler"
2350
            commandId="org.eclipse.ui.edit.copy">
2351
         <activeWhen>
2352
            <with
2353
                  variable="org.eclipse.ui.installationPage.activePage.id">
2354
               <equals value="16.SystemPage"/>
2355
            </with>
2356
         </activeWhen>
2357
      </handler>
2358
       <handler
2359
            class="org.eclipse.ui.internal.about.OpenBrowserHandler"
2360
            commandId="org.eclipse.ui.about.openBrowser">
2361
         <activeWhen>
2362
            <with
2363
                  variable="org.eclipse.ui.installationPage.activePage.id">
2364
               <equals value="15.PluginPage"/>
2365
            </with>
2366
         </activeWhen>
2367
        <enabledWhen>
2368
            <with
2369
                  variable="org.eclipse.ui.installationPage.activePage.selection">
2370
               <count value="1"/>
2371
            </with>
2372
         </enabledWhen>
2373
      </handler>
2374
      <handler
2375
            class="org.eclipse.ui.internal.about.OpenBrowserHandler"
2376
            commandId="org.eclipse.ui.about.pluginsDialog.openLegal">
2377
         <activeWhen>
2378
            <with
2379
                  variable="org.eclipse.ui.internal.about.activeProductDialogPageId">
2380
               <equals value="productInfo.plugins"/>
2381
            </with>
2382
          </activeWhen>
2383
        <enabledWhen>
2384
            <with
2385
                  variable="org.eclipse.ui.internal.about.activeProductDialogSelection">
2386
               <count value="1"/>
2387
            </with>
2388
         </enabledWhen>
2389
      </handler>     
2390
    </extension>
2224
</plugin>
2391
</plugin>
(-)plugin.properties (-1 / +15 lines)
Lines 330-333 Link Here
330
command.quickMenu.name = Open Quick Menu
330
command.quickMenu.name = Open Quick Menu
331
command.quickMenu.uri.name = Location URI
331
command.quickMenu.uri.name = Location URI
332
command.showIn.name = Show In
332
command.showIn.name = Show In
333
command.showIn.targetId.name = Show In Target Id
333
command.showIn.targetId.name = Show In Target Id
334
335
installationPage.main.name = About
336
installationPage.system.name = Configuration
337
installationPage.plugins.name = Plug-ins
338
command.installationPageColumns.name = Columns
339
command.installationPageColumns.description = Open a dialog to set the column widths
340
command.installationPageColumns.mnemonic = C
341
command.installationPageOpenBrowser.name = More
342
command.installationPageOpenBrowser.description = Open a browser on additional information
343
command.installationPageLegalInfo.name = Legal Info
344
command.installationPageLegalInfo.mnemonic = L
345
command.installationPageViewErrorLog.name = View Error Log
346
command.installationPageViewErrorLog.description = Open a browser on the error log
347
command.installationPageViewErrorLog.mnemonic = V
(-)schema/installationPages.exsd (-23 / +55 lines)
Lines 2-20 Link Here
2
<!-- Schema file written by PDE -->
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.ui" xmlns="http://www.w3.org/2001/XMLSchema">
3
<schema targetNamespace="org.eclipse.ui" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
4
<annotation>
5
      <appinfo>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.ui" id="installationPages" name="Installation Dialog Pages"/>
6
         <meta.schema plugin="org.eclipse.ui" id="installationPages" name="Installation Dialog Pages"/>
7
      </appinfo>
7
      </appInfo>
8
      <documentation>
8
      <documentation>
9
         This is an experimental extension point for an extensible about dialog.  It is not ready for production and is included at this time only for evaluation by downstream clients.  Use at your own risk.
9
         &lt;p&gt;The Eclipse UI provides an AboutDialog that can be branded and reused by client product plugins.  This dialog typically shows the product splash image and other descriptive information about the product. The about dialog includes a button that allows the user to launch a secondary dialog, the &lt;b&gt;Installation Details&lt;/b&gt; dialog.&lt;/p&gt;
10
&lt;p&gt;The purpose of this extension point is to allow plug-ins to add
11
pages to the installation details dialog.  When the installation details dialog is opened, the pages contributed in this way will be added to the dialog box.  These pages are used to supply additional detail about the product configuration.&lt;/p&gt;
12
13
&lt;p&gt;This is an experimental extension point for an extensible about dialog.  It is not ready for production and is included at this time only for evaluation by downstream clients.  Use at your own risk.&lt;/p&gt;
10
      </documentation>
14
      </documentation>
11
   </annotation>
15
   </annotation>
12
16
13
   <element name="extension">
17
   <element name="extension">
14
      <annotation>
18
      <annotation>
15
         <appinfo>
19
         <appInfo>
16
            <meta.element />
20
            <meta.element />
17
         </appinfo>
21
         </appInfo>
18
      </annotation>
22
      </annotation>
19
      <complexType>
23
      <complexType>
20
         <sequence>
24
         <sequence>
Lines 39-47 Link Here
39
               <documentation>
43
               <documentation>
40
                  
44
                  
41
               </documentation>
45
               </documentation>
42
               <appinfo>
46
               <appInfo>
43
                  <meta.attribute translatable="true"/>
47
                  <meta.attribute translatable="true"/>
44
               </appinfo>
48
               </appInfo>
45
            </annotation>
49
            </annotation>
46
         </attribute>
50
         </attribute>
47
      </complexType>
51
      </complexType>
Lines 61-69 Link Here
61
               <documentation>
65
               <documentation>
62
                  
66
                  
63
               </documentation>
67
               </documentation>
64
               <appinfo>
68
               <appInfo>
65
                  <meta.attribute kind="java" basedOn="org.eclipse.ui.branding.InstallationPage:"/>
69
                  <meta.attribute kind="java" basedOn="org.eclipse.ui.branding.InstallationPage:"/>
66
               </appinfo>
70
               </appInfo>
67
            </annotation>
71
            </annotation>
68
         </attribute>
72
         </attribute>
69
         <attribute name="name" type="string" use="required">
73
         <attribute name="name" type="string" use="required">
Lines 71-119 Link Here
71
               <documentation>
75
               <documentation>
72
                  
76
                  
73
               </documentation>
77
               </documentation>
74
               <appinfo>
78
               <appInfo>
75
                  <meta.attribute translatable="true"/>
79
                  <meta.attribute translatable="true"/>
76
               </appinfo>
80
               </appInfo>
77
            </annotation>
81
            </annotation>
78
         </attribute>
82
         </attribute>
79
      </complexType>
83
      </complexType>
80
   </element>
84
   </element>
81
85
82
   <annotation>
86
   <annotation>
83
      <appinfo>
87
      <appInfo>
84
         <meta.section type="since"/>
88
         <meta.section type="since"/>
85
      </appinfo>
89
      </appInfo>
86
      <documentation>
90
      <documentation>
87
         [Enter the first release in which this extension point appears.]
91
         3.5
88
      </documentation>
92
      </documentation>
89
   </annotation>
93
   </annotation>
90
94
91
   <annotation>
95
   <annotation>
92
      <appinfo>
96
      <appInfo>
93
         <meta.section type="examples"/>
97
         <meta.section type="examples"/>
94
      </appinfo>
98
      </appInfo>
95
      <documentation>
99
      <documentation>
96
         [Enter extension point usage example here.]
100
         The following is an example installation page: 
101
&lt;p&gt;
102
&lt;pre&gt;
103
   &lt;extension point=&quot;org.eclipse.ui.installationPages&quot;&gt; 
104
       &lt;page
105
            name=&quot;XYZ Info&quot;
106
            class=&quot;org.eclipse.ui.internal.XYZInstallInfoPage&quot;
107
            id=&quot;org.eclipse.ui.internal.xyz&gt;
108
       &lt;/page&gt;
109
    &lt;/extension&gt;
110
&lt;/pre&gt;
111
&lt;/p&gt;
97
      </documentation>
112
      </documentation>
98
   </annotation>
113
   </annotation>
99
114
100
   <annotation>
115
   <annotation>
101
      <appinfo>
116
      <appInfo>
102
         <meta.section type="apiinfo"/>
117
         <meta.section type="apiinfo"/>
103
      </appinfo>
118
      </appInfo>
104
      <documentation>
119
      <documentation>
105
         [Enter API information here.]
120
         The value of the attribute class must represent a fully qualified name of a class that is a concrete subclass of
121
&lt;samp&gt;org.eclipse.ui.about.InstallationPage&lt;/samp&gt;.
106
      </documentation>
122
      </documentation>
107
   </annotation>
123
   </annotation>
108
124
109
   <annotation>
125
   <annotation>
110
      <appinfo>
126
      <appInfo>
111
         <meta.section type="implementation"/>
127
         <meta.section type="implementation"/>
112
      </appinfo>
128
      </appInfo>
113
      <documentation>
129
      <documentation>
114
         [Enter information about supplied implementation of this extension point.]
130
         The Workbench uses this extension point to provide the following pages in the installation details dialog:
131
&lt;ul&gt;
132
&lt;li&gt;Plug-ins: A list of all of the plug-ins in the running the system, including details about each plug-in.&lt;/li&gt;
133
&lt;li&gt;Configuration: The configuration information contributed via the &lt;samp&gt;org.eclipse.ui.systemSummarySections&lt;/samp&gt; extension.&lt;/li&gt;
134
&lt;/ul&gt;
115
      </documentation>
135
      </documentation>
116
   </annotation>
136
   </annotation>
117
137
138
   <annotation>
139
      <appInfo>
140
         <meta.section type="copyright"/>
141
      </appInfo>
142
      <documentation>
143
         Copyright (c) 2008, 2009 IBM Corporation and others.&lt;br&gt;
144
All rights reserved. This program and the accompanying materials are made
145
available under the terms of the Eclipse Public License v1.0 which accompanies
146
this distribution, and is available at &lt;a 
147
href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
148
      </documentation>
149
   </annotation>
118
150
119
</schema>
151
</schema>
(-)schema/systemSummarySections.exsd (-2 / +7 lines)
Lines 1-16 Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.ui">
3
<schema targetNamespace="org.eclipse.ui" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
4
<annotation>
5
      <appInfo>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.ui" id="systemSummarySections" name="System Summary Sections"/>
6
         <meta.schema plugin="org.eclipse.ui" id="systemSummarySections" name="System Summary Sections"/>
7
      </appInfo>
7
      </appInfo>
8
      <documentation>
8
      <documentation>
9
         The Eclipse UI provides an AboutDialog that can be branded and reused by client product plugins.  This dialog includes a SystemSummary dialog that contains configuration details.  By extending the org.eclipse.ui.systemSummarySections extension point clients are able to put their own information into the log.
9
         The Eclipse UI provides an AboutDialog that can be branded and reused by client product plugins.  This dialog includes SystemSummary information that contains configuration details.  By extending the org.eclipse.ui.systemSummarySections extension point clients are able to put their own information into the log.
10
      </documentation>
10
      </documentation>
11
   </annotation>
11
   </annotation>
12
12
13
   <element name="extension">
13
   <element name="extension">
14
      <annotation>
15
         <appInfo>
16
            <meta.element />
17
         </appInfo>
18
      </annotation>
14
      <complexType>
19
      <complexType>
15
         <sequence>
20
         <sequence>
16
            <element ref="section" minOccurs="1" maxOccurs="unbounded"/>
21
            <element ref="section" minOccurs="1" maxOccurs="unbounded"/>
(-)src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/RevertProfilePage.java (-4 / +3 lines)
Lines 35-42 Link Here
35
import org.eclipse.swt.layout.GridLayout;
35
import org.eclipse.swt.layout.GridLayout;
36
import org.eclipse.swt.widgets.*;
36
import org.eclipse.swt.widgets.*;
37
import org.eclipse.ui.PlatformUI;
37
import org.eclipse.ui.PlatformUI;
38
import org.eclipse.ui.about.IInstallationPageContainer;
38
import org.eclipse.ui.about.*;
39
import org.eclipse.ui.about.InstallationPage;
40
import org.eclipse.ui.menus.*;
39
import org.eclipse.ui.menus.*;
41
import org.eclipse.ui.services.IServiceLocator;
40
import org.eclipse.ui.services.IServiceLocator;
42
import org.eclipse.ui.statushandlers.StatusManager;
41
import org.eclipse.ui.statushandlers.StatusManager;
Lines 75-81 Link Here
75
		factory = new AbstractContributionFactory(pageContainer.getButtonBarURI(), null) {
74
		factory = new AbstractContributionFactory(pageContainer.getButtonBarURI(), null) {
76
75
77
			public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) {
76
			public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) {
78
				additions.addContributionItem(new ActionContributionItem(revertAction), null);
77
				additions.addContributionItem(new ActionContributionItem(revertAction), new ActiveInstallationPageExpression(RevertProfilePage.this));
79
			}
78
			}
80
		};
79
		};
81
		menuService.addContributionFactory(factory);
80
		menuService.addContributionFactory(factory);
Lines 179-185 Link Here
179
					return;
178
					return;
180
				boolean finish = revert();
179
				boolean finish = revert();
181
				if (finish) {
180
				if (finish) {
182
					pageContainer.close();
181
					pageContainer.closeContainer();
183
				}
182
				}
184
			}
183
			}
185
		};
184
		};
(-)src/org/eclipse/equinox/internal/provisional/p2/ui/dialogs/InstalledSoftwarePage.java (-7 / +8 lines)
Lines 30-37 Link Here
30
import org.eclipse.swt.layout.GridLayout;
30
import org.eclipse.swt.layout.GridLayout;
31
import org.eclipse.swt.widgets.*;
31
import org.eclipse.swt.widgets.*;
32
import org.eclipse.ui.PlatformUI;
32
import org.eclipse.ui.PlatformUI;
33
import org.eclipse.ui.about.IInstallationPageContainer;
33
import org.eclipse.ui.about.*;
34
import org.eclipse.ui.about.InstallationPage;
35
import org.eclipse.ui.menus.*;
34
import org.eclipse.ui.menus.*;
36
import org.eclipse.ui.services.IServiceLocator;
35
import org.eclipse.ui.services.IServiceLocator;
37
36
Lines 98-103 Link Here
98
97
99
		detailsArea = new Text(group, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY | SWT.WRAP);
98
		detailsArea = new Text(group, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY | SWT.WRAP);
100
		detailsArea.setLayoutData(gd);
99
		detailsArea.setLayoutData(gd);
100
		detailsArea.setBackground(detailsArea.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
101
101
102
		setControl(composite);
102
		setControl(composite);
103
	}
103
	}
Lines 111-116 Link Here
111
		factory = new AbstractContributionFactory(pageContainer.getButtonBarURI(), null) {
111
		factory = new AbstractContributionFactory(pageContainer.getButtonBarURI(), null) {
112
112
113
			public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) {
113
			public void createContributionItems(IServiceLocator serviceLocator, IContributionRoot additions) {
114
				ActiveInstallationPageExpression whenPageActive = new ActiveInstallationPageExpression(InstalledSoftwarePage.this);
114
				// For the update action, we create a custom selection provider that will interpret no
115
				// For the update action, we create a custom selection provider that will interpret no
115
				// selection as checking for updates to everything.
116
				// selection as checking for updates to everything.
116
				// We also override the run method to close the containing dialog
117
				// We also override the run method to close the containing dialog
Lines 143-166 Link Here
143
					public void run() {
144
					public void run() {
144
						super.run();
145
						super.run();
145
						if (getReturnCode() == Window.OK)
146
						if (getReturnCode() == Window.OK)
146
							pageContainer.close();
147
							pageContainer.closeContainer();
147
					}
148
					}
148
				};
149
				};
149
				additions.addContributionItem(new ActionContributionItem(action), null);
150
				additions.addContributionItem(new ActionContributionItem(action), whenPageActive);
150
151
151
				// Uninstall action
152
				// Uninstall action
152
				action = new UninstallAction(Policy.getDefault(), installedIUGroup.getStructuredViewer(), profileId) {
153
				action = new UninstallAction(Policy.getDefault(), installedIUGroup.getStructuredViewer(), profileId) {
153
					public void run() {
154
					public void run() {
154
						super.run();
155
						super.run();
155
						if (getReturnCode() == Window.OK)
156
						if (getReturnCode() == Window.OK)
156
							pageContainer.close();
157
							pageContainer.closeContainer();
157
					}
158
					}
158
				};
159
				};
159
				additions.addContributionItem(new ActionContributionItem(action), null);
160
				additions.addContributionItem(new ActionContributionItem(action), whenPageActive);
160
161
161
				// Properties action
162
				// Properties action
162
				action = new PropertyDialogAction(new SameShellProvider(getShell()), installedIUGroup.getStructuredViewer());
163
				action = new PropertyDialogAction(new SameShellProvider(getShell()), installedIUGroup.getStructuredViewer());
163
				additions.addContributionItem(new ActionContributionItem(action), null);
164
				additions.addContributionItem(new ActionContributionItem(action), whenPageActive);
164
			}
165
			}
165
		};
166
		};
166
		menuService.addContributionFactory(factory);
167
		menuService.addContributionFactory(factory);
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/AboutFeaturesDialog.java (-503 / +17 lines)
Lines 12-110 Link Here
12
 *******************************************************************************/
12
 *******************************************************************************/
13
package org.eclipse.ui.internal.dialogs;
13
package org.eclipse.ui.internal.dialogs;
14
14
15
import java.util.HashMap;
16
import java.util.Iterator;
17
import java.util.Map;
18
19
import org.eclipse.core.runtime.IBundleGroup;
20
import org.eclipse.jface.dialogs.IDialogConstants;
21
import org.eclipse.jface.dialogs.MessageDialog;
22
import org.eclipse.jface.internal.ConfigureColumnsDialog;
23
import org.eclipse.jface.resource.ImageDescriptor;
24
import org.eclipse.jface.window.Window;
25
import org.eclipse.osgi.util.NLS;
15
import org.eclipse.osgi.util.NLS;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.custom.StyledText;
28
import org.eclipse.swt.events.DisposeEvent;
29
import org.eclipse.swt.events.DisposeListener;
30
import org.eclipse.swt.events.SelectionAdapter;
31
import org.eclipse.swt.events.SelectionEvent;
32
import org.eclipse.swt.graphics.Cursor;
33
import org.eclipse.swt.graphics.Font;
34
import org.eclipse.swt.graphics.Image;
35
import org.eclipse.swt.layout.GridData;
36
import org.eclipse.swt.layout.GridLayout;
37
import org.eclipse.swt.widgets.Button;
38
import org.eclipse.swt.widgets.Composite;
39
import org.eclipse.swt.widgets.Control;
40
import org.eclipse.swt.widgets.Label;
41
import org.eclipse.swt.widgets.Shell;
16
import org.eclipse.swt.widgets.Shell;
42
import org.eclipse.swt.widgets.Table;
43
import org.eclipse.swt.widgets.TableColumn;
44
import org.eclipse.swt.widgets.TableItem;
45
import org.eclipse.ui.PlatformUI;
46
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
17
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
47
import org.eclipse.ui.internal.WorkbenchMessages;
18
import org.eclipse.ui.internal.WorkbenchMessages;
48
import org.eclipse.ui.internal.about.AboutBundleGroupData;
19
import org.eclipse.ui.internal.about.AboutBundleGroupData;
49
import org.eclipse.ui.internal.about.AboutData;
20
import org.eclipse.ui.internal.about.AboutFeaturesPage;
50
import org.osgi.framework.Bundle;
21
import org.eclipse.ui.internal.about.ProductInfoDialog;
51
22
52
/**
23
/**
53
 * Displays information about the product plugins.
24
 * Displays information about the product plugins.
54
 *
25
 * 
55
 * PRIVATE
26
 * PRIVATE This class is internal to the workbench and must not be called
56
 *	This class is internal to the workbench and must not be called outside
27
 * outside the workbench.
57
 *	the workbench.
58
 */
28
 */
59
public class AboutFeaturesDialog extends ProductInfoDialog {
29
public class AboutFeaturesDialog extends ProductInfoDialog {
60
30
	   /**
61
    /**
62
     * Table height in dialog units (value 150).
63
     */
64
    private static final int TABLE_HEIGHT = 150;
65
66
    private static final int INFO_HEIGHT = 100;
67
68
    private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
69
70
    private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
71
72
    private final static int COLUMNS_ID = IDialogConstants.CLIENT_ID + 3;
73
74
    private Table table;
75
76
    private Label imageLabel;
77
78
    private StyledText text;
79
80
    private Composite infoArea;
81
82
    private Map cachedImages = new HashMap();
83
84
    private String columnTitles[] = {
85
            WorkbenchMessages.AboutFeaturesDialog_provider,
86
            WorkbenchMessages.AboutFeaturesDialog_featureName, 
87
            WorkbenchMessages.AboutFeaturesDialog_version, 
88
            WorkbenchMessages.AboutFeaturesDialog_featureId, 
89
    };
90
91
    private String productName;
92
93
    private AboutBundleGroupData[] bundleGroupInfos;
94
95
    private int lastColumnChosen = 0; // initially sort by provider
96
97
    private boolean reverseSort = false; // initially sort ascending
98
99
    private AboutBundleGroupData lastSelection = null;
100
101
    private Button moreButton;
102
103
    private Button pluginsButton;
104
105
    private static Map featuresMap;
106
107
    /**
108
     * Constructor for AboutFeaturesDialog.
31
     * Constructor for AboutFeaturesDialog.
109
     * 
32
     * 
110
     * @param parentShell the parent shell
33
     * @param parentShell the parent shell
Lines 112-537 Link Here
112
     * @param bundleGroupInfos the bundle info
35
     * @param bundleGroupInfos the bundle info
113
     */
36
     */
114
    public AboutFeaturesDialog(Shell parentShell, String productName,
37
    public AboutFeaturesDialog(Shell parentShell, String productName,
115
            AboutBundleGroupData[] bundleGroupInfos) {
38
            AboutBundleGroupData[] bundleGroupInfos, AboutBundleGroupData initialSelection) {
116
        super(parentShell);
39
        super(parentShell);
117
        this.productName = productName;
40
        AboutFeaturesPage page = new AboutFeaturesPage();
118
41
        page.setProductName(productName);
119
        // the order of the array may be changed due to sorting, so create a
42
        page.setBundleGroupInfos(bundleGroupInfos);
120
        // copy
43
        page.setInitialSelection(initialSelection);
121
        this.bundleGroupInfos = new AboutBundleGroupData[bundleGroupInfos.length];
44
        String title;
122
        System.arraycopy(bundleGroupInfos, 0, this.bundleGroupInfos, 0,
45
        if (productName != null) 
123
                bundleGroupInfos.length);
46
			title = NLS.bind(WorkbenchMessages.AboutFeaturesDialog_shellTitle, productName);
124
47
        else
125
        AboutData.sortByProvider(reverseSort, this.bundleGroupInfos);
48
        	title = WorkbenchMessages.AboutFeaturesDialog_SimpleTitle;
126
    }
49
        initializeDialog(page, title, IWorkbenchHelpContextIds.ABOUT_FEATURES_DIALOG);
127
128
    /**
129
     * The More Info button was pressed.  Open a browser with the license for the
130
     * selected item or an information dialog if there is no license, or the browser
131
     * cannot be opened. 
132
     */
133
    private void handleMoreInfoPressed() {
134
        TableItem[] items = table.getSelection();
135
        if (items.length <= 0) {
136
			return;
137
		}
138
139
        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
140
        if (info == null || !openBrowser(info.getLicenseUrl())) {
141
            MessageDialog.openInformation(getShell(), WorkbenchMessages.AboutFeaturesDialog_noInfoTitle, 
142
                    WorkbenchMessages.AboutFeaturesDialog_noInformation);
143
        }
144
    }
145
146
    /**
147
     * The Plugins button was pressed. Open an about dialog on the plugins for
148
     * the selected feature.
149
     */
150
    private void handlePluginInfoPressed() {
151
        TableItem[] items = table.getSelection();
152
        if (items.length <= 0) {
153
			return;
154
		}
155
156
        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
157
        IBundleGroup bundleGroup = info.getBundleGroup();
158
        Bundle[] bundles = bundleGroup == null ? new Bundle[0] : bundleGroup
159
                .getBundles();
160
161
        AboutPluginsDialog d = new AboutPluginsDialog(getShell(), productName,
162
                bundles, WorkbenchMessages.AboutFeaturesDialog_pluginInfoTitle, 
163
                NLS.bind(WorkbenchMessages.AboutFeaturesDialog_pluginInfoMessage, bundleGroup.getIdentifier()),
164
                IWorkbenchHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG);
165
        d.open();
166
    }
167
168
    /*
169
     * (non-Javadoc) Method declared on Dialog.
170
     */
171
    protected void buttonPressed(int buttonId) {
172
        switch (buttonId) {
173
        case MORE_ID:
174
            handleMoreInfoPressed();
175
            break;
176
        case PLUGINS_ID:
177
            handlePluginInfoPressed();
178
            break;
179
        case COLUMNS_ID:
180
        	handleColumnsPressed();
181
        	break;
182
        default:
183
            super.buttonPressed(buttonId);
184
            break;
185
        }
186
    }
187
188
    /**
189
	 * 
190
	 */
191
	private void handleColumnsPressed() {
192
		ConfigureColumnsDialog d = new ConfigureColumnsDialog(this, table);
193
		d.open();
194
	}
195
196
	/*
197
     * (non-Javadoc) Method declared on Window.
198
     */
199
    protected void configureShell(Shell newShell) {
200
        super.configureShell(newShell);
201
        if (productName != null) {
202
			newShell.setText(NLS.bind(WorkbenchMessages.AboutFeaturesDialog_shellTitle, productName));
203
		}
204
205
        PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
206
				IWorkbenchHelpContextIds.ABOUT_FEATURES_DIALOG);
207
    }
208
209
    /**
210
     * Add buttons to the dialog's button bar.
211
     * 
212
     * Subclasses should override.
213
     * 
214
     * @param parent
215
     *            the button bar composite
216
     */
217
    protected void createButtonsForButtonBar(Composite parent) {
218
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
219
220
        moreButton = createButton(parent, MORE_ID, WorkbenchMessages.AboutFeaturesDialog_moreInfo, false);
221
        pluginsButton = createButton(parent, PLUGINS_ID, WorkbenchMessages.AboutFeaturesDialog_pluginsInfo, false); 
222
        createButton(parent, COLUMNS_ID, WorkbenchMessages.AboutFeaturesDialog_columns, false); 
223
        Label l = new Label(parent, SWT.NONE);
224
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
225
        GridLayout layout = (GridLayout) parent.getLayout();
226
        layout.numColumns++;
227
        layout.makeColumnsEqualWidth = false;
228
229
        Button b = createButton(parent, IDialogConstants.OK_ID,
230
                IDialogConstants.OK_LABEL, true);
231
        b.setFocus();
232
233
        TableItem[] items = table.getSelection();
234
        if (items.length > 0) {
235
			updateButtons((AboutBundleGroupData) items[0].getData());
236
		}
237
    }
238
239
    /**
240
     * Create the contents of the dialog (above the button bar).
241
     * 
242
     * Subclasses should overide.
243
     * 
244
     * @param parent  the parent composite to contain the dialog area
245
     * @return the dialog area control
246
     */
247
    protected Control createDialogArea(Composite parent) {
248
        setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND));
249
        setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT));
250
        getShell().addDisposeListener(new DisposeListener() {
251
            public void widgetDisposed(DisposeEvent e) {
252
                if (getHandCursor() != null) {
253
					getHandCursor().dispose();
254
				}
255
                if (getBusyCursor() != null) {
256
					getBusyCursor().dispose();
257
				}
258
            }
259
        });
260
261
        Composite outer = (Composite) super.createDialogArea(parent);
262
263
        createTable(outer);
264
        createInfoArea(outer);
265
        
266
        return outer;
267
    }
268
269
    /** 
270
     * Create the info area containing the image and text
271
     */
272
    protected void createInfoArea(Composite parent) {
273
        Font font = parent.getFont();
274
275
        infoArea = new Composite(parent, SWT.NULL);
276
        GridData data = new GridData(GridData.FILL, GridData.FILL, true, true);
277
        // need to provide space for arbitrary feature infos, not just the
278
        // one selected by default
279
        data.heightHint = convertVerticalDLUsToPixels(INFO_HEIGHT);
280
        infoArea.setLayoutData(data);
281
282
        GridLayout layout = new GridLayout();
283
        layout.numColumns = 2;
284
        infoArea.setLayout(layout);
285
286
        imageLabel = new Label(infoArea, SWT.NONE);
287
        data = new GridData(GridData.FILL, GridData.BEGINNING, false, false);
288
        data.widthHint = 32;
289
        data.heightHint = 32;
290
        imageLabel.setLayoutData(data);
291
        imageLabel.setFont(font);
292
293
        // text on the right
294
        text = new StyledText(infoArea, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
295
        text.setCaret(null);
296
        text.setFont(parent.getFont());
297
        data = new GridData(GridData.FILL, GridData.FILL, true, true);
298
        text.setLayoutData(data);
299
        text.setFont(font);
300
        text.setCursor(null);
301
        text.setBackground(infoArea.getBackground());
302
        addListeners(text);
303
304
        TableItem[] items = table.getSelection();
305
        if (items.length > 0) {
306
			updateInfoArea((AboutBundleGroupData) items[0].getData());
307
		}
308
    }
309
310
    /**
311
     * Create the table part of the dialog.
312
     *
313
     * @param parent  the parent composite to contain the dialog area
314
     */
315
    protected void createTable(Composite parent) {
316
        table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
317
                | SWT.FULL_SELECTION | SWT.BORDER);
318
        
319
        GridData gridData = new GridData(GridData.FILL, GridData.FILL, true,
320
                true);
321
        gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
322
        table.setLayoutData(gridData);
323
        table.setHeaderVisible(true);
324
        
325
        table.setLinesVisible(true);
326
        table.setFont(parent.getFont());
327
        table.addSelectionListener(new SelectionAdapter() {
328
            public void widgetSelected(SelectionEvent e) {
329
                AboutBundleGroupData info = (AboutBundleGroupData) e.item
330
                        .getData();
331
                updateInfoArea(info);
332
                updateButtons(info);
333
            }
334
        });
335
        
336
        int[] columnWidths = { convertHorizontalDLUsToPixels(120),
337
                convertHorizontalDLUsToPixels(120),
338
                convertHorizontalDLUsToPixels(70),
339
                convertHorizontalDLUsToPixels(130) };
340
341
        for (int i = 0; i < columnTitles.length; i++) {
342
            TableColumn tableColumn = new TableColumn(table, SWT.NULL);
343
            tableColumn.setWidth(columnWidths[i]);
344
            tableColumn.setText(columnTitles[i]);
345
            final int columnIndex = i;
346
            tableColumn.addSelectionListener(new SelectionAdapter() {
347
                public void widgetSelected(SelectionEvent e) {
348
                    sort(columnIndex);
349
                }
350
            });
351
        }
352
353
        // create a table row for each bundle group
354
        String selId = lastSelection == null ? null : lastSelection.getId();
355
        int sel = 0;
356
        for (int i = 0; i < bundleGroupInfos.length; i++) {
357
            if (bundleGroupInfos[i].getId().equals(selId)) {
358
				sel = i;
359
			}
360
361
            TableItem item = new TableItem(table, SWT.NULL);
362
            item.setText(createRow(bundleGroupInfos[i]));
363
            item.setData(bundleGroupInfos[i]);
364
        }
365
366
        // if an item was specified during construction, it should be
367
        // selected when the table is created
368
        if (bundleGroupInfos.length > 0) {
369
            table.setSelection(sel);
370
            table.showSelection();
371
        }
372
    }
373
374
    /**
375
     * @see Window#close()
376
     */
377
    public boolean close() {
378
        boolean ret = super.close();
379
380
        Iterator iter = cachedImages.values().iterator();
381
        while (iter.hasNext()) {
382
            Image image = (Image) iter.next();
383
            image.dispose();
384
        }
385
386
        return ret;
387
    }
388
389
    /**
390
     * Update the button enablement
391
     */
392
    private void updateButtons(AboutBundleGroupData info) {
393
        if (info == null) {
394
            moreButton.setEnabled(false);
395
            pluginsButton.setEnabled(false);
396
            return;
397
        }
398
399
        // Creating the feature map is too much just to determine enablement, so if
400
        // it doesn't already exist, just enable the buttons.  If this was the wrong
401
        // choice, then when the button is actually pressed an dialog will be opened. 
402
        if (featuresMap == null) {
403
            moreButton.setEnabled(true);
404
            pluginsButton.setEnabled(true);
405
            return;
406
        }
407
408
        moreButton.setEnabled(info.getLicenseUrl() != null);
409
        pluginsButton.setEnabled(true);
410
    }
411
412
    /**
413
     * Update the info area
414
     */
415
    private void updateInfoArea(AboutBundleGroupData info) {
416
        if (info == null) {
417
            imageLabel.setImage(null);
418
            text.setText(""); //$NON-NLS-1$
419
            return;
420
        }
421
422
        ImageDescriptor desc = info.getFeatureImage();
423
        Image image = (Image) cachedImages.get(desc);
424
        if (image == null && desc != null) {
425
            image = desc.createImage();
426
            cachedImages.put(desc, image);
427
        }
428
        imageLabel.setImage(image);
429
430
        String aboutText = info.getAboutText();
431
        setItem(null);
432
        if (aboutText != null) {
433
			setItem(scan(aboutText));
434
		}
435
436
        if (getItem() == null) {
437
			text.setText(WorkbenchMessages.AboutFeaturesDialog_noInformation);
438
		} else {
439
            text.setText(getItem().getText());
440
            text.setCursor(null);
441
            setLinkRanges(text, getItem().getLinkRanges());
442
        }
443
    }
444
445
    /**
446
     * Select the initial selection
447
     * 
448
     * @param info the info
449
     */
450
    public void setInitialSelection(AboutBundleGroupData info) {
451
        lastSelection = info;
452
    }
453
454
    /**
455
     * Sort the rows of the table based on the selected column.
456
     * 
457
     * @param column
458
     *            index of table column selected as sort criteria
459
     */
460
    private void sort(int column) {
461
        if (lastColumnChosen == column) {
462
			reverseSort = !reverseSort;
463
		} else {
464
            reverseSort = false;
465
            lastColumnChosen = column;
466
        }
467
468
        if (table.getItemCount() <= 1) {
469
			return;
470
		}
471
472
        // Remember the last selection
473
        int sel = table.getSelectionIndex();
474
        if (sel != -1) {
475
			lastSelection = bundleGroupInfos[sel];
476
		}
477
478
        switch (column) {
479
        case 0:
480
            AboutData.sortByProvider(reverseSort, bundleGroupInfos);
481
            break;
482
        case 1:
483
            AboutData.sortByName(reverseSort, bundleGroupInfos);
484
            break;
485
        case 2:
486
            AboutData.sortByVersion(reverseSort, bundleGroupInfos);
487
            break;
488
        case 3:
489
            AboutData.sortById(reverseSort, bundleGroupInfos);
490
            break;
491
        }
492
493
        refreshTable();
494
    }
495
496
    /**
497
     * Refresh the rows of the table based on the selected column. Maintain
498
     * selection from before sort action request.
499
     */
500
    private void refreshTable() {
501
        TableItem[] items = table.getItems();
502
503
        // create new order of table items
504
        for (int i = 0; i < items.length; i++) {
505
            items[i].setText(createRow(bundleGroupInfos[i]));
506
            items[i].setData(bundleGroupInfos[i]);
507
        }
508
509
        // Maintain the original selection
510
        int sel = -1;
511
        if (lastSelection != null) {
512
            String oldId = lastSelection.getId();
513
            for (int k = 0; k < bundleGroupInfos.length; k++) {
514
				if (oldId.equalsIgnoreCase(bundleGroupInfos[k].getId())) {
515
					sel = k;
516
				}
517
			}
518
519
            table.setSelection(sel);
520
            table.showSelection();
521
        }
522
523
        updateInfoArea(lastSelection);
524
    }
525
526
    /**
527
     * Return an array of strings containing the argument's information in the
528
     * proper order for this table's columns.
529
     * 
530
     * @param info
531
     *            the source information for the new row, must not be null
532
     */
533
    private static String[] createRow(AboutBundleGroupData info) {
534
        return new String[] { info.getProviderName(), info.getName(),
535
                info.getVersion(), info.getId() };
536
    }
50
    }
537
}
51
}
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/AboutDialog.java (-56 / +24 lines)
Lines 19-24 Link Here
19
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.core.runtime.Platform;
20
import org.eclipse.jface.action.MenuManager;
20
import org.eclipse.jface.action.MenuManager;
21
import org.eclipse.jface.dialogs.IDialogConstants;
21
import org.eclipse.jface.dialogs.IDialogConstants;
22
import org.eclipse.jface.dialogs.TrayDialog;
22
import org.eclipse.jface.resource.ImageDescriptor;
23
import org.eclipse.jface.resource.ImageDescriptor;
23
import org.eclipse.jface.resource.JFaceColors;
24
import org.eclipse.jface.resource.JFaceColors;
24
import org.eclipse.osgi.util.NLS;
25
import org.eclipse.osgi.util.NLS;
Lines 35-41 Link Here
35
import org.eclipse.swt.events.SelectionAdapter;
36
import org.eclipse.swt.events.SelectionAdapter;
36
import org.eclipse.swt.events.SelectionEvent;
37
import org.eclipse.swt.events.SelectionEvent;
37
import org.eclipse.swt.graphics.Color;
38
import org.eclipse.swt.graphics.Color;
38
import org.eclipse.swt.graphics.Cursor;
39
import org.eclipse.swt.graphics.GC;
39
import org.eclipse.swt.graphics.GC;
40
import org.eclipse.swt.graphics.Image;
40
import org.eclipse.swt.graphics.Image;
41
import org.eclipse.swt.graphics.Point;
41
import org.eclipse.swt.graphics.Point;
Lines 47-72 Link Here
47
import org.eclipse.swt.widgets.Control;
47
import org.eclipse.swt.widgets.Control;
48
import org.eclipse.swt.widgets.Label;
48
import org.eclipse.swt.widgets.Label;
49
import org.eclipse.swt.widgets.Shell;
49
import org.eclipse.swt.widgets.Shell;
50
import org.eclipse.ui.IWorkbenchWindow;
50
import org.eclipse.ui.PlatformUI;
51
import org.eclipse.ui.PlatformUI;
51
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
52
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
52
import org.eclipse.ui.internal.ProductProperties;
53
import org.eclipse.ui.internal.ProductProperties;
53
import org.eclipse.ui.internal.WorkbenchMessages;
54
import org.eclipse.ui.internal.WorkbenchMessages;
54
import org.eclipse.ui.internal.about.AboutBundleGroupData;
55
import org.eclipse.ui.internal.about.AboutBundleGroupData;
55
import org.eclipse.ui.internal.about.AboutFeaturesButtonManager;
56
import org.eclipse.ui.internal.about.AboutFeaturesButtonManager;
57
import org.eclipse.ui.internal.about.AboutItem;
58
import org.eclipse.ui.internal.about.AboutTextManager;
59
import org.eclipse.ui.internal.about.InstallationDialog;
56
import org.eclipse.ui.menus.CommandContributionItem;
60
import org.eclipse.ui.menus.CommandContributionItem;
57
import org.eclipse.ui.menus.CommandContributionItemParameter;
61
import org.eclipse.ui.menus.CommandContributionItemParameter;
58
62
59
/**
63
/**
60
 * Displays information about the product.
64
 * Displays information about the product.
61
 */
65
 */
62
public class AboutDialog extends ProductInfoDialog {
66
public class AboutDialog extends TrayDialog {
63
    private final static int MAX_IMAGE_WIDTH_FOR_TEXT = 250;
67
    private final static int MAX_IMAGE_WIDTH_FOR_TEXT = 250;
64
68
65
    private final static int FEATURES_ID = IDialogConstants.CLIENT_ID + 1;
69
    private final static int DETAILS_ID = IDialogConstants.CLIENT_ID + 1;
66
67
    private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
68
69
    private final static int INFO_ID = IDialogConstants.CLIENT_ID + 3;
70
70
71
    private String productName;
71
    private String productName;
72
72
Lines 78-86 Link Here
78
78
79
    private AboutFeaturesButtonManager buttonManager = new AboutFeaturesButtonManager();
79
    private AboutFeaturesButtonManager buttonManager = new AboutFeaturesButtonManager();
80
80
81
    // TODO should the styled text be disposed? if not then it likely
82
    //      doesn't need to be a member
83
    private StyledText text;
81
    private StyledText text;
82
    
83
    private AboutTextManager aboutTextManager;
84
84
85
    /**
85
    /**
86
     * Create an instance of the AboutDialog for the given window.
86
     * Create an instance of the AboutDialog for the given window.
Lines 117-141 Link Here
117
     */
117
     */
118
    protected void buttonPressed(int buttonId) {
118
    protected void buttonPressed(int buttonId) {
119
        switch (buttonId) {
119
        switch (buttonId) {
120
        case FEATURES_ID:
120
        case DETAILS_ID:
121
			BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
121
			BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
122
				public void run() {
122
				public void run() {
123
		            new AboutFeaturesDialog(getShell(), productName, bundleGroupInfos)
123
					IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
124
		                    .open();
124
					InstallationDialog dialog = new InstallationDialog(getShell(), workbenchWindow);
125
				}
125
					dialog.open();	
126
			});
127
            break;
128
        case PLUGINS_ID:
129
			BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
130
				public void run() {
131
		            new AboutPluginsDialog(getShell(), productName).open();
132
				}
133
			});
134
            break;
135
        case INFO_ID:
136
			BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
137
				public void run() {
138
		            new AboutSystemDialog(getShell()).open();
139
				}
126
				}
140
			});
127
			});
141
            break;
128
            break;
Lines 176-189 Link Here
176
    protected void createButtonsForButtonBar(Composite parent) {
163
    protected void createButtonsForButtonBar(Composite parent) {
177
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
164
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
178
165
179
        // bug 64232: the feature details button should only be created if there
166
        createButton(parent, DETAILS_ID, WorkbenchMessages.AboutDialog_DetailsButton, false); 
180
        // are features to show
181
        if (bundleGroupInfos != null && bundleGroupInfos.length > 0) {
182
			createButton(parent, FEATURES_ID, WorkbenchMessages.AboutDialog_featureInfo, false);
183
		} 
184
185
        createButton(parent, PLUGINS_ID, WorkbenchMessages.AboutDialog_pluginInfo, false);
186
        createButton(parent, INFO_ID, WorkbenchMessages.AboutDialog_systemInfo, false); 
187
167
188
        Label l = new Label(parent, SWT.NONE);
168
        Label l = new Label(parent, SWT.NONE);
189
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
169
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Lines 206-226 Link Here
206
     * @return the dialog area control
186
     * @return the dialog area control
207
     */
187
     */
208
    protected Control createDialogArea(Composite parent) {
188
    protected Control createDialogArea(Composite parent) {
209
        final Cursor hand = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
189
         // brand the about box if there is product info
210
        final Cursor busy = new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT);
211
        setHandCursor(hand);
212
        setBusyCursor(busy);
213
        getShell().addDisposeListener(new DisposeListener() {
214
            public void widgetDisposed(DisposeEvent e) {
215
                setHandCursor(null);
216
                hand.dispose();
217
                setBusyCursor(null);
218
                busy.dispose();
219
            }
220
        });
221
222
        // brand the about box if there is product info
223
        Image aboutImage = null;
190
        Image aboutImage = null;
191
        AboutItem item = null;
224
        if (product != null) {
192
        if (product != null) {
225
            ImageDescriptor imageDescriptor = ProductProperties
193
            ImageDescriptor imageDescriptor = ProductProperties
226
                    .getAboutImage(product);
194
                    .getAboutImage(product);
Lines 233-239 Link Here
233
                    || aboutImage.getBounds().width <= MAX_IMAGE_WIDTH_FOR_TEXT) {
201
                    || aboutImage.getBounds().width <= MAX_IMAGE_WIDTH_FOR_TEXT) {
234
                String aboutText = ProductProperties.getAboutText(product);
202
                String aboutText = ProductProperties.getAboutText(product);
235
                if (aboutText != null) {
203
                if (aboutText != null) {
236
					setItem(scan(aboutText));
204
					item = AboutTextManager.scan(aboutText);
237
				}
205
				}
238
            }
206
            }
239
207
Lines 276-282 Link Here
276
        topContainer.setForeground(foreground);
244
        topContainer.setForeground(foreground);
277
245
278
        layout = new GridLayout();
246
        layout = new GridLayout();
279
        layout.numColumns = (aboutImage == null || getItem() == null ? 1 : 2);
247
        layout.numColumns = (aboutImage == null || item == null ? 1 : 2);
280
        layout.marginWidth = 0;
248
        layout.marginWidth = 0;
281
        layout.marginHeight = 0;
249
        layout.marginHeight = 0;
282
        layout.verticalSpacing = 0;
250
        layout.verticalSpacing = 0;
Lines 318-324 Link Here
318
        data.heightHint = topContainerHeightHint;
286
        data.heightHint = topContainerHeightHint;
319
        topContainer.setLayoutData(data);
287
        topContainer.setLayoutData(data);
320
        
288
        
321
        if (getItem() != null) {
289
        if (item != null) {
322
        	final int minWidth = 400; // This value should really be calculated
290
        	final int minWidth = 400; // This value should really be calculated
323
        	// from the computeSize(SWT.DEFAULT,
291
        	// from the computeSize(SWT.DEFAULT,
324
        	// SWT.DEFAULT) of all the
292
        	// SWT.DEFAULT) of all the
Lines 340-351 Link Here
340
    		text = new StyledText(textComposite, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
308
    		text = new StyledText(textComposite, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
341
    		text.setCaret(null);
309
    		text.setCaret(null);
342
            text.setFont(parent.getFont());
310
            text.setFont(parent.getFont());
343
            text.setText(getItem().getText());
311
            text.setText(item.getText());
344
            text.setCursor(null);
312
            text.setCursor(null);
345
            text.setBackground(background);
313
            text.setBackground(background);
346
            text.setForeground(foreground);
314
            text.setForeground(foreground);
347
            setLinkRanges(text, getItem().getLinkRanges());
315
            
348
            addListeners(text);
316
            aboutTextManager = new AboutTextManager(text);
317
            aboutTextManager.setItem(item);
349
            
318
            
350
            createTextMenu();
319
            createTextMenu();
351
            
320
            
Lines 487-494 Link Here
487
                        .getData();
456
                        .getData();
488
457
489
                AboutFeaturesDialog d = new AboutFeaturesDialog(getShell(),
458
                AboutFeaturesDialog d = new AboutFeaturesDialog(getShell(),
490
                        productName, groupInfos);
459
                        productName, groupInfos, selection);
491
                d.setInitialSelection(selection);
492
                d.open();
460
                d.open();
493
            }
461
            }
494
        });
462
        });
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/BundleSigningTray.java (-301 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2008 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
12
package org.eclipse.ui.internal.dialogs;
13
14
import java.io.IOException;
15
import java.security.GeneralSecurityException;
16
import java.security.cert.Certificate;
17
import java.security.cert.X509Certificate;
18
import java.text.DateFormat;
19
import java.util.ArrayList;
20
import java.util.Date;
21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Map;
24
import java.util.Properties;
25
import java.util.StringTokenizer;
26
import java.util.Map.Entry;
27
28
import org.eclipse.core.runtime.IProgressMonitor;
29
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.OperationCanceledException;
31
import org.eclipse.core.runtime.Status;
32
import org.eclipse.core.runtime.jobs.Job;
33
import org.eclipse.jface.dialogs.Dialog;
34
import org.eclipse.jface.dialogs.DialogTray;
35
import org.eclipse.jface.dialogs.TrayDialog;
36
import org.eclipse.jface.resource.JFaceResources;
37
import org.eclipse.osgi.signedcontent.SignedContent;
38
import org.eclipse.osgi.signedcontent.SignedContentFactory;
39
import org.eclipse.osgi.signedcontent.SignerInfo;
40
import org.eclipse.osgi.util.NLS;
41
import org.eclipse.swt.SWT;
42
import org.eclipse.swt.custom.StyledText;
43
import org.eclipse.swt.graphics.Color;
44
import org.eclipse.swt.graphics.GC;
45
import org.eclipse.swt.graphics.Point;
46
import org.eclipse.swt.layout.GridData;
47
import org.eclipse.swt.layout.GridLayout;
48
import org.eclipse.swt.widgets.Composite;
49
import org.eclipse.swt.widgets.Control;
50
import org.eclipse.swt.widgets.Display;
51
import org.eclipse.swt.widgets.Label;
52
import org.eclipse.swt.widgets.Shell;
53
import org.eclipse.swt.widgets.Text;
54
import org.eclipse.ui.internal.WorkbenchMessages;
55
import org.eclipse.ui.internal.WorkbenchPlugin;
56
import org.eclipse.ui.internal.about.AboutBundleData;
57
import org.eclipse.ui.statushandlers.StatusManager;
58
import org.osgi.framework.BundleContext;
59
import org.osgi.framework.ServiceReference;
60
61
/**
62
 * @since 3.3
63
 *
64
 */
65
public class BundleSigningTray extends DialogTray {
66
67
68
	private Text date;
69
	private StyledText certificate;
70
	private AboutBundleData data;
71
	private TrayDialog dialog;
72
	
73
	/**
74
	 * 
75
	 */
76
	public BundleSigningTray(TrayDialog dialog) {
77
		this.dialog = dialog;
78
	}
79
	
80
	public void setData(AboutBundleData data) {
81
		this.data = data;
82
		startJobs();
83
	}
84
85
	/* (non-Javadoc)
86
	 * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets.Composite)
87
	 */
88
	protected Control createContents(Composite parent) {
89
		Composite content = new Composite(parent, SWT.NONE);
90
		content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
91
		GridLayout layout = new GridLayout(2, false);
92
		content.setLayout(layout);
93
		// date
94
		Color backgroundColor = parent.getDisplay().getSystemColor(
95
				SWT.COLOR_WIDGET_BACKGROUND);
96
		{
97
			Label label = new Label(content, SWT.NONE);
98
			label.setText(WorkbenchMessages.BundleSigningTray_Signing_Date); 
99
			GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
100
			date = new Text(content, SWT.READ_ONLY);
101
			GC gc = new GC(date);
102
			gc.setFont(JFaceResources.getDialogFont());
103
			Point size = gc.stringExtent(DateFormat.getDateTimeInstance().format(new Date()));
104
			data.widthHint = size.x;
105
			gc.dispose();
106
			date.setText(WorkbenchMessages.BundleSigningTray_Working); 
107
			date.setLayoutData(data);
108
			date.setBackground(backgroundColor);
109
		}
110
		// signer
111
		{
112
			Label label = new Label(content, SWT.NONE);
113
			label.setText(WorkbenchMessages.BundleSigningTray_Signing_Certificate); 
114
			GridData data = new GridData(SWT.BEGINNING, SWT.BEGINNING, true, false);
115
			data.horizontalSpan = 2;
116
			data = new GridData(SWT.FILL, SWT.FILL, true, true);
117
			data.horizontalSpan = 2;
118
			certificate = new StyledText(content, SWT.READ_ONLY | SWT.MULTI | SWT.WRAP);
119
			certificate.setText(WorkbenchMessages.BundleSigningTray_Working); 
120
			certificate.setLayoutData(data);
121
		}
122
		
123
		// problems
124
//		{
125
//			Label label = new Label(content, SWT.NONE);
126
//			label.setText("Problems:"); //$NON-NLS-1$
127
//
128
//		}
129
		Dialog.applyDialogFont(content);
130
131
		startJobs(); // start the jobs that will prime the content
132
133
		return content;
134
	}
135
	
136
	/**
137
	 * 
138
	 */
139
	private void startJobs() {
140
		if (!isOpen())
141
			return;
142
		certificate.setText(WorkbenchMessages.BundleSigningTray_Working); 
143
		date.setText(WorkbenchMessages.BundleSigningTray_Working); 
144
		final BundleContext bundleContext = WorkbenchPlugin.getDefault()
145
				.getBundleContext();
146
		final ServiceReference factoryRef = bundleContext
147
				.getServiceReference(SignedContentFactory.class.getName());
148
		if (factoryRef == null) {
149
			StatusManager.getManager().handle(
150
					new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
151
							WorkbenchMessages.BundleSigningTray_Cant_Find_Service), 
152
					StatusManager.LOG);
153
			return;
154
		}
155
156
		final SignedContentFactory contentFactory = (SignedContentFactory) bundleContext
157
				.getService(factoryRef);
158
		if (contentFactory == null) {
159
			StatusManager.getManager().handle(
160
					new Status(IStatus.WARNING, WorkbenchPlugin.PI_WORKBENCH,
161
							WorkbenchMessages.BundleSigningTray_Cant_Find_Service), 
162
					StatusManager.LOG);
163
			return;
164
		}
165
166
		final AboutBundleData myData = data;
167
		final Job signerJob = new Job(NLS.bind(WorkbenchMessages.BundleSigningTray_Determine_Signer_For, myData.getId())) { 
168
169
			protected IStatus run(IProgressMonitor monitor) {
170
				try {
171
					if (myData != data)
172
						return Status.OK_STATUS;
173
					SignedContent signedContent = contentFactory.getSignedContent(myData
174
							.getBundle());
175
					if (myData != data)
176
						return Status.OK_STATUS;
177
					SignerInfo[] signers = signedContent.getSignerInfos();
178
					final String signerText, dateText;
179
					final Shell dialogShell = dialog.getShell();
180
					if (!isOpen() && BundleSigningTray.this.data == myData)
181
						return Status.OK_STATUS;
182
183
					if (signers.length == 0) {
184
						signerText = WorkbenchMessages.BundleSigningTray_Unsigned; 
185
						dateText = WorkbenchMessages.BundleSigningTray_Unsigned; 
186
					} else {
187
						Properties [] certs = parseCerts(signers[0].getCertificateChain());
188
						if (certs.length == 0)
189
							signerText = WorkbenchMessages.BundleSigningTray_Unknown; 
190
						else {
191
							StringBuffer buffer = new StringBuffer();
192
							for (Iterator i = certs[0].entrySet().iterator(); i.hasNext(); ) {
193
								Map.Entry entry = (Entry) i.next();
194
								buffer.append(entry.getKey());
195
								buffer.append('=');
196
								buffer.append(entry.getValue());
197
								if (i.hasNext())
198
									buffer.append('\n');
199
							}
200
							signerText = buffer.toString();
201
						}
202
203
						Date signDate = signedContent.getSigningTime(signers[0]);
204
						if (signDate != null)
205
							dateText = DateFormat.getDateTimeInstance().format(
206
									signDate);
207
						else
208
							dateText = WorkbenchMessages.BundleSigningTray_Unknown; 
209
					}
210
					
211
					Display display = dialogShell.getDisplay();
212
					display.asyncExec(new Runnable() {
213
214
						public void run() {
215
							// check to see if the tray is still visible and if we're still looking at the same item
216
							if (!isOpen() && BundleSigningTray.this.data != myData)
217
								return;
218
							certificate.setText(signerText);
219
							date.setText(dateText);
220
						}
221
					});
222
223
				} catch (IOException e) {
224
					return new Status(IStatus.ERROR,
225
							WorkbenchPlugin.PI_WORKBENCH, e.getMessage(), e);
226
				} catch (GeneralSecurityException e) {
227
					return new Status(IStatus.ERROR,
228
							WorkbenchPlugin.PI_WORKBENCH, e.getMessage(), e);
229
				}
230
				return Status.OK_STATUS;
231
			}
232
		};
233
		signerJob.setSystem(true);
234
		signerJob.belongsTo(signerJob);
235
		signerJob.schedule();
236
237
		Job cleanup = new Job(WorkbenchMessages.BundleSigningTray_Unget_Signing_Service) { 
238
239
			protected IStatus run(IProgressMonitor monitor) {
240
				try {
241
					getJobManager().join(signerJob, monitor);
242
				} catch (OperationCanceledException e) {
243
				} catch (InterruptedException e) {
244
				}
245
				bundleContext.ungetService(factoryRef);
246
				return Status.OK_STATUS;
247
			}
248
		};
249
		cleanup.setSystem(true);
250
		cleanup.schedule();
251
252
	}
253
254
	/**
255
	 * 
256
	 */
257
	private boolean isOpen() {
258
		return certificate != null && !certificate.isDisposed();
259
	}
260
261
	private Properties[] parseCerts(Certificate[] chain) {
262
		List certs = new ArrayList(chain.length);
263
		for (int i = 0; i < chain.length; i++) {
264
			if (!(chain[i] instanceof X509Certificate))
265
				continue;
266
			Map cert = parseCert(((X509Certificate) chain[i]).getSubjectDN().getName());
267
			if (cert != null)
268
				certs.add(cert);
269
		}
270
		return (Properties []) certs.toArray(new Properties[certs.size()]);
271
272
273
	}
274
275
	/**
276
	 * @param certString
277
	 * @return
278
	 */
279
	private Properties parseCert(String certString) {
280
		StringTokenizer toker = new StringTokenizer(certString, ","); //$NON-NLS-1$
281
		Properties cert = new Properties();
282
		while (toker.hasMoreTokens()) {
283
			String pair = toker.nextToken();
284
			int idx = pair.indexOf('=');
285
			if (idx > 0 && idx < pair.length() - 2) {
286
				String key = pair.substring(0, idx).trim();
287
				String value = pair.substring(idx + 1).trim();
288
				if (value.length() > 2) {
289
					if (value.charAt(0) == '\"')
290
						value = value.substring(1);
291
292
					if (value.charAt(value.length() - 1) == '\"')
293
						value = value.substring(0, value.length() - 1);
294
				}
295
				cert.setProperty(key, value);
296
			}
297
		}
298
		return cert;
299
	}
300
301
}
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/ProductInfoDialog.java (-478 lines)
Removed Link Here
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
 *******************************************************************************/
11
package org.eclipse.ui.internal.dialogs;
12
13
import java.io.IOException;
14
import java.net.MalformedURLException;
15
import java.net.URL;
16
import java.util.ArrayList;
17
import java.util.StringTokenizer;
18
19
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.jface.dialogs.TrayDialog;
22
import org.eclipse.jface.resource.JFaceColors;
23
import org.eclipse.osgi.util.NLS;
24
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.custom.StyleRange;
26
import org.eclipse.swt.custom.StyledText;
27
import org.eclipse.swt.events.KeyAdapter;
28
import org.eclipse.swt.events.KeyEvent;
29
import org.eclipse.swt.events.MouseAdapter;
30
import org.eclipse.swt.events.MouseEvent;
31
import org.eclipse.swt.events.MouseMoveListener;
32
import org.eclipse.swt.events.TraverseEvent;
33
import org.eclipse.swt.events.TraverseListener;
34
import org.eclipse.swt.graphics.Color;
35
import org.eclipse.swt.graphics.Cursor;
36
import org.eclipse.swt.graphics.Point;
37
import org.eclipse.swt.widgets.Shell;
38
import org.eclipse.ui.PartInitException;
39
import org.eclipse.ui.PlatformUI;
40
import org.eclipse.ui.browser.IWebBrowser;
41
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
42
import org.eclipse.ui.internal.WorkbenchMessages;
43
import org.eclipse.ui.internal.WorkbenchPlugin;
44
import org.eclipse.ui.internal.about.AboutItem;
45
import org.eclipse.ui.internal.misc.StatusUtil;
46
import org.eclipse.ui.statushandlers.StatusManager;
47
48
/**
49
 * Abstract superclass of about dialogs 
50
 */
51
52
public abstract class ProductInfoDialog extends TrayDialog {
53
54
    private AboutItem item;
55
56
    private Cursor handCursor;
57
58
    private Cursor busyCursor;
59
60
    private boolean mouseDown = false;
61
62
    private boolean dragEvent = false;
63
64
    /**
65
     * Create an instance of this Dialog
66
     */
67
    public ProductInfoDialog(Shell parentShell) {
68
        super(parentShell);
69
    }
70
71
    /**
72
     * Adds listeners to the given styled text
73
     */
74
    protected void addListeners(StyledText styledText) {
75
        styledText.addMouseListener(new MouseAdapter() {
76
            public void mouseDown(MouseEvent e) {
77
                if (e.button != 1) {
78
                    return;
79
                }
80
                mouseDown = true;
81
            }
82
83
            public void mouseUp(MouseEvent e) {
84
                mouseDown = false;
85
                StyledText text = (StyledText) e.widget;
86
                int offset = text.getCaretOffset();
87
                if (dragEvent) {
88
                    // don't activate a link during a drag/mouse up operation
89
                    dragEvent = false;
90
                    if (item != null && item.isLinkAt(offset)) {
91
                        text.setCursor(handCursor);
92
                    }
93
                } else if (item != null && item.isLinkAt(offset)) {
94
                    text.setCursor(busyCursor);
95
                    openLink(item.getLinkAt(offset));
96
                    StyleRange selectionRange = getCurrentRange(text);
97
                    text.setSelectionRange(selectionRange.start,
98
                            selectionRange.length);
99
                    text.setCursor(null);
100
                }
101
            }
102
        });
103
104
        styledText.addMouseMoveListener(new MouseMoveListener() {
105
            public void mouseMove(MouseEvent e) {
106
                // Do not change cursor on drag events
107
                if (mouseDown) {
108
                    if (!dragEvent) {
109
                        StyledText text = (StyledText) e.widget;
110
                        text.setCursor(null);
111
                    }
112
                    dragEvent = true;
113
                    return;
114
                }
115
                StyledText text = (StyledText) e.widget;
116
                int offset = -1;
117
                try {
118
                    offset = text.getOffsetAtLocation(new Point(e.x, e.y));
119
                } catch (IllegalArgumentException ex) {
120
                    // leave value as -1
121
                }
122
                if (offset == -1) {
123
					text.setCursor(null);
124
				} else if (item != null && item.isLinkAt(offset)) {
125
					text.setCursor(handCursor);
126
				} else {
127
					text.setCursor(null);
128
				}
129
            }
130
        });
131
132
        styledText.addTraverseListener(new TraverseListener() {
133
            public void keyTraversed(TraverseEvent e) {
134
                StyledText text = (StyledText) e.widget;
135
                switch (e.detail) {
136
                case SWT.TRAVERSE_ESCAPE:
137
                    e.doit = true;
138
                    break;
139
                case SWT.TRAVERSE_TAB_NEXT:
140
                    //Previously traverse out in the backward direction?
141
                    Point nextSelection = text.getSelection();
142
                    int charCount = text.getCharCount();
143
                    if ((nextSelection.x == charCount)
144
                            && (nextSelection.y == charCount)) {
145
                        text.setSelection(0);
146
                    }
147
                    StyleRange nextRange = findNextRange(text);
148
                    if (nextRange == null) {
149
                        // Next time in start at beginning, also used by 
150
                        // TRAVERSE_TAB_PREVIOUS to indicate we traversed out
151
                        // in the forward direction
152
                        text.setSelection(0);
153
                        e.doit = true;
154
                    } else {
155
                        text.setSelectionRange(nextRange.start,
156
                                nextRange.length);
157
                        e.doit = true;
158
                        e.detail = SWT.TRAVERSE_NONE;
159
                    }
160
                    break;
161
                case SWT.TRAVERSE_TAB_PREVIOUS:
162
                    //Previously traverse out in the forward direction?
163
                    Point previousSelection = text.getSelection();
164
                    if ((previousSelection.x == 0)
165
                            && (previousSelection.y == 0)) {
166
						text.setSelection(text.getCharCount());
167
					}
168
                    StyleRange previousRange = findPreviousRange(text);
169
                    if (previousRange == null) {
170
                        // Next time in start at the end, also used by 
171
                        // TRAVERSE_TAB_NEXT to indicate we traversed out
172
                        // in the backward direction
173
                        text.setSelection(text.getCharCount());
174
                        e.doit = true;
175
                    } else {
176
                        text.setSelectionRange(previousRange.start,
177
                                previousRange.length);
178
                        e.doit = true;
179
                        e.detail = SWT.TRAVERSE_NONE;
180
                    }
181
                    break;
182
                default:
183
                    break;
184
                }
185
            }
186
        });
187
188
        //Listen for Tab and Space to allow keyboard navigation
189
        styledText.addKeyListener(new KeyAdapter() {
190
            public void keyPressed(KeyEvent event) {
191
                StyledText text = (StyledText) event.widget;
192
                if (event.character == ' ' || event.character == SWT.CR) {
193
                    if (item != null) {
194
                        //Be sure we are in the selection
195
                        int offset = text.getSelection().x + 1;
196
197
                        if (item.isLinkAt(offset)) {
198
                            text.setCursor(busyCursor);
199
                            openLink(item.getLinkAt(offset));
200
                            StyleRange selectionRange = getCurrentRange(text);
201
                            text.setSelectionRange(selectionRange.start,
202
                                    selectionRange.length);
203
                            text.setCursor(null);
204
                        }
205
                    }
206
                    return;
207
                }
208
            }
209
        });
210
    }
211
212
    /**
213
     * Gets the busy cursor.
214
     * @return the busy cursor
215
     */
216
    protected Cursor getBusyCursor() {
217
        return busyCursor;
218
    }
219
220
    /**
221
     * Sets the busy cursor.
222
     * @param busyCursor the busy cursor
223
     */
224
    protected void setBusyCursor(Cursor busyCursor) {
225
        this.busyCursor = busyCursor;
226
    }
227
228
    /**
229
     * Gets the hand cursor.
230
     * @return Returns a hand cursor
231
     */
232
    protected Cursor getHandCursor() {
233
        return handCursor;
234
    }
235
236
    /**
237
     * Sets the hand cursor.
238
     * @param handCursor The hand cursor to set
239
     */
240
    protected void setHandCursor(Cursor handCursor) {
241
        this.handCursor = handCursor;
242
    }
243
244
    /**
245
     * Gets the about item.
246
     * @return the about item
247
     */
248
    protected AboutItem getItem() {
249
        return item;
250
    }
251
252
    /**
253
     * Sets the about item.
254
     * @param item about item
255
     */
256
    protected void setItem(AboutItem item) {
257
        this.item = item;
258
    }
259
260
    /**
261
     * Find the range of the current selection.
262
     */
263
    protected StyleRange getCurrentRange(StyledText text) {
264
        StyleRange[] ranges = text.getStyleRanges();
265
        int currentSelectionEnd = text.getSelection().y;
266
        int currentSelectionStart = text.getSelection().x;
267
268
        for (int i = 0; i < ranges.length; i++) {
269
            if ((currentSelectionStart >= ranges[i].start)
270
                    && (currentSelectionEnd <= (ranges[i].start + ranges[i].length))) {
271
                return ranges[i];
272
            }
273
        }
274
        return null;
275
    }
276
277
    /**
278
     * Find the next range after the current 
279
     * selection.
280
     */
281
    protected StyleRange findNextRange(StyledText text) {
282
        StyleRange[] ranges = text.getStyleRanges();
283
        int currentSelectionEnd = text.getSelection().y;
284
285
        for (int i = 0; i < ranges.length; i++) {
286
            if (ranges[i].start >= currentSelectionEnd) {
287
				return ranges[i];
288
			}
289
        }
290
        return null;
291
    }
292
293
    /**
294
     * Find the previous range before the current selection.
295
     */
296
    protected StyleRange findPreviousRange(StyledText text) {
297
        StyleRange[] ranges = text.getStyleRanges();
298
        int currentSelectionStart = text.getSelection().x;
299
300
        for (int i = ranges.length - 1; i > -1; i--) {
301
            if ((ranges[i].start + ranges[i].length - 1) < currentSelectionStart) {
302
				return ranges[i];
303
			}
304
        }
305
        return null;
306
    }
307
308
    /**
309
     * display an error message
310
     */
311
    private void openWebBrowserError(final String href, final Throwable t) {
312
        String title = WorkbenchMessages.ProductInfoDialog_errorTitle;
313
		String msg = NLS.bind(
314
				WorkbenchMessages.ProductInfoDialog_unableToOpenWebBrowser,
315
				href);
316
		IStatus status = WorkbenchPlugin.getStatus(t);
317
		StatusUtil.handleStatus(status, title + ": " + msg, StatusManager.SHOW, //$NON-NLS-1$
318
				getShell());
319
    }
320
321
    /**
322
     * Open a link
323
     */
324
    protected void openLink(String href) {
325
        // format the href for an html file (file:///<filename.html>
326
        // required for Mac only.
327
        if (href.startsWith("file:")) { //$NON-NLS-1$
328
            href = href.substring(5);
329
            while (href.startsWith("/")) { //$NON-NLS-1$
330
                href = href.substring(1);
331
            }
332
            href = "file:///" + href; //$NON-NLS-1$
333
        }
334
		IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
335
		try {
336
			IWebBrowser browser = support.getExternalBrowser();
337
			browser.openURL(new URL(urlEncodeForSpaces(href.toCharArray())));
338
		}
339
		catch (MalformedURLException e) {
340
			openWebBrowserError(href, e);
341
		}
342
		catch (PartInitException e) {
343
			openWebBrowserError(href, e);
344
		}
345
    }
346
347
    /**
348
     * This method encodes the url, removes the spaces from the url and replaces
349
     * the same with <code>"%20"</code>. This method is required to fix Bug
350
     * 77840.
351
     * 
352
     * @since 3.0.2
353
     */
354
    private String urlEncodeForSpaces(char[] input) {
355
       StringBuffer retu = new StringBuffer(input.length);
356
       for (int i = 0; i < input.length; i++) {
357
           if (input[i] == ' ') {
358
			retu.append("%20"); //$NON-NLS-1$
359
		} else {
360
			retu.append(input[i]);
361
		}
362
       }
363
       return retu.toString();
364
    }
365
366
    /**
367
     * Open a browser with the argument title on the argument url.  If the url refers to a
368
     * resource within a bundle, then a temp copy of the file will be extracted and opened.
369
     * @see <code>Platform.asLocalUrl</code>
370
     * @param url The target url to be displayed, null will be safely ignored
371
     * @return true if the url was successfully displayed and false otherwise
372
     */
373
    protected boolean openBrowser(URL url) {
374
        if (url != null) {
375
			try {
376
                url = Platform.asLocalURL(url);
377
            } catch (IOException e) {
378
                return false;
379
            }
380
		}
381
        if (url == null) {
382
			return false;
383
		}
384
        openLink(url.toString());
385
        return true;
386
    }
387
388
    /**
389
     * Sets the styled text's bold ranges
390
     */
391
    protected void setBoldRanges(StyledText styledText, int[][] boldRanges) {
392
        for (int i = 0; i < boldRanges.length; i++) {
393
            StyleRange r = new StyleRange(boldRanges[i][0], boldRanges[i][1],
394
                    null, null, SWT.BOLD);
395
            styledText.setStyleRange(r);
396
        }
397
    }
398
399
    /**
400
     * Sets the styled text's link (blue) ranges
401
     */
402
    protected void setLinkRanges(StyledText styledText, int[][] linkRanges) {
403
        Color fg = JFaceColors.getHyperlinkText(styledText.getShell()
404
                .getDisplay());
405
        for (int i = 0; i < linkRanges.length; i++) {
406
            StyleRange r = new StyleRange(linkRanges[i][0], linkRanges[i][1],
407
                    fg, null);
408
            styledText.setStyleRange(r);
409
        }
410
    }
411
412
    /**
413
     * Scan the contents of the about text
414
     */
415
    protected AboutItem scan(String s) {
416
        ArrayList linkRanges = new ArrayList();
417
        ArrayList links = new ArrayList();
418
        
419
        // slightly modified version of jface url detection
420
        // see org.eclipse.jface.text.hyperlink.URLHyperlinkDetector
421
        
422
		int urlSeparatorOffset= s.indexOf("://"); //$NON-NLS-1$
423
		while(urlSeparatorOffset >= 0) {
424
	
425
			boolean startDoubleQuote= false;
426
	
427
			// URL protocol (left to "://")
428
			int urlOffset= urlSeparatorOffset;
429
			char ch;
430
			do {
431
				urlOffset--;
432
				ch= ' ';
433
				if (urlOffset > -1)
434
					ch= s.charAt(urlOffset);
435
				startDoubleQuote= ch == '"';
436
			} while (Character.isUnicodeIdentifierStart(ch));
437
			urlOffset++;
438
			
439
	
440
			// Right to "://"
441
			StringTokenizer tokenizer= new StringTokenizer(s.substring(urlSeparatorOffset + 3), " \t\n\r\f<>", false); //$NON-NLS-1$
442
			if (!tokenizer.hasMoreTokens())
443
				return null;
444
	
445
			int urlLength= tokenizer.nextToken().length() + 3 + urlSeparatorOffset - urlOffset;
446
	
447
			if (startDoubleQuote) {
448
				int endOffset= -1;
449
				int nextDoubleQuote= s.indexOf('"', urlOffset);
450
				int nextWhitespace= s.indexOf(' ', urlOffset);
451
				if (nextDoubleQuote != -1 && nextWhitespace != -1)
452
					endOffset= Math.min(nextDoubleQuote, nextWhitespace);
453
				else if (nextDoubleQuote != -1)
454
					endOffset= nextDoubleQuote;
455
				else if (nextWhitespace != -1)
456
					endOffset= nextWhitespace;
457
				if (endOffset != -1)
458
					urlLength= endOffset - urlOffset;
459
			}
460
			
461
			linkRanges.add(new int[] { urlOffset, urlLength });
462
			links.add(s.substring(urlOffset, urlOffset+urlLength));
463
			
464
			urlSeparatorOffset= s.indexOf("://", urlOffset+urlLength+1); //$NON-NLS-1$
465
		}
466
        return new AboutItem(s, (int[][]) linkRanges.toArray(new int[linkRanges
467
                .size()][2]), (String[]) links
468
                .toArray(new String[links.size()]));
469
    }
470
    
471
    /*
472
     * (non-Javadoc)
473
     * @see org.eclipse.jface.dialogs.Dialog#isResizable()
474
     */
475
    protected boolean isResizable() {
476
    	return true;
477
    }
478
}
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/AboutPluginsDialog.java (-645 / +12 lines)
Lines 12-672 Link Here
12
 *******************************************************************************/
12
 *******************************************************************************/
13
package org.eclipse.ui.internal.dialogs;
13
package org.eclipse.ui.internal.dialogs;
14
14
15
import java.io.IOException;
16
import java.net.URL;
17
import java.util.ArrayList;
18
import java.util.HashMap;
19
import java.util.LinkedList;
20
import java.util.List;
21
import java.util.Map;
22
23
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.IProgressMonitor;
25
import org.eclipse.core.runtime.IStatus;
26
import org.eclipse.core.runtime.Path;
27
import org.eclipse.core.runtime.Platform;
28
import org.eclipse.core.runtime.Status;
29
import org.eclipse.core.runtime.jobs.Job;
30
import org.eclipse.jface.dialogs.DialogTray;
31
import org.eclipse.jface.dialogs.IDialogConstants;
32
import org.eclipse.jface.internal.ConfigureColumnsDialog;
33
import org.eclipse.jface.viewers.ArrayContentProvider;
34
import org.eclipse.jface.viewers.IBaseLabelProvider;
35
import org.eclipse.jface.viewers.ISelectionChangedListener;
36
import org.eclipse.jface.viewers.IStructuredSelection;
37
import org.eclipse.jface.viewers.ITableLabelProvider;
38
import org.eclipse.jface.viewers.LabelProvider;
39
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
40
import org.eclipse.jface.viewers.SelectionChangedEvent;
41
import org.eclipse.jface.viewers.TableViewer;
42
import org.eclipse.jface.viewers.Viewer;
43
import org.eclipse.jface.viewers.ViewerComparator;
44
import org.eclipse.osgi.util.NLS;
15
import org.eclipse.osgi.util.NLS;
45
import org.eclipse.swt.SWT;
46
import org.eclipse.swt.events.SelectionAdapter;
47
import org.eclipse.swt.events.SelectionEvent;
48
import org.eclipse.swt.graphics.Image;
49
import org.eclipse.swt.layout.GridData;
50
import org.eclipse.swt.layout.GridLayout;
51
import org.eclipse.swt.widgets.Button;
52
import org.eclipse.swt.widgets.Composite;
53
import org.eclipse.swt.widgets.Control;
54
import org.eclipse.swt.widgets.Label;
55
import org.eclipse.swt.widgets.Shell;
16
import org.eclipse.swt.widgets.Shell;
56
import org.eclipse.swt.widgets.TableColumn;
57
import org.eclipse.ui.PlatformUI;
58
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
59
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
60
import org.eclipse.ui.internal.WorkbenchImages;
61
import org.eclipse.ui.internal.WorkbenchMessages;
17
import org.eclipse.ui.internal.WorkbenchMessages;
62
import org.eclipse.ui.internal.WorkbenchPlugin;
18
import org.eclipse.ui.internal.about.AboutPluginsPage;
63
import org.eclipse.ui.internal.about.AboutBundleData;
64
import org.eclipse.ui.internal.misc.StatusUtil;
65
import org.eclipse.ui.internal.util.BundleUtility;
66
import org.eclipse.ui.progress.WorkbenchJob;
67
import org.eclipse.ui.statushandlers.StatusManager;
68
import org.osgi.framework.Bundle;
19
import org.osgi.framework.Bundle;
20
import org.eclipse.ui.internal.about.ProductInfoDialog;
69
21
70
/**
22
/**
71
 * Displays information about the product plugins.
23
 * Displays information about the product plugins.
72
 *
24
 * 
73
 * PRIVATE
25
 * PRIVATE this class is internal to the ide
74
 *	this class is internal to the ide
75
 */
26
 */
76
public class AboutPluginsDialog extends ProductInfoDialog {
27
public class AboutPluginsDialog extends ProductInfoDialog {
77
78
	public class BundleTableLabelProvider extends LabelProvider implements ITableLabelProvider  {
79
		
80
		/**
81
		 * Queue containing bundle signing info to be resolved.
82
		 */
83
		private LinkedList resolveQueue = new LinkedList();
84
		
85
		/**
86
         * Queue containing bundle data that's been resolve and needs updating.
87
         */
88
		private List updateQueue = new ArrayList();
89
90
		/*
91
		 * this job will attempt to discover the signing state of a given bundle
92
		 * and then send it along to the update job
93
		 */
94
		private Job resolveJob= new Job(AboutPluginsDialog.class.getName()) {
95
			{
96
				setSystem(true);
97
				setPriority(Job.SHORT);
98
			}
99
			
100
			protected IStatus run(IProgressMonitor monitor) {
101
				while (true) {
102
					Shell dialogShell = getShell();
103
					// the shell has gone down since we were asked to render
104
					if (dialogShell == null || dialogShell.isDisposed())
105
						return Status.OK_STATUS;
106
					AboutBundleData data = null;
107
					synchronized (resolveQueue) {
108
						if (resolveQueue.isEmpty())
109
							return Status.OK_STATUS;
110
						data = (AboutBundleData) resolveQueue.removeFirst();
111
					}
112
					try {
113
						// following is an expensive call
114
						data.isSigned();
115
						
116
						synchronized (updateQueue) {
117
							updateQueue.add(data);
118
						}
119
						// start the update job
120
						updateJob.schedule();
121
					} catch (IllegalStateException e) {
122
						// the bundle we're testing has been unloaded.  Do nothing.
123
					}
124
				}
125
			}
126
		};
127
		
128
		/*
129
		 * this job is responsible for feeding label change events into the
130
		 * viewer as they become available from the resolve job
131
		 */
132
		private Job updateJob= new WorkbenchJob(getShell().getDisplay(), AboutPluginsDialog.class.getName()) {
133
			{
134
				setSystem(true);
135
				setPriority(Job.DECORATE);
136
			}
137
			
138
			/* (non-Javadoc)
139
			 * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
140
			 */
141
			public IStatus runInUIThread(IProgressMonitor monitor) {
142
				while (true) {
143
					Shell dialogShell = getShell();
144
					// the shell has gone down since we were asked to render
145
					if (dialogShell == null || dialogShell.isDisposed())
146
						return Status.OK_STATUS;
147
					AboutBundleData[] data = null;
148
					synchronized (updateQueue) {
149
						if (updateQueue.isEmpty())
150
							return Status.OK_STATUS;
151
152
						data = (AboutBundleData[]) updateQueue
153
								.toArray(new AboutBundleData[updateQueue.size()]);
154
						updateQueue.clear();
155
156
					}
157
					fireLabelProviderChanged(new LabelProviderChangedEvent(
158
							BundleTableLabelProvider.this, data));
159
				}
160
			}
161
		};
162
			
163
		/* (non-Javadoc)
164
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int)
165
		 */
166
		public Image getColumnImage(Object element, int columnIndex) {
167
			if (columnIndex == 0) {
168
				if (element instanceof AboutBundleData) {
169
					final AboutBundleData data = (AboutBundleData) element;
170
					if (data.isSignedDetermined()) {
171
						return WorkbenchImages
172
								.getImage(data.isSigned() ? IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_YES
173
										: IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_NO);
174
					} 
175
					
176
					synchronized (resolveQueue) {
177
						resolveQueue.add(data);
178
					}
179
					resolveJob.schedule();
180
					
181
					return WorkbenchImages
182
							.getImage(IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_UNKNOWN);
183
				}
184
			}
185
			return null;
186
		}
187
188
		/* (non-Javadoc)
189
		 * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int)
190
		 */
191
		public String getColumnText(Object element, int columnIndex) {
192
			if (element instanceof AboutBundleData) {
193
				AboutBundleData data = (AboutBundleData) element;
194
				switch (columnIndex) {
195
				case 1:
196
					return data.getProviderName();
197
				case 2:
198
					return data.getName();
199
				case 3:
200
					return data.getVersion();
201
				case 4:
202
					return data.getId();
203
				}
204
			}
205
			return ""; //$NON-NLS-1$
206
		}		
207
	}
208
	
209
    /**
210
     * Table height in dialog units (value 200).
211
     */
212
    private static final int TABLE_HEIGHT = 200;
213
214
	private static final IPath baseNLPath = new Path("$nl$"); //$NON-NLS-1$
215
216
    private static final String PLUGININFO = "about.html"; //$NON-NLS-1$
217
218
    private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
219
    private final static int SIGNING_ID = MORE_ID + 1;
220
    private final static int COLUMNS_ID = MORE_ID + 2;
221
    
222
    private static final int PLUGIN_NAME_COLUMN_INDEX = 2;
223
224
    private TableViewer vendorInfo;
225
226
    private Button moreInfo, signingInfo;
227
228
    private String title;
229
230
    private String message;
231
    
232
    private String helpContextId;
233
234
    private String columnTitles[] = {
235
    		WorkbenchMessages.AboutPluginsDialog_signed,
236
            WorkbenchMessages.AboutPluginsDialog_provider,
237
            WorkbenchMessages.AboutPluginsDialog_pluginName,
238
            WorkbenchMessages.AboutPluginsDialog_version, 
239
            WorkbenchMessages.AboutPluginsDialog_pluginId,
240
            
241
    };
242
243
    private String productName;
244
245
    private AboutBundleData[] bundleInfos;
246
    
247
    /**
248
     * Constructor for AboutPluginsDialog.
249
     * 
250
     * @param parentShell the parent shell
251
     * @param productName the product name
252
     */
253
    public AboutPluginsDialog(Shell parentShell, String productName) {
254
        this(parentShell, productName, WorkbenchPlugin.getDefault()
255
                .getBundles(), null, null, IWorkbenchHelpContextIds.ABOUT_PLUGINS_DIALOG);
256
        WorkbenchPlugin.class.getSigners();
257
    }
258
259
    /**
260
     * Constructor for AboutPluginsDialog.
261
     * 
262
     * @param parentShell 
263
     * 			  the parent shell
264
     * @param productName
265
     *            must not be null
266
     * @param bundles
267
     *            must not be null
268
     * @param title 
269
     *            the title
270
     * @param message 
271
     * 			  the message
272
     * @param helpContextId 
273
     *            the help context id
274
     */
275
    public AboutPluginsDialog(Shell parentShell, String productName,
28
    public AboutPluginsDialog(Shell parentShell, String productName,
276
            Bundle[] bundles, String title, String message, String helpContextId) {
29
            Bundle[] bundles, String title, String message, String helpContextId) {
277
        super(parentShell);
30
    	super(parentShell);
278
        this.title = title;
31
    	AboutPluginsPage page = new AboutPluginsPage();
279
        this.message = message;
32
    	page.setHelpContextId(helpContextId);
280
        this.helpContextId = helpContextId;
33
    	page.setBundles(bundles);
281
        this.productName = productName;
34
    	page.setMessage(message);
282
        
35
    	if (title == null && page.getProductName() != null)
283
        // create a data object for each bundle, remove duplicates, and include only resolved bundles (bug 65548)
36
            title = NLS.bind(WorkbenchMessages.AboutPluginsDialog_shellTitle, productName);
284
        Map map = new HashMap();
37
    	initializeDialog(page, title, helpContextId);
285
        for (int i = 0; i < bundles.length; ++i) {
286
            AboutBundleData data = new AboutBundleData(bundles[i]);
287
            if (BundleUtility.isReady(data.getState()) && !map.containsKey(data.getVersionedId())) {
288
				map.put(data.getVersionedId(), data);
289
			}
290
        }
291
        bundleInfos = (AboutBundleData[]) map.values().toArray(
292
                new AboutBundleData[0]);
293
    }
294
295
    /*
296
     * (non-Javadoc) Method declared on Dialog.
297
     */
298
    protected void buttonPressed(int buttonId) {
299
        switch (buttonId) {
300
        case MORE_ID:
301
            handleMoreInfoPressed();
302
            break;
303
        case SIGNING_ID:
304
        	handleSigningInfoPressed();
305
        	break;
306
        case COLUMNS_ID:
307
        	handleColumnsPressed();
308
        	break;
309
        default:
310
            super.buttonPressed(buttonId);
311
            break;
312
        }
313
    }
314
315
    /**
316
	 * 
317
	 */
318
	private void handleColumnsPressed() {
319
		ConfigureColumnsDialog d = new ConfigureColumnsDialog(this, vendorInfo.getTable());
320
		d.open();
321
	}
322
323
	/**
324
	 */
325
	private void handleSigningInfoPressed() {
326
		DialogTray existingTray = getTray();
327
		if (existingTray instanceof BundleSigningTray) {
328
			// hide
329
			getButton(SIGNING_ID).setText(WorkbenchMessages.AboutPluginsDialog_signingInfo_show); 
330
			closeTray();
331
		}
332
		else {
333
			//show
334
			getButton(SIGNING_ID).setText(WorkbenchMessages.AboutPluginsDialog_signingInfo_hide);
335
			if (existingTray != null)
336
				closeTray();
337
			AboutBundleData bundleInfo = (AboutBundleData) ((IStructuredSelection) vendorInfo
338
					.getSelection()).getFirstElement();
339
			BundleSigningTray tray = new BundleSigningTray(this);
340
			tray.setData(bundleInfo);
341
			openTray(tray);
342
		}
343
		
344
	}
345
346
	/*
347
     * (non-Javadoc) Method declared on Window.
348
     */
349
    protected void configureShell(Shell newShell) {
350
        super.configureShell(newShell);
351
        
352
        //signImage = new Image( this.getParentShell().getDisplay(), AboutPluginsDialog.class.getResourceAsStream("Signed.gif")); //$NON-NLS-1$
353
        
354
        if (title == null && productName != null) {
355
			title = NLS.bind(WorkbenchMessages.AboutPluginsDialog_shellTitle, productName);
356
		}
357
358
        if (title != null) {
359
			newShell.setText(title);
360
		}
361
362
        PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
363
				helpContextId);
364
    }
365
    
366
    /**
367
     * Add buttons to the dialog's button bar.
368
     * 
369
     * Subclasses should override.
370
     * 
371
     * @param parent
372
     *            the button bar composite
373
     */
374
    protected void createButtonsForButtonBar(Composite parent) {
375
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
376
377
        moreInfo = createButton(parent, MORE_ID, WorkbenchMessages.AboutPluginsDialog_moreInfo, false); 
378
        moreInfo.setEnabled(false);
379
        
380
        signingInfo = createButton(parent, SIGNING_ID, WorkbenchMessages.AboutPluginsDialog_signingInfo_show, false);
381
        signingInfo.setEnabled(false);
382
383
        createButton(parent, COLUMNS_ID, WorkbenchMessages.AboutPluginsDialog_columns, false);
384
385
        Label l = new Label(parent, SWT.NONE);
386
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
387
        GridLayout layout = (GridLayout) parent.getLayout();
388
        layout.numColumns++;
389
        layout.makeColumnsEqualWidth = false;
390
391
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
392
                true);
393
    }
394
395
    /**
396
     * Create the contents of the dialog (above the button bar).
397
     * 
398
     * Subclasses should overide.
399
     * 
400
     * @param parent
401
     *            the parent composite to contain the dialog area
402
     * @return the dialog area control
403
     */
404
    protected Control createDialogArea(Composite parent) {
405
        Composite outer = (Composite) super.createDialogArea(parent);
406
407
        if (message != null) {
408
            Label label = new Label(outer, SWT.NONE);
409
            label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
410
            label.setFont(parent.getFont());
411
            label.setText(message);
412
        }
413
414
        createTable(outer);
415
416
        return outer;
417
    }
418
419
    /**
420
     * Create the table part of the dialog.
421
     * 
422
     * @param parent
423
     *            the parent composite to contain the dialog area
424
     */
425
    protected void createTable(Composite parent) {
426
        vendorInfo = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
427
                | SWT.FULL_SELECTION | SWT.BORDER);
428
        vendorInfo.setUseHashlookup(true);
429
        vendorInfo.getTable().setHeaderVisible(true);
430
        vendorInfo.getTable().setLinesVisible(true);
431
        vendorInfo.getTable().setFont(parent.getFont());
432
        vendorInfo.addSelectionChangedListener(new ISelectionChangedListener() {
433
434
			public void selectionChanged(SelectionChangedEvent event) {
435
				// enable if there is an item selected and that
436
                // item has additional info
437
				IStructuredSelection selection = (IStructuredSelection) event.getSelection();
438
				if (selection.getFirstElement() instanceof AboutBundleData) {
439
					AboutBundleData selected = (AboutBundleData) selection.getFirstElement(); 
440
					moreInfo.setEnabled(selectionHasInfo(selected));
441
					signingInfo.setEnabled(true);
442
					if (getTray() instanceof BundleSigningTray) {
443
						((BundleSigningTray)getTray()).setData(selected);
444
					}
445
				}
446
				else {
447
					moreInfo.setEnabled(false);
448
					signingInfo.setEnabled(false);
449
				}
450
			}});
451
        
452
        final TableComparator comparator = new TableComparator();
453
        vendorInfo.setComparator(comparator);
454
        int[] columnWidths = {
455
        		convertHorizontalDLUsToPixels(30), //signature
456
        		convertHorizontalDLUsToPixels(120),
457
                convertHorizontalDLUsToPixels(120),
458
                convertHorizontalDLUsToPixels(70),
459
                convertHorizontalDLUsToPixels(130),
460
                };
461
462
        
463
        // create table headers
464
        for (int i = 0; i < columnTitles.length; i++) {
465
            TableColumn column = new TableColumn(vendorInfo.getTable(), SWT.NULL);
466
            if (i == PLUGIN_NAME_COLUMN_INDEX) { // prime initial sorting
467
            	updateTableSorting(i);
468
            }	
469
            column.setWidth(columnWidths[i]);
470
            column.setText(columnTitles[i]);
471
            final int columnIndex = i;
472
            column.addSelectionListener(new SelectionAdapter() {
473
                public void widgetSelected(SelectionEvent e) {
474
                    updateTableSorting(columnIndex);
475
                }
476
            });
477
        }
478
                
479
        vendorInfo.setContentProvider(new ArrayContentProvider());        
480
        vendorInfo.setLabelProvider(new BundleTableLabelProvider());
481
       
482
        GridData gridData = new GridData(GridData.FILL, GridData.FILL, true,
483
                true);
484
        gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
485
        vendorInfo.getTable().setLayoutData(gridData);
486
        
487
        vendorInfo.setInput(bundleInfos);
488
    }
489
490
	/**
491
	 * Update the sort information on both the comparator and the table.
492
	 * 
493
	 * @param columnIndex
494
	 *            the index to sort by
495
	 * @since 3.4
496
	 */
497
	private void updateTableSorting(final int columnIndex) {
498
		TableComparator comparator = (TableComparator) vendorInfo
499
				.getComparator();
500
		// toggle direction if it's the same column
501
		if (columnIndex == comparator.getSortColumn()) {
502
			comparator.setAscending(!comparator.isAscending());
503
		}
504
		comparator.setSortColumn(columnIndex);
505
		vendorInfo.getTable().setSortColumn(
506
				vendorInfo.getTable().getColumn(columnIndex));
507
		vendorInfo.getTable().setSortDirection(
508
				comparator.isAscending() ? SWT.UP : SWT.DOWN);
509
		vendorInfo.refresh(false);
510
	}
511
	
512
	/**
513
     * Check if the currently selected plugin has additional information to
514
     * show.
515
     * @param bundleInfo 
516
     * 
517
     * @return true if the selected plugin has additional info available to
518
     *         display
519
     */
520
    private boolean selectionHasInfo(AboutBundleData bundleInfo) {
521
        
522
        URL infoURL = getMoreInfoURL(bundleInfo, false);
523
524
        // only report ini problems if the -debug command line argument is used
525
        if (infoURL == null && WorkbenchPlugin.DEBUG) {
526
        	WorkbenchPlugin.log("Problem reading plugin info for: " //$NON-NLS-1$
527
					+ bundleInfo.getName());
528
		}
529
530
        return infoURL != null;
531
    }
532
533
    /** 
534
     * The More Info button was pressed.  Open a browser showing the license information
535
     * for the selected bundle or an error dialog if the browser cannot be opened.
536
     */
537
    protected void handleMoreInfoPressed() {
538
        if (vendorInfo == null) {
539
			return;
540
		}
541
        
542
        if (vendorInfo.getSelection().isEmpty())
543
        	return;
544
        
545
        AboutBundleData bundleInfo = (AboutBundleData) ((IStructuredSelection) vendorInfo
546
				.getSelection()).getFirstElement();
547
        
548
        if (!openBrowser(getMoreInfoURL(bundleInfo, true))) {
549
			String message = NLS.bind(
550
					WorkbenchMessages.AboutPluginsDialog_unableToOpenFile,
551
					PLUGININFO, bundleInfo.getId());
552
			StatusUtil.handleStatus(
553
					WorkbenchMessages.AboutPluginsDialog_errorTitle
554
							+ ": " + message, StatusManager.SHOW, getShell()); //$NON-NLS-1$
555
		}
556
    }
557
558
    /**
559
     * Return an url to the plugin's about.html file (what is shown when "More info" is
560
     * pressed) or null if no such file exists.  The method does nl lookup to allow for
561
     * i18n.
562
     * 
563
     * @param bundleInfo the bundle info
564
     * @param makeLocal whether to make the about content local
565
     * @return the url or <code>null</code>
566
     */
567
    private URL getMoreInfoURL(AboutBundleData bundleInfo, boolean makeLocal) {
568
        Bundle bundle = Platform.getBundle(bundleInfo.getId());
569
        if (bundle == null) {
570
			return null;
571
		}
572
573
        URL aboutUrl = Platform.find(bundle, baseNLPath.append(PLUGININFO), null);
574
        if (!makeLocal) {
575
            return aboutUrl;
576
        }
577
		if (aboutUrl != null) {
578
		    try {
579
				URL result = Platform.asLocalURL(aboutUrl);
580
				try {
581
				    // Make local all content in the "about" directory.
582
				    // This is needed to handle jar'ed plug-ins.
583
				    // See Bug 88240 [About] About dialog needs to extract subdirs.
584
					URL about = new URL(aboutUrl, "about_files"); //$NON-NLS-1$
585
					if (about != null) {
586
						Platform.asLocalURL(about);
587
					}
588
				} catch (IOException e) {
589
					// skip the about dir if its not found or there are other problems.
590
				}
591
				return result;
592
		    } catch(IOException e) {
593
		        // do nothing
594
		    }
595
        }
596
		return null;
597
    }
598
}
599
600
601
class TableComparator extends ViewerComparator {
602
603
	private int sortColumn = 0;
604
	private boolean ascending = true;
605
	
606
	/* (non-Javadoc)
607
	 * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
608
	 */
609
	public int compare(Viewer viewer, Object e1, Object e2) {
610
		if (sortColumn == 0 && e1 instanceof AboutBundleData && e2 instanceof AboutBundleData) {
611
			AboutBundleData d1= (AboutBundleData) e1;
612
			AboutBundleData d2= (AboutBundleData) e2;
613
			int diff= getSignedSortValue(d1) - getSignedSortValue(d2);
614
			return ascending ? diff : -diff;
615
		}
616
		if (viewer instanceof TableViewer) {
617
			TableViewer tableViewer = (TableViewer) viewer;
618
			IBaseLabelProvider baseLabel = tableViewer.getLabelProvider();
619
			if (baseLabel instanceof ITableLabelProvider) {
620
				ITableLabelProvider tableProvider = (ITableLabelProvider) baseLabel;
621
				String e1p = tableProvider.getColumnText(e1, sortColumn);
622
				String e2p = tableProvider.getColumnText(e2, sortColumn);
623
				int result = getComparator().compare(e1p, e2p);
624
				return ascending ?  result : (-1) * result;
625
			}
626
		}
627
		
628
		return super.compare(viewer, e1, e2);
629
	}
630
631
	/**
632
	 * @param data
633
	 * @return a sort value depending on the signed state
634
	 */
635
	private int getSignedSortValue(AboutBundleData data) {
636
		if (! data.isSignedDetermined()) {
637
			return 0;
638
		} else if (data.isSigned()) {
639
			return 1;
640
		} else {
641
			return -1;
642
		}
643
	}
644
	
645
	/**
646
	 * @return Returns the sortColumn.
647
	 */
648
	public int getSortColumn() {
649
		return sortColumn;
650
	}
651
652
	/**
653
	 * @param sortColumn The sortColumn to set.
654
	 */
655
	public void setSortColumn(int sortColumn) {
656
		this.sortColumn = sortColumn;
657
	}
658
659
	/**
660
	 * @return Returns the ascending.
661
	 */
662
	public boolean isAscending() {
663
		return ascending;
664
	}
665
666
	/**
667
	 * @param ascending The ascending to set.
668
	 */
669
	public void setAscending(boolean ascending) {
670
		this.ascending = ascending;
671
	}
38
	}
672
}
39
}
(-)Eclipse UI/org/eclipse/ui/internal/dialogs/AboutSystemDialog.java (-229 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2008 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.dialogs;
12
13
import java.io.File;
14
import java.io.FileNotFoundException;
15
import java.io.FileReader;
16
import java.io.FileWriter;
17
import java.io.IOException;
18
19
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.jface.dialogs.IDialogConstants;
22
import org.eclipse.jface.dialogs.MessageDialog;
23
import org.eclipse.jface.resource.JFaceResources;
24
import org.eclipse.osgi.util.NLS;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.dnd.Clipboard;
27
import org.eclipse.swt.dnd.TextTransfer;
28
import org.eclipse.swt.dnd.Transfer;
29
import org.eclipse.swt.layout.GridData;
30
import org.eclipse.swt.layout.GridLayout;
31
import org.eclipse.swt.widgets.Button;
32
import org.eclipse.swt.widgets.Composite;
33
import org.eclipse.swt.widgets.Control;
34
import org.eclipse.swt.widgets.Label;
35
import org.eclipse.swt.widgets.Shell;
36
import org.eclipse.swt.widgets.Text;
37
import org.eclipse.ui.PlatformUI;
38
import org.eclipse.ui.internal.ConfigurationInfo;
39
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
40
import org.eclipse.ui.internal.WorkbenchMessages;
41
import org.eclipse.ui.internal.WorkbenchPlugin;
42
43
44
/**
45
 * Displays system information about the eclipse application.  The content of
46
 * what is displayed is selectable through the
47
 * <code>org.eclipse.ui.systemSummaryExtensions</code> extension point.
48
 */
49
public final class AboutSystemDialog extends ProductInfoDialog {
50
51
    private Text text;
52
    
53
    private final static int BROWSE_ERROR_LOG_BUTTON = IDialogConstants.CLIENT_ID;
54
55
    private final static int COPY_TO_CLIPBOARD_BUTTON = IDialogConstants.CLIENT_ID + 1;
56
    
57
    private final static String ERROR_LOG_COPY_FILENAME = "log"; //$NON-NLS-1$
58
59
    /**
60
     * Create an instance of this dialog.
61
     * 
62
     * @param parentShell the parent shell
63
     */
64
    public AboutSystemDialog(Shell parentShell) {
65
        super(parentShell);
66
    }
67
68
    /* (non-Javadoc)
69
     * Method declared on Window.
70
     */
71
    protected void configureShell(Shell newShell) {
72
        super.configureShell(newShell);
73
        newShell.setText(WorkbenchMessages.SystemSummary_title);
74
        PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
75
				IWorkbenchHelpContextIds.SYSTEM_SUMMARY_DIALOG);
76
    }
77
78
    /* (non-Javadoc)
79
     * Method declared on Dialog.
80
     */
81
    protected void createButtonsForButtonBar(Composite parent) {
82
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
83
84
        Button button = createButton(parent, BROWSE_ERROR_LOG_BUTTON, WorkbenchMessages.AboutSystemDialog_browseErrorLogName, false);
85
        String filename = Platform.getLogFileLocation().toOSString();
86
        button.setEnabled(new File(filename).exists());
87
88
        createButton(parent, COPY_TO_CLIPBOARD_BUTTON, WorkbenchMessages.AboutSystemDialog_copyToClipboardName, false);
89
90
        new Label(parent, SWT.NONE).setLayoutData(new GridData(
91
                GridData.FILL_HORIZONTAL));
92
        GridLayout layout = (GridLayout) parent.getLayout();
93
        layout.numColumns++;
94
        layout.makeColumnsEqualWidth = false;
95
96
        createButton(parent, IDialogConstants.CLOSE_ID,
97
                IDialogConstants.CLOSE_LABEL, true);
98
    }
99
100
    /* (non-Javadoc)
101
     * Method declared on Dialog.
102
     */
103
    protected Control createDialogArea(Composite parent) {
104
        Composite outer = (Composite) super.createDialogArea(parent);
105
106
        text = new Text(outer, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY
107
                | SWT.V_SCROLL | SWT.NO_FOCUS | SWT.H_SCROLL);
108
        text.setBackground(parent.getDisplay().getSystemColor(
109
                SWT.COLOR_LIST_BACKGROUND));
110
        GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
111
                | GridData.VERTICAL_ALIGN_FILL);
112
        gridData.grabExcessVerticalSpace = true;
113
        gridData.grabExcessHorizontalSpace = true;
114
        gridData.heightHint = convertVerticalDLUsToPixels(300);
115
        gridData.widthHint = convertHorizontalDLUsToPixels(400);
116
        text.setLayoutData(gridData);
117
        text.setText(ConfigurationInfo.getSystemSummary());
118
        text.setFont(JFaceResources.getTextFont());
119
        return outer;
120
    }
121
122
    /* (non-Javadoc)
123
     * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
124
     */
125
    protected void buttonPressed(int buttonId) {
126
        switch (buttonId) {
127
        case IDialogConstants.CLOSE_ID:
128
            close();
129
            break;
130
        case BROWSE_ERROR_LOG_BUTTON:
131
            openErrorLogBrowser();
132
            break;
133
        case COPY_TO_CLIPBOARD_BUTTON:
134
            runCopyToClipboard();
135
            break;
136
        }
137
        super.buttonPressed(buttonId);
138
    }
139
140
    private void openErrorLogBrowser() {
141
        String filename = Platform.getLogFileLocation().toOSString();
142
143
        File log = new File(filename);
144
        if (log.exists()) {
145
        	// Make a copy of the file with a temporary name.
146
        	// Working around an issue with windows file associations/browser malfunction
147
        	// whereby the browser doesn't open on ".log" and we aren't returned an error.
148
        	// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97783
149
        	File logCopy = makeDisplayCopy(log);
150
        	if (logCopy != null) {
151
        		openLink("file:///" + logCopy.getAbsolutePath()); //$NON-NLS-1$
152
        		return;
153
        	}
154
        	// Couldn't make copy, try to open the original log.
155
        	// We try the original in this case rather than putting up an error,
156
        	// because the copy could fail due to an I/O or out of space problem.
157
        	// In that case we may still be able to show the original log,
158
        	// depending on the platform.  The risk is that users with configurations
159
        	// that have bug #97783 will still get nothing (vs. an error) but we'd rather
160
        	// try again than put up an error dialog on platforms where the ability to
161
        	// view the original log works just fine.
162
        	openLink("file:///" + filename); //$NON-NLS-1$
163
        	return;
164
        }
165
        MessageDialog.openInformation(getShell(), WorkbenchMessages.AboutSystemDialog_noLogTitle, 
166
                NLS.bind(WorkbenchMessages.AboutSystemDialog_noLogMessage,  filename ));
167
    }
168
    
169
    /**
170
     * Returns a copy of the given file to be used for display in
171
     * a browser.
172
     * 
173
     * @return the file, or <code>null</code>
174
     */
175
    private File makeDisplayCopy(File file) {
176
        IPath path = WorkbenchPlugin.getDefault().getDataLocation();
177
        if(path == null) {
178
			return null;
179
		}
180
        path = path.append(ERROR_LOG_COPY_FILENAME);
181
        File copy = path.toFile();
182
        FileReader in = null;
183
        FileWriter out = null;
184
        try {
185
			in = new FileReader(file);
186
			// don't append data, overwrite what was there
187
			out = new FileWriter(copy);
188
			char buffer[] = new char[4096];
189
		    int count;
190
		    while ((count = in.read(buffer, 0, buffer.length)) > 0) {
191
		        out.write(buffer, 0, count);
192
		    }
193
		} catch (FileNotFoundException e) {
194
			return null;
195
		} catch (IOException e) {
196
			return null;
197
		} finally {
198
			try {
199
				if (in != null) {
200
					in.close();
201
				}
202
				if (out != null) {
203
					out.close();
204
				}
205
			} catch (IOException e) {
206
				return null;
207
			}
208
		}
209
		return copy;
210
211
    }
212
213
    private void runCopyToClipboard() {
214
        if (text == null) {
215
			return;
216
		}
217
218
        Clipboard clipboard = null;
219
        try {
220
            clipboard = new Clipboard(getShell().getDisplay());
221
            clipboard.setContents(new Object[] { text.getText() },
222
                    new Transfer[] { TextTransfer.getInstance() });
223
        } finally {
224
            if (clipboard != null) {
225
				clipboard.dispose();
226
			}
227
        }
228
    }
229
}
(-)Eclipse UI/org/eclipse/ui/internal/about/InstallationDialog.java (-207 / +231 lines)
Lines 11-35 Link Here
11
11
12
package org.eclipse.ui.internal.about;
12
package org.eclipse.ui.internal.about;
13
13
14
import org.eclipse.core.expressions.Expression;
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.IConfigurationElement;
16
import org.eclipse.core.runtime.IConfigurationElement;
16
import org.eclipse.core.runtime.IExtensionPoint;
17
import org.eclipse.core.runtime.IExtensionPoint;
18
import org.eclipse.core.runtime.IProduct;
17
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.core.runtime.Platform;
18
import org.eclipse.jface.action.ContributionManager;
20
import org.eclipse.jface.action.ContributionManager;
19
import org.eclipse.jface.action.IContributionItem;
21
import org.eclipse.jface.action.IContributionItem;
20
import org.eclipse.jface.action.ToolBarManager;
21
import org.eclipse.jface.dialogs.Dialog;
22
import org.eclipse.jface.dialogs.Dialog;
22
import org.eclipse.jface.dialogs.IDialogConstants;
23
import org.eclipse.jface.dialogs.IDialogConstants;
23
import org.eclipse.jface.resource.ColorRegistry;
24
import org.eclipse.jface.dialogs.IDialogSettings;
24
import org.eclipse.jface.resource.JFaceResources;
25
import org.eclipse.osgi.util.NLS;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.custom.CTabFolder;
27
import org.eclipse.swt.custom.CTabItem;
28
import org.eclipse.swt.events.DisposeEvent;
27
import org.eclipse.swt.events.DisposeEvent;
29
import org.eclipse.swt.events.DisposeListener;
28
import org.eclipse.swt.events.DisposeListener;
30
import org.eclipse.swt.events.SelectionAdapter;
29
import org.eclipse.swt.events.SelectionAdapter;
31
import org.eclipse.swt.events.SelectionEvent;
30
import org.eclipse.swt.events.SelectionEvent;
32
import org.eclipse.swt.graphics.Color;
33
import org.eclipse.swt.graphics.FontMetrics;
31
import org.eclipse.swt.graphics.FontMetrics;
34
import org.eclipse.swt.graphics.GC;
32
import org.eclipse.swt.graphics.GC;
35
import org.eclipse.swt.graphics.Point;
33
import org.eclipse.swt.graphics.Point;
Lines 39-77 Link Here
39
import org.eclipse.swt.widgets.Control;
37
import org.eclipse.swt.widgets.Control;
40
import org.eclipse.swt.widgets.Label;
38
import org.eclipse.swt.widgets.Label;
41
import org.eclipse.swt.widgets.Shell;
39
import org.eclipse.swt.widgets.Shell;
42
import org.eclipse.swt.widgets.ToolBar;
40
import org.eclipse.swt.widgets.TabFolder;
43
import org.eclipse.ui.IWorkbenchPreferenceConstants;
41
import org.eclipse.swt.widgets.TabItem;
44
import org.eclipse.ui.PlatformUI;
42
import org.eclipse.ui.about.ActiveInstallationPageExpression;
45
import org.eclipse.ui.about.IInstallationPageContainer;
43
import org.eclipse.ui.about.IInstallationPageContainer;
46
import org.eclipse.ui.about.InstallationPage;
44
import org.eclipse.ui.about.InstallationPage;
47
import org.eclipse.ui.internal.IWorkbenchThemeConstants;
45
import org.eclipse.ui.internal.ConfigurationInfo;
48
import org.eclipse.ui.internal.menus.InternalMenuService;
46
import org.eclipse.ui.internal.WorkbenchMessages;
49
import org.eclipse.ui.internal.menus.SlaveMenuService;
47
import org.eclipse.ui.internal.WorkbenchPlugin;
50
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
48
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
49
import org.eclipse.ui.internal.services.IServiceLocatorCreator;
51
import org.eclipse.ui.menus.IMenuService;
50
import org.eclipse.ui.menus.IMenuService;
51
import org.eclipse.ui.services.AbstractServiceFactory;
52
import org.eclipse.ui.services.IDisposable;
52
import org.eclipse.ui.services.IServiceLocator;
53
import org.eclipse.ui.services.IServiceLocator;
54
import org.eclipse.ui.services.ISourceProviderService;
53
55
54
/**
56
/**
55
 * @since 3.5
57
 * @since 3.5
56
 * 
58
 * 
57
 */
59
 */
58
public class InstallationDialog extends Dialog {
60
public class InstallationDialog extends Dialog implements
59
	private static final String ID = "ID"; //$NON-NLS-1$
61
		IInstallationPageContainer {
62
	class ButtonManager extends ContributionManager {
60
63
61
	private CTabFolder folder;
64
		private Composite composite;
65
66
		public ButtonManager(Composite composite) {
67
			this.composite = composite;
68
		}
69
70
		public Composite getParent() {
71
			return composite;
72
		}
73
74
		/*
75
		 * (non-Javadoc)
76
		 * 
77
		 * @see org.eclipse.jface.action.IContributionManager#update(boolean)
78
		 */
79
		public void update(boolean force) {
80
			if (composite == null || composite.isDisposed())
81
				return;
82
			GC metricsGC = new GC(composite);
83
			FontMetrics metrics = metricsGC.getFontMetrics();
84
			metricsGC.dispose();
85
			IContributionItem[] items = getItems();
86
			Control[] children = composite.getChildren();
87
88
			int visibleChildren = 0;
89
			for (int i = 0; i < children.length; i++) {
90
				Control control = children[i];
91
				control.dispose();
92
			}
93
94
			for (int i = 0; i < items.length; i++) {
95
				IContributionItem item = items[i];
96
				if (item.isVisible()) {
97
					item.fill(composite);
98
					children = composite.getChildren();
99
					Control itemControl = children[children.length - 1];
100
					setButtonLayoutData(metrics, itemControl);
101
					visibleChildren++;
102
				}
103
			}
104
			GridLayout compositeLayout = (GridLayout) composite.getLayout();
105
			compositeLayout.numColumns = visibleChildren;
106
			composite.layout(true);
107
		}
108
109
		protected void setButtonLayoutData(FontMetrics metrics, Control button) {
110
			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
111
			int widthHint = Dialog.convertHorizontalDLUsToPixels(metrics,
112
					IDialogConstants.BUTTON_WIDTH);
113
			Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
114
			data.widthHint = Math.max(widthHint, minSize.x);
115
			button.setLayoutData(data);
116
		}
117
118
	}
119
120
	protected static final String ID = "ID"; //$NON-NLS-1$
121
	private static final String DIALOG_SETTINGS_SECTION = "InstallationDialogSettings"; //$NON-NLS-1$
122
	private static final String URI = "toolbar:org.eclipse.ui.installationDialog.buttonbar"; //$NON-NLS-1$
123
	private TabFolder folder;
62
	private IServiceLocator serviceLocator;
124
	private IServiceLocator serviceLocator;
63
	private ToolBarManager toolbarManager;
64
	private ButtonManager buttonManager;
125
	private ButtonManager buttonManager;
65
	private IMenuService menuService = null;
126
	private InstallationDialogSourceProvider sourceProvider = null;
66
127
67
	/**
128
	/**
68
	 * @param parentShell
129
	 * @param parentShell
130
	 * @param locator
69
	 */
131
	 */
70
	protected InstallationDialog(Shell parentShell, IServiceLocator locator) {
132
	public InstallationDialog(Shell parentShell, IServiceLocator locator) {
71
		super(parentShell);
133
		super(parentShell);
72
		this.serviceLocator = locator;
134
		IServiceLocatorCreator slc = (IServiceLocatorCreator) locator
73
		menuService = new SlaveMenuService((InternalMenuService) serviceLocator
135
				.getService(IServiceLocatorCreator.class);
74
				.getService(IMenuService.class), serviceLocator, null);
136
		createDialogServiceLocator(slc, locator);
137
		ISourceProviderService sps = (ISourceProviderService) serviceLocator
138
				.getService(ISourceProviderService.class);
139
		sourceProvider = (InstallationDialogSourceProvider) sps
140
				.getSourceProvider(InstallationDialogSourceProvider.ACTIVE_PRODUCT_DIALOG_PAGE);
75
141
76
	}
142
	}
77
143
Lines 84-101 Link Here
84
	 */
150
	 */
85
	protected void configureShell(Shell newShell) {
151
	protected void configureShell(Shell newShell) {
86
		super.configureShell(newShell);
152
		super.configureShell(newShell);
87
		// TODO
153
		String productName = ""; //$NON-NLS-1$
88
		// This should use the title of the about dialog, this
154
		IProduct product = Platform.getProduct();
89
		// is a temporary hack so that p2 can launch the dialog
155
		if (product != null && product.getName() != null)
90
		// with a proper title until this is actually hooked into
156
			productName = product.getName();
91
		// the about dialog.
157
		newShell.setText(NLS.bind(
92
		newShell.setText("Installation Information"); //$NON-NLS-1$
158
				WorkbenchMessages.InstallationDialog_ShellTitle, productName));
93
		newShell.setSize(600, 768);
94
95
	}
159
	}
96
	
160
97
	/*
161
	/*
98
	 * (non-Javadoc)
162
	 * (non-Javadoc)
163
	 * 
99
	 * @see org.eclipse.jface.dialogs.Dialog#isResizable()
164
	 * @see org.eclipse.jface.dialogs.Dialog#isResizable()
100
	 */
165
	 */
101
	protected boolean isResizable() {
166
	protected boolean isResizable() {
Lines 112-214 Link Here
112
	protected Control createDialogArea(Composite parent) {
177
	protected Control createDialogArea(Composite parent) {
113
		Composite composite = (Composite) super.createDialogArea(parent);
178
		Composite composite = (Composite) super.createDialogArea(parent);
114
179
115
		createToolbar(composite);
180
		folder = new TabFolder(composite, SWT.NONE);
116
117
		folder = new CTabFolder(composite, SWT.MULTI | SWT.BORDER);
118
		configureFolder();
181
		configureFolder();
182
		createFolderItems(folder);
183
119
		GridData folderData = new GridData(SWT.FILL, SWT.FILL, true, true);
184
		GridData folderData = new GridData(SWT.FILL, SWT.FILL, true, true);
120
		folderData.widthHint = SWT.DEFAULT;
185
		folderData.widthHint = SWT.DEFAULT;
121
		folderData.heightHint = SWT.DEFAULT;
186
		folderData.heightHint = SWT.DEFAULT;
122
		folder.setLayoutData(folderData);
187
		folder.setLayoutData(folderData);
188
		folder.addSelectionListener(createFolderSelectionListener());
189
		folder.addDisposeListener(new DisposeListener() {
190
			public void widgetDisposed(DisposeEvent e) {
191
				releaseContributions();
192
				resetVariables(sourceProvider);
193
			}
194
		});
195
		return composite;
196
	}
123
197
124
		IConfigurationElement[] elements = loadElements();
198
	protected void createFolderItems(TabFolder folder) {
199
		IConfigurationElement[] elements = ConfigurationInfo
200
				.getSortedExtensions(loadElements());
125
		for (int i = 0; i < elements.length; i++) {
201
		for (int i = 0; i < elements.length; i++) {
126
			IConfigurationElement element = elements[i];
202
			IConfigurationElement element = elements[i];
127
			CTabItem item = new CTabItem(folder, SWT.NONE);
203
			TabItem item = new TabItem(folder, SWT.NONE);
128
			item.setText(element
204
			item.setText(element
129
					.getAttribute(IWorkbenchRegistryConstants.ATT_NAME));
205
					.getAttribute(IWorkbenchRegistryConstants.ATT_NAME));
130
			item.setData(element);
206
			item.setData(element);
131
			Composite control = new Composite(folder, SWT.BORDER);
207
			Composite control = new Composite(folder, SWT.BORDER);
132
			control.setLayout(new GridLayout());
208
			control.setLayout(new GridLayout());
133
			item.setControl(control);
209
			item.setControl(control);
134
135
		}
210
		}
136
		folder.addSelectionListener(createFolderSelectionListener());
211
	}
137
		return composite;
212
213
	protected Control createContents(Composite parent) {
214
		Control control = super.createContents(parent);
215
		if (folder.getItemCount() > 0)
216
			tabSelected(folder.getItem(0));
217
		return control;
138
	}
218
	}
139
219
140
	private SelectionAdapter createFolderSelectionListener() {
220
	private SelectionAdapter createFolderSelectionListener() {
141
		return new SelectionAdapter() {
221
		return new SelectionAdapter() {
142
222
143
			public void widgetSelected(SelectionEvent e) {
223
			public void widgetSelected(SelectionEvent e) {
144
				final CTabItem item = (CTabItem) e.item;
224
				tabSelected((TabItem) e.item);
145
				String id = null;
146
				if (item.getData() instanceof IConfigurationElement) {
147
					final IConfigurationElement element = (IConfigurationElement) item
148
							.getData();
149
150
					id = element
151
							.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
152
					item.setData(ID, id);
153
154
					Composite pageComposite = (Composite) item.getControl();
155
					try {
156
						final InstallationPage page = (InstallationPage) element
157
								.createExecutableExtension(IWorkbenchRegistryConstants.ATT_CLASS);
158
						page.createControl(pageComposite);
159
						page.init(createDialogServiceLocator(item));
160
						item.setData(page);
161
						item.addDisposeListener(new DisposeListener() {
162
163
							public void widgetDisposed(DisposeEvent e) {
164
								page.dispose();
165
							}
166
						});
167
						pageComposite.layout(true, true);
168
169
					} catch (CoreException e1) {
170
						Label label = new Label(pageComposite, SWT.NONE);
171
						label.setText(e1.getMessage());
172
						item.setData(null);
173
					}
174
175
					
176
				} else {
177
					id = (String) item.getData(ID);
178
				}
179
				
180
				menuService.releaseContributions(toolbarManager);
181
				menuService.populateContributionManager(toolbarManager,
182
						InstallationDialog.this.getToolbarURI(id));
183
				toolbarManager.update(true);
184
185
				menuService.releaseContributions(buttonManager);
186
				menuService.populateContributionManager(buttonManager,
187
						InstallationDialog.this.getButtonBarURI(id));
188
				buttonManager.update(true);
189
				createButton(buttonManager.getParent(), IDialogConstants.OK_ID,
190
						IDialogConstants.OK_LABEL, true);
191
				// Layout the button manager again now that the OK button is there.
192
				// Must do this before we layout the button bar or else the button
193
				// manager will not know about the OK button
194
				buttonManager.getParent().layout();
195
				// Now we layout the button bar itself so it will accommodate the
196
				// button manager's buttons
197
				getButtonBar().getParent().layout();
198
			}
225
			}
199
		};
226
		};
200
	}
227
	}
201
228
202
	private void createToolbar(Composite composite) {
229
	/*
203
		toolbarManager = new ToolBarManager(SWT.NONE);
230
	 * Must be called after contributions and button manager are created.
204
		toolbarManager.createControl(composite);
231
	 */
205
		ToolBar toolbar = toolbarManager.getControl();
232
	private void tabSelected(TabItem item) {
206
		{
233
		String id = null;
207
			GridData toolbarData = new GridData(SWT.FILL, SWT.FILL, true, false);
234
		if (item.getData() instanceof IConfigurationElement) {
208
			toolbarData.widthHint = SWT.DEFAULT;
235
			final IConfigurationElement element = (IConfigurationElement) item
209
			toolbarData.heightHint = SWT.DEFAULT;
236
					.getData();
210
			toolbar.setLayoutData(toolbarData);
237
238
			id = element.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
239
			item.setData(ID, id);
240
241
			Composite pageComposite = (Composite) item.getControl();
242
			try {
243
				final InstallationPage page = (InstallationPage) element
244
						.createExecutableExtension(IWorkbenchRegistryConstants.ATT_CLASS);
245
				page.createControl(pageComposite);
246
				page.init(serviceLocator);
247
				item.setData(page);
248
				item.addDisposeListener(new DisposeListener() {
249
250
					public void widgetDisposed(DisposeEvent e) {
251
						page.dispose();
252
					}
253
				});
254
				pageComposite.layout(true, true);
255
256
			} catch (CoreException e1) {
257
				Label label = new Label(pageComposite, SWT.NONE);
258
				label.setText(e1.getMessage());
259
				item.setData(null);
260
			}
261
262
		} else {
263
			id = (String) item.getData(ID);
211
		}
264
		}
265
		updateContributions(id, (InstallationPage) item.getData());
266
		createButton(buttonManager.getParent(), IDialogConstants.OK_ID,
267
				IDialogConstants.OK_LABEL, true);
268
		// Layout the button manager again now that the OK button is there.
269
		// Must do this before we layout the button bar or else the button
270
		// manager will not know about the OK button
271
		buttonManager.getParent().layout();
272
		// Now we layout the button bar itself so it will accommodate the
273
		// button manager's buttons
274
		getButtonBar().getParent().layout();
275
	}
276
277
	protected void updateContributions(String id, InstallationPage page) {
278
		// Changing the source provider will cause the contributions and the
279
		// button manager to be updated. If for some reason we don't have a
280
		// source provider, update it ourselves.
281
		if (sourceProvider != null)
282
			sourceProvider.setCurrentPage(id, page);
283
		else
284
			buttonManager.update(true);
285
	}
286
	
287
	protected InstallationDialogSourceProvider getSourceProvider() {
288
		return sourceProvider;
212
	}
289
	}
213
290
214
	/*
291
	/*
Lines 220-359 Link Here
220
	 */
297
	 */
221
	protected void createButtonsForButtonBar(Composite parent) {
298
	protected void createButtonsForButtonBar(Composite parent) {
222
		buttonManager = new ButtonManager(parent);
299
		buttonManager = new ButtonManager(parent);
300
		((IMenuService) serviceLocator.getService(IMenuService.class))
301
				.populateContributionManager(buttonManager, getButtonBarURI());
223
	}
302
	}
224
303
225
	/**
226
	 * @param folder2
227
	 */
228
	private void configureFolder() {
304
	private void configureFolder() {
229
		ColorRegistry reg = JFaceResources.getColorRegistry();
230
		Color c1 = reg.get(IWorkbenchThemeConstants.ACTIVE_TAB_BG_START), c2 = reg
231
				.get(IWorkbenchThemeConstants.ACTIVE_TAB_BG_END);
232
		folder.setSelectionBackground(new Color[] { c1, c2 }, new int[] { 50 },
233
				true);
234
		folder.setSelectionForeground(reg
235
				.get(IWorkbenchThemeConstants.ACTIVE_TAB_TEXT_COLOR));
236
		folder.setSimple(PlatformUI.getPreferenceStore().getBoolean(
237
				IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS));
238
239
	}
305
	}
240
306
241
	/**
242
	 * @return
243
	 */
244
	private IConfigurationElement[] loadElements() {
307
	private IConfigurationElement[] loadElements() {
245
		IExtensionPoint point = Platform.getExtensionRegistry()
308
		IExtensionPoint point = Platform.getExtensionRegistry()
246
				.getExtensionPoint("org.eclipse.ui", "installationPages"); //$NON-NLS-1$ //$NON-NLS-2$
309
				.getExtensionPoint("org.eclipse.ui", "installationPages"); //$NON-NLS-1$ //$NON-NLS-2$
247
		return point.getConfigurationElements();
310
		return point.getConfigurationElements();
248
	}
311
	}
249
312
250
	private String getButtonBarURI(String id) {
313
	protected void createDialogServiceLocator(IServiceLocatorCreator slc,
251
		return "toolbar:org.eclipse.ui.installationDialog.buttonbar/" + id; //$NON-NLS-1$
314
			IServiceLocator locator) {
252
	}
315
		AbstractServiceFactory localFactory = new AbstractServiceFactory() {
253
316
			public Object create(Class serviceInterface,
254
	protected String getToolbarURI(String id) {
317
					IServiceLocator parentLocator, IServiceLocator locator) {
255
		return "toolbar:org.eclipse.ui.installationDialog/" + id; //$NON-NLS-1$
318
				if (serviceInterface == IInstallationPageContainer.class) {
256
	}
319
					return InstallationDialog.this;
257
258
	private IServiceLocator createDialogServiceLocator(final CTabItem item) {
259
		return new IServiceLocator() {
260
261
			public Object getService(Class api) {
262
				if (api == IInstallationPageContainer.class)
263
					return new IInstallationPageContainer() {
264
265
						public String getButtonBarURI() {
266
							return InstallationDialog.this
267
									.getButtonBarURI((String) item.getData(ID));
268
						}
269
270
						public String getToolbarURI() {
271
							return InstallationDialog.this
272
									.getToolbarURI((String) item.getData(ID));
273
						}
274
275
						public void updateMessage() {
276
							// TBD
277
278
						}
279
						
280
						public void close() {
281
							InstallationDialog.this.close();
282
						}
283
					};
284
				else if (api == IMenuService.class) {
285
					return menuService;
286
				}
320
				}
287
				return serviceLocator.getService(api);
321
				return parentLocator.getService(serviceInterface);
288
			}
289
290
			public boolean hasService(Class api) {
291
				if (api == IInstallationPageContainer.class)
292
					return true;
293
				return serviceLocator.hasService(api);
294
			}
322
			}
295
		};
323
		};
324
		this.serviceLocator = slc.createServiceLocator(locator, localFactory,
325
				new IDisposable() {
326
					public void dispose() {
327
						close();
328
					}
329
				});
296
	}
330
	}
297
}
298
331
299
class ButtonManager extends ContributionManager {
332
	protected IDialogSettings getDialogBoundsSettings() {
333
		IDialogSettings settings = WorkbenchPlugin.getDefault()
334
				.getDialogSettings();
335
		IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
336
		if (section == null) {
337
			section = settings.addNewSection(DIALOG_SETTINGS_SECTION);
338
		}
339
		return section;
340
	}
300
341
301
	private Composite composite;
342
	protected void releaseContributions() {
343
		((IMenuService) serviceLocator.getService(IMenuService.class))
344
				.releaseContributions(buttonManager);
345
		buttonManager.removeAll();
346
	}
302
347
303
	/**
348
	/*
349
	 * (non-Javadoc)
304
	 * 
350
	 * 
351
	 * @see org.eclipse.ui.about.IInstallationPageContainer#getButtonBarURI()
305
	 */
352
	 */
306
	public ButtonManager(Composite composite) {
353
	public String getButtonBarURI() {
307
		this.composite = composite;
354
		return URI;
308
	}
355
	}
309
356
310
	/**
357
	public void closeContainer() {
311
	 * @return
358
		close();
312
	 */
359
	}
313
	public Composite getParent() {
360
314
		return composite;
361
	protected IServiceLocator getDialogServiceLocator() {
362
		return serviceLocator;
363
	}
364
365
	protected ButtonManager getButtonManager() {
366
		return buttonManager;
315
	}
367
	}
316
368
317
	/*
369
	/*
318
	 * (non-Javadoc)
370
	 * (non-Javadoc)
319
	 * 
371
	 * 
320
	 * @see org.eclipse.jface.action.IContributionManager#update(boolean)
372
	 * @see
373
	 * org.eclipse.ui.about.IInstallationPageContainer#getActivePageExpression
374
	 * (org.eclipse.ui.about.InstallationPage)
321
	 */
375
	 */
322
	public void update(boolean force) {
376
	public Expression getActivePageExpression(InstallationPage page) {
323
		if (composite == null || composite.isDisposed())
377
		return new ActiveInstallationPageExpression(page);
324
			return;
325
		GC metricsGC = new GC(composite);
326
		FontMetrics metrics = metricsGC.getFontMetrics();
327
		metricsGC.dispose();
328
		IContributionItem[] items = getItems();
329
		Control[] children = composite.getChildren();
330
331
		int visibleChildren = 0;
332
		for (int i = 0; i < children.length; i++) {
333
			Control control = children[i];
334
			control.dispose();
335
		}
336
337
		for (int i = 0; i < items.length; i++) {
338
			IContributionItem item = items[i];
339
			if (item.isVisible()) {
340
				item.fill(composite);
341
				children = composite.getChildren();
342
				Control itemControl = children[children.length - 1];
343
				setButtonLayoutData(metrics, itemControl);
344
				visibleChildren++;
345
			}
346
		}
347
		GridLayout compositeLayout = (GridLayout) composite.getLayout();
348
		compositeLayout.numColumns = visibleChildren;
349
		composite.layout(true);
350
	}
378
	}
351
	
379
352
	protected void setButtonLayoutData(FontMetrics metrics, Control button) {
380
	protected void resetVariables(InstallationDialogSourceProvider sp) {
353
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
381
		sp.resetAll();
354
		int widthHint = Dialog.convertHorizontalDLUsToPixels(metrics, IDialogConstants.BUTTON_WIDTH);
355
		Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
356
		data.widthHint = Math.max(widthHint, minSize.x);
357
		button.setLayoutData(data);
358
	}
382
	}
359
}
383
}
(-)Eclipse UI/org/eclipse/ui/about/InstallationPage.java (-4 / +4 lines)
Lines 6-20 Link Here
6
/**
6
/**
7
 * An installation dialog page.
7
 * An installation dialog page.
8
 * 
8
 * 
9
 * The counterpart, {@link IInstallationPageContainer}, may be accessed by the
9
 * The counterpart, {@link IInstallationPageContainer}, may be accessed using
10
 * page (via the provided service locator) to update the status message in the
10
 * the service locator.
11
 * hosting dialog.
12
 * 
11
 * 
13
 * <em>This API is experiemental and will change before 3.5 ships</em>
12
 * <em>This API is experimental and will change before 3.5 ships</em>
14
 * 
13
 * 
15
 * @since 3.5
14
 * @since 3.5
16
 */
15
 */
17
public abstract class InstallationPage extends DialogPage {
16
public abstract class InstallationPage extends DialogPage {
18
17
19
	public abstract void init(IServiceLocator locator);
18
	public abstract void init(IServiceLocator locator);
19
20
}
20
}
(-)Eclipse UI/org/eclipse/ui/about/IInstallationPageContainer.java (-19 / +2 lines)
Lines 11-16 Link Here
11
11
12
package org.eclipse.ui.about;
12
package org.eclipse.ui.about;
13
13
14
14
/**
15
/**
15
 * <em>This API is experimental and will change before 3.5 ships</em>
16
 * <em>This API is experimental and will change before 3.5 ships</em>
16
 * 
17
 * 
Lines 19-42 Link Here
19
public interface IInstallationPageContainer {
20
public interface IInstallationPageContainer {
20
21
21
	/**
22
	/**
22
	 * Updates the message (or error message) shown in the message line to
23
	 * reflect the state of the currently active page in this container.
24
	 * <p>
25
	 * This method is called by the container itself when its preference page
26
	 * changes and may be called by the page at other times to force a message
27
	 * update.
28
	 * </p>
29
	 */
30
	public void updateMessage();
31
32
	/**
33
	 * URI to be provided to the IMenuService for additions to the toolbar.
34
	 * 
35
	 * @return the toolbar uri
36
	 */
37
	public String getToolbarURI();
38
39
	/**
40
	 * URI to be provided to the IMenuService for additions to the button bar.
23
	 * URI to be provided to the IMenuService for additions to the button bar.
41
	 * 
24
	 * 
42
	 * This may not be desirable. We've never had a "button manager" before now,
25
	 * This may not be desirable. We've never had a "button manager" before now,
Lines 49-54 Link Here
49
	/**
32
	/**
50
	 * Closes the window that is hosting this container.
33
	 * Closes the window that is hosting this container.
51
	 */
34
	 */
52
	public void close();
35
	public void closeContainer();
53
	
36
	
54
}
37
}
(-)Eclipse UI/org/eclipse/ui/internal/messages.properties (-3 / +5 lines)
Lines 59-64 Link Here
59
ExportResourcesAction_toolTip = Export
59
ExportResourcesAction_toolTip = Export
60
ImportResourcesAction_text = &Import...
60
ImportResourcesAction_text = &Import...
61
ImportResourcesAction_toolTip = Import
61
ImportResourcesAction_toolTip = Import
62
OpenBrowserHandler_NoInfoDialogMessage=There was no additional information available.
63
OpenBrowserHandler_NoInfoDialogTitle=No Further Information
62
OpenRecent_errorTitle = Problems opening editor
64
OpenRecent_errorTitle = Problems opening editor
63
OpenRecent_unableToOpen = Unable to open ''{0}''.
65
OpenRecent_unableToOpen = Unable to open ''{0}''.
64
Exit_text = E&xit
66
Exit_text = E&xit
Lines 243-252 Link Here
243
DynamicHelpAction_text = &Dynamic Help
245
DynamicHelpAction_text = &Dynamic Help
244
DynamicHelpAction_toolTip = Dynamic Help
246
DynamicHelpAction_toolTip = Dynamic Help
245
AboutDialog_shellTitle = About {0}
247
AboutDialog_shellTitle = About {0}
246
AboutDialog_featureInfo = &Feature Details
247
AboutDialog_pluginInfo = &Plug-in Details
248
AboutDialog_systemInfo = &Configuration Details
249
AboutDialog_defaultProductName =
248
AboutDialog_defaultProductName =
249
AboutDialog_DetailsButton=&Installation Details
250
ProductInfoDialog_errorTitle = Problems Opening Link
250
ProductInfoDialog_errorTitle = Problems Opening Link
251
ProductInfoDialog_unableToOpenWebBrowser = Unable to open web browser on {0}
251
ProductInfoDialog_unableToOpenWebBrowser = Unable to open web browser on {0}
252
PreferencesExportDialog_ErrorDialogTitle=Error
252
PreferencesExportDialog_ErrorDialogTitle=Error
Lines 282-287 Link Here
282
AboutFeaturesDialog_pluginInfoTitle = Feature Plug-ins
282
AboutFeaturesDialog_pluginInfoTitle = Feature Plug-ins
283
AboutFeaturesDialog_pluginInfoMessage = Plug-ins contributed by feature: {0}
283
AboutFeaturesDialog_pluginInfoMessage = Plug-ins contributed by feature: {0}
284
AboutFeaturesDialog_noInfoTitle = No Further Information
284
AboutFeaturesDialog_noInfoTitle = No Further Information
285
AboutFeaturesDialog_SimpleTitle=Features
285
AboutSystemDialog_browseErrorLogName = &View Error Log
286
AboutSystemDialog_browseErrorLogName = &View Error Log
286
AboutSystemDialog_copyToClipboardName = Copy &to Clipboard
287
AboutSystemDialog_copyToClipboardName = Copy &to Clipboard
287
AboutSystemDialog_noLogTitle = Error Log Not Found
288
AboutSystemDialog_noLogTitle = Error Log Not Found
Lines 518-523 Link Here
518
# ==============================================================================
519
# ==============================================================================
519
Error = Error
520
Error = Error
520
Information = Information
521
Information = Information
522
InstallationDialog_ShellTitle={0} Installation Details
521
523
522
Workbench_NeedsClose_Title = Restart Needed
524
Workbench_NeedsClose_Title = Restart Needed
523
Workbench_NeedsClose_Message = A required plug-in is no longer available and the Workbench needs to be restarted. You will be prompted to save if there is any unsaved work.
525
Workbench_NeedsClose_Message = A required plug-in is no longer available and the Workbench needs to be restarted. You will be prompted to save if there is any unsaved work.
(-)Eclipse UI/org/eclipse/ui/internal/ConfigurationInfo.java (-6 / +5 lines)
Lines 80-86 Link Here
80
	 * extension point.
80
	 * extension point.
81
	 */
81
	 */
82
	private static void appendExtensions(PrintWriter writer) {
82
	private static void appendExtensions(PrintWriter writer) {
83
		IConfigurationElement[] configElements = getSortedExtensions();
83
		IConfigurationElement[] configElements = getSortedExtensions(Platform
84
				.getExtensionRegistry().getConfigurationElementsFor(
85
						PlatformUI.PLUGIN_ID,
86
						IWorkbenchRegistryConstants.PL_SYSTEM_SUMMARY_SECTIONS));
84
		for (int i = 0; i < configElements.length; ++i) {
87
		for (int i = 0; i < configElements.length; ++i) {
85
			IConfigurationElement element = configElements[i];
88
			IConfigurationElement element = configElements[i];
86
89
Lines 108-118 Link Here
108
		}
111
		}
109
	}
112
	}
110
113
111
	private static IConfigurationElement[] getSortedExtensions() {
114
	public static IConfigurationElement[] getSortedExtensions(IConfigurationElement[] configElements) {
112
		IConfigurationElement[] configElements = Platform
113
				.getExtensionRegistry().getConfigurationElementsFor(
114
						PlatformUI.PLUGIN_ID,
115
						IWorkbenchRegistryConstants.PL_SYSTEM_SUMMARY_SECTIONS);
116
115
117
		Arrays.sort(configElements, new Comparator() {
116
		Arrays.sort(configElements, new Comparator() {
118
			Collator collator = Collator.getInstance(Locale.getDefault());
117
			Collator collator = Collator.getInstance(Locale.getDefault());
(-)Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java (-3 / +15 lines)
Lines 98-103 Link Here
98
	public static String ExportResourcesAction_toolTip;
98
	public static String ExportResourcesAction_toolTip;
99
	public static String ImportResourcesAction_text;
99
	public static String ImportResourcesAction_text;
100
	public static String ImportResourcesAction_toolTip;
100
	public static String ImportResourcesAction_toolTip;
101
	public static String OpenBrowserHandler_NoInfoDialogMessage;
102
103
104
	public static String OpenBrowserHandler_NoInfoDialogTitle;
105
106
101
	public static String OpenRecent_errorTitle;
107
	public static String OpenRecent_errorTitle;
102
	public static String OpenRecent_unableToOpen;
108
	public static String OpenRecent_unableToOpen;
103
	public static String Exit_text;
109
	public static String Exit_text;
Lines 283-292 Link Here
283
	public static String DynamicHelpAction_text;
289
	public static String DynamicHelpAction_text;
284
	public static String DynamicHelpAction_toolTip;
290
	public static String DynamicHelpAction_toolTip;
285
	public static String AboutDialog_shellTitle;
291
	public static String AboutDialog_shellTitle;
286
	public static String AboutDialog_featureInfo;
287
	public static String AboutDialog_pluginInfo;
288
	public static String AboutDialog_systemInfo;
289
	public static String AboutDialog_defaultProductName;
292
	public static String AboutDialog_defaultProductName;
293
294
295
	public static String AboutDialog_DetailsButton;
290
	public static String ProductInfoDialog_errorTitle;
296
	public static String ProductInfoDialog_errorTitle;
291
	public static String ProductInfoDialog_unableToOpenWebBrowser;
297
	public static String ProductInfoDialog_unableToOpenWebBrowser;
292
	public static String PreferencesExportDialog_ErrorDialogTitle;
298
	public static String PreferencesExportDialog_ErrorDialogTitle;
Lines 322-327 Link Here
322
	public static String AboutFeaturesDialog_pluginInfoTitle;
328
	public static String AboutFeaturesDialog_pluginInfoTitle;
323
	public static String AboutFeaturesDialog_pluginInfoMessage;
329
	public static String AboutFeaturesDialog_pluginInfoMessage;
324
	public static String AboutFeaturesDialog_noInfoTitle;
330
	public static String AboutFeaturesDialog_noInfoTitle;
331
332
333
	public static String AboutFeaturesDialog_SimpleTitle;
325
	public static String AboutSystemDialog_browseErrorLogName;
334
	public static String AboutSystemDialog_browseErrorLogName;
326
	public static String AboutSystemDialog_copyToClipboardName;
335
	public static String AboutSystemDialog_copyToClipboardName;
327
	public static String AboutSystemDialog_noLogTitle;
336
	public static String AboutSystemDialog_noLogTitle;
Lines 551-556 Link Here
551
	// ==============================================================================
560
	// ==============================================================================
552
	public static String Error;
561
	public static String Error;
553
	public static String Information;
562
	public static String Information;
563
564
565
	public static String InstallationDialog_ShellTitle;
554
	
566
	
555
	public static String Workbench_NeedsClose_Title;
567
	public static String Workbench_NeedsClose_Title;
556
	public static String Workbench_NeedsClose_Message;
568
	public static String Workbench_NeedsClose_Message;
(-)Eclipse (+140 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 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.about;
12
13
import org.eclipse.core.expressions.Expression;
14
import org.eclipse.swt.SWT;
15
import org.eclipse.swt.events.DisposeEvent;
16
import org.eclipse.swt.events.DisposeListener;
17
import org.eclipse.swt.layout.GridLayout;
18
import org.eclipse.swt.widgets.Composite;
19
import org.eclipse.swt.widgets.Shell;
20
import org.eclipse.swt.widgets.TabFolder;
21
import org.eclipse.swt.widgets.TabItem;
22
import org.eclipse.ui.PlatformUI;
23
import org.eclipse.ui.about.InstallationPage;
24
25
/**
26
 * Abstract superclass of the individual about dialogs that appear outside of
27
 * the InstallationDialog These dialogs contain a single installation page, and
28
 * scope the page to something more specific than it would be in the standard
29
 * installation dialog.
30
 * 
31
 * It is important that the visibility and enablement expressions of
32
 * contributions to this dialog, and the source variables that drive them, do
33
 * not conflict with those used inside the normal InstallationDialog. Otherwise,
34
 * the button manager of the InstallationDialog will be affected by changes in
35
 * the launched dialog. Where commands have enablement expressions in this
36
 * dialog, we use a unique command id so that there are no handler conflicts
37
 * with the regular dialog.
38
 */
39
40
public abstract class ProductInfoDialog extends InstallationDialog {
41
42
	ProductInfoPage page;
43
	String title;
44
	String helpContextId;
45
	Object previouslyActivePage;
46
	Object previouslyActiveSelection;
47
48
	protected ProductInfoDialog(Shell shell) {
49
		super(shell, PlatformUI.getWorkbench().getActiveWorkbenchWindow());
50
		// capture the previous variables values.  This is used for
51
		// nested product info dialogs, such as a feature dialog that opens a
52
		// plugins dialog
53
		previouslyActivePage = getSourceProvider().getCurrentState().get(
54
				InstallationDialogSourceProvider.ACTIVE_PRODUCT_DIALOG_PAGE);
55
		previouslyActiveSelection = getSourceProvider()
56
				.getCurrentState()
57
				.get(
58
						InstallationDialogSourceProvider.ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION);
59
60
	}
61
62
	public void initializeDialog(ProductInfoPage page, String title,
63
			String helpContextId) {
64
		this.page = page;
65
		this.title = title;
66
		this.helpContextId = helpContextId;
67
	}
68
69
	protected void createFolderItems(TabFolder folder) {
70
		TabItem item = new TabItem(folder, SWT.NONE);
71
		item.setText(title);
72
		Composite control = new Composite(folder, SWT.BORDER);
73
		control.setLayout(new GridLayout());
74
		item.setControl(control);
75
		page.createControl(control);
76
		// must set up the page data before creating the service locator.
77
		// The id is used by the dialog service locator
78
		item.setData(page);
79
		item.setData(ID, page.getId());
80
		page.init(getDialogServiceLocator());
81
		item.addDisposeListener(new DisposeListener() {
82
83
			public void widgetDisposed(DisposeEvent e) {
84
				page.dispose();
85
			}
86
		});
87
		control.layout(true, true);
88
	}
89
90
	/*
91
	 * (non-Javadoc)
92
	 * 
93
	 * @see
94
	 * org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets
95
	 * .Shell)
96
	 */
97
	protected void configureShell(Shell newShell) {
98
		super.configureShell(newShell);
99
		newShell.setText(title);
100
		if (helpContextId != null)
101
			PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
102
					helpContextId);
103
	}
104
105
	/*
106
	 * (non-Javadoc)
107
	 * 
108
	 * @see org.eclipse.ui.about.IInstallationPageContainer#getButtonBarURI()
109
	 */
110
	public String getButtonBarURI() {
111
		return super.getButtonBarURI() + "." + page.getId(); //$NON-NLS-1$
112
	}
113
114
	protected void updateContributions(String id, InstallationPage page) {
115
		InstallationDialogSourceProvider sp = getSourceProvider();
116
		if (sp != null) {
117
			sp.setProductDialogPage((ProductInfoPage) page);
118
		}
119
		getButtonManager().update(true);
120
	}
121
122
	/*
123
	 * (non-Javadoc)
124
	 * 
125
	 * @see
126
	 * org.eclipse.ui.about.IInstallationPageContainer#getActivePageExpression
127
	 * (org.eclipse.ui.about.InstallationPage)
128
	 */
129
	public Expression getActivePageExpression(InstallationPage page) {
130
		// We have our own menu URI and do not share with other pages, so
131
		// there is no visibility expression needed.
132
		return null;
133
	}
134
135
	protected void resetVariables(InstallationDialogSourceProvider sp) {
136
		sp.setProductDialogPage(previouslyActivePage);
137
		sp.setProductDialogPageSelection(previouslyActiveSelection);
138
	}
139
140
}
(-)Eclipse (+105 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.about;
13
14
import org.eclipse.core.expressions.EvaluationResult;
15
import org.eclipse.core.expressions.Expression;
16
import org.eclipse.core.expressions.ExpressionInfo;
17
import org.eclipse.core.expressions.IEvaluationContext;
18
19
/**
20
 * <p>
21
 * An expression that checks the active InstallationPage variable. The variable
22
 * name is <code>IInstallationPageSources.ACTIVE_PAGE</code>.
23
 * </p>
24
 * 
25
 * <em>This API is experimental and will change before 3.5 ships</em>
26
 * 
27
 * @since 3.5
28
 */
29
public final class ActiveInstallationPageExpression extends Expression {
30
31
	/**
32
	 * The seed for the hash code for all schemes.
33
	 */
34
	private static final int HASH_INITIAL = ActiveInstallationPageExpression.class
35
			.getName().hashCode();
36
37
	/**
38
	 * The page that must be active for this expression to evaluate to
39
	 * <code>true</code>. If this value is <code>null</code>, then any page may
40
	 * be active.
41
	 */
42
	private final InstallationPage page;
43
44
	/**
45
	 * Constructs a new instance of <code>ActiveShellExpression</code>
46
	 * 
47
	 * @param page
48
	 *            The page to match with the active installation page;
49
	 *            <code>null</code> if it will match any active page.
50
	 */
51
	public ActiveInstallationPageExpression(final InstallationPage page) {
52
		this.page = page;
53
	}
54
55
	/**
56
	 * Expression information for this expression.
57
	 * 
58
	 * @since 3.5
59
	 */
60
	public final void collectExpressionInfo(final ExpressionInfo info) {
61
		info.addVariableNameAccess(IInstallationPageSources.ACTIVE_PAGE);
62
	}
63
64
	protected final int computeHashCode() {
65
		return HASH_INITIAL * HASH_FACTOR + hashCode(page);
66
	}
67
68
	public final boolean equals(final Object object) {
69
		if (object instanceof ActiveInstallationPageExpression) {
70
			final ActiveInstallationPageExpression that = (ActiveInstallationPageExpression) object;
71
			return equals(this.page, that.page);
72
		}
73
74
		return false;
75
	}
76
77
	/**
78
	 * Evaluates this expression. If the active page defined by the context
79
	 * matches the page from this expression, then this evaluates to
80
	 * <code>EvaluationResult.TRUE</code>.
81
	 * 
82
	 * @param context
83
	 *            The context from which the current state is determined; must
84
	 *            not be <code>null</code>.
85
	 * @return <code>EvaluationResult.TRUE</code> if the page is active;
86
	 *         <code>EvaluationResult.FALSE</code> otherwise.
87
	 */
88
	public final EvaluationResult evaluate(final IEvaluationContext context) {
89
		if (page != null) {
90
			Object value = context
91
					.getVariable(IInstallationPageSources.ACTIVE_PAGE);
92
			if (page.equals(value))
93
				return EvaluationResult.TRUE;
94
		}
95
		return EvaluationResult.FALSE;
96
	}
97
98
	public final String toString() {
99
		final StringBuffer buffer = new StringBuffer();
100
		buffer.append("ActiveInstallationPageExpression("); //$NON-NLS-1$
101
		buffer.append(page);
102
		buffer.append(')');
103
		return buffer.toString();
104
	}
105
}
(-)Eclipse (+148 lines)
Added Link Here
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
 *******************************************************************************/
11
package org.eclipse.ui.internal.about;
12
13
import org.eclipse.core.runtime.IProduct;
14
import org.eclipse.core.runtime.Platform;
15
import org.eclipse.jface.window.IShellProvider;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.events.DisposeEvent;
18
import org.eclipse.swt.events.DisposeListener;
19
import org.eclipse.swt.layout.GridData;
20
import org.eclipse.swt.layout.GridLayout;
21
import org.eclipse.swt.widgets.Composite;
22
import org.eclipse.swt.widgets.Control;
23
import org.eclipse.ui.about.IInstallationPageContainer;
24
import org.eclipse.ui.about.InstallationPage;
25
import org.eclipse.ui.internal.WorkbenchMessages;
26
import org.eclipse.ui.menus.AbstractContributionFactory;
27
import org.eclipse.ui.menus.IMenuService;
28
import org.eclipse.ui.services.IServiceLocator;
29
30
/**
31
 * Abstract superclass of about dialog installation pages.  The ProductInfoPage
32
 * is set up so that the page can be hosted as one of many pages in the
33
 * InstallationDialog, or as the only page in a ProductInfoDialog.
34
 * When hosted inside a ProductInfoDialog, the page id, source variables,
35
 * command contributions, and associated visibility/enablement expressions, are
36
 * different than when hosted as a page in the InstallationDialog.  This is important
37
 * because another instance of the page may be launched from an InstallationDialog, and
38
 * this secondary page should not affect the contributions of the originating dialog.
39
 */
40
41
public abstract class ProductInfoPage extends InstallationPage implements
42
		IShellProvider {
43
44
	private IMenuService menuService;
45
46
	private InstallationDialog dialog;
47
48
	private AbstractContributionFactory factory;
49
50
	private IProduct product;
51
52
	private String productName;
53
54
	/*
55
	 * (non-Javadoc)
56
	 * 
57
	 * @seeorg.eclipse.ui.about.InstallationPage#init(org.eclipse.ui.services.
58
	 * IServiceLocator)
59
	 */
60
	public void init(IServiceLocator locator) {
61
		IInstallationPageContainer pageContainer = (IInstallationPageContainer) locator
62
				.getService(IInstallationPageContainer.class);
63
		// Must cast to dialog because we rely on the ProductInfoDialog framework
64
		// to provide us with the appropriate variables and visibility expressions
65
		dialog = (InstallationDialog)pageContainer;
66
		menuService = (IMenuService) locator.getService(IMenuService.class);
67
		// this assumes that the control is created before init
68
		addButtons();
69
	}
70
71
	protected IMenuService getMenuService() {
72
		return menuService;
73
	}
74
75
	protected InstallationDialog getInstallationDialog() {
76
		return dialog;
77
	}
78
79
	protected IProduct getProduct() {
80
		if (product == null)
81
			product = Platform.getProduct();
82
		return product;
83
	}
84
85
	public String getProductName() {
86
		if (productName == null) {
87
			if (getProduct() != null) {
88
				productName = getProduct().getName();
89
			}
90
			if (productName == null) {
91
				productName = WorkbenchMessages.AboutDialog_defaultProductName;
92
			}
93
		}
94
		return productName;
95
	}
96
97
	public void setProductName(String name) {
98
		productName = name;
99
	}
100
101
	abstract String getId();
102
103
	public final void createControl(Composite parent) {
104
		Control control = createPageControl(parent);
105
		control.addDisposeListener(new DisposeListener() {
106
			public void widgetDisposed(DisposeEvent e) {
107
				releaseContributionFactory();
108
			}
109
		});
110
		setControl(control);
111
	}
112
	
113
	protected abstract Control createPageControl(Composite parent);
114
115
	protected Composite createOuterComposite(Composite parent) {
116
		Composite composite = new Composite(parent, SWT.NONE);
117
		GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
118
		composite.setLayoutData(gd);
119
		GridLayout layout = new GridLayout();
120
		layout.marginWidth = 0;
121
		layout.marginHeight = 0;
122
		composite.setLayout(layout);
123
		return composite;
124
	}
125
126
	private void addButtons() {
127
		if (menuService == null)
128
			return;
129
		factory = makeContributionFactory();
130
		if (factory != null)
131
			menuService.addContributionFactory(factory);
132
	}
133
134
	protected AbstractContributionFactory makeContributionFactory() {
135
		return null;
136
	}
137
138
	protected void releaseContributionFactory() {
139
		if (factory != null) {
140
			menuService.removeContributionFactory(factory);
141
			factory = null;
142
		}
143
	}
144
	
145
	protected void copyToClipboard() {
146
		// Do nothing by default
147
	}
148
}
(-)Eclipse (+138 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import java.util.HashMap;
15
import java.util.Map;
16
17
import org.eclipse.core.expressions.IEvaluationContext;
18
import org.eclipse.ui.AbstractSourceProvider;
19
import org.eclipse.ui.ISources;
20
import org.eclipse.ui.about.IInstallationPageSources;
21
import org.eclipse.ui.about.InstallationPage;
22
23
/**
24
 * A registered source provider that can update variables associated with an
25
 * InstallationDialog.
26
 * 
27
 * @since 3.5
28
 */
29
public class InstallationDialogSourceProvider extends AbstractSourceProvider {
30
	Map currentState;
31
32
	/**
33
	 * These variables are internal to the about framework. They are only needed
34
	 * because some of the platform about pages can be launched into their own
35
	 * nested ProductInfoDialog from another platform about page. We need
36
	 * different variables for the visibility expressions for those cases,
37
	 * because the launching InstallationDialog is still open and using the
38
	 * regular variables.
39
	 */
40
	public static final String ACTIVE_PRODUCT_DIALOG_PAGE = "org.eclipse.ui.internal.about.activeProductDialogPage"; //$NON-NLS-1$
41
	public static final String ACTIVE_PRODUCT_DIALOG_PAGE_ID = "org.eclipse.ui.internal.about.activeProductDialogPageId"; //$NON-NLS-1$
42
	public static final String ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION = "org.eclipse.ui.internal.about.activeProductDialogSelection"; //$NON-NLS-1$
43
44
	/*
45
	 * (non-Javadoc)
46
	 * 
47
	 * @see org.eclipse.ui.ISourceProvider#dispose()
48
	 */
49
	public void dispose() {
50
		currentState = null;
51
	}
52
53
	/*
54
	 * (non-Javadoc)
55
	 * 
56
	 * @see org.eclipse.ui.ISourceProvider#getCurrentState()
57
	 */
58
	public Map getCurrentState() {
59
		if (currentState == null) {
60
			currentState = new HashMap();
61
			currentState.put(IInstallationPageSources.ACTIVE_PAGE,
62
					IEvaluationContext.UNDEFINED_VARIABLE);
63
			currentState.put(IInstallationPageSources.ACTIVE_PAGE_ID,
64
					IEvaluationContext.UNDEFINED_VARIABLE);
65
			currentState.put(IInstallationPageSources.ACTIVE_PAGE_SELECTION,
66
					IEvaluationContext.UNDEFINED_VARIABLE);
67
			currentState.put(ACTIVE_PRODUCT_DIALOG_PAGE,
68
					IEvaluationContext.UNDEFINED_VARIABLE);
69
			currentState.put(ACTIVE_PRODUCT_DIALOG_PAGE_ID,
70
					IEvaluationContext.UNDEFINED_VARIABLE);
71
			currentState.put(ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION,
72
					IEvaluationContext.UNDEFINED_VARIABLE);
73
		}
74
		return currentState;
75
	}
76
77
	public void setCurrentPage(String id, InstallationPage page) {
78
		Map map = getCurrentState();
79
		map.put(IInstallationPageSources.ACTIVE_PAGE_ID, id);
80
		map.put(IInstallationPageSources.ACTIVE_PAGE, page);
81
		fireSourceChanged(ISources.WORKBENCH,
82
				IInstallationPageSources.ACTIVE_PAGE_ID, id);
83
		fireSourceChanged(ISources.WORKBENCH,
84
				IInstallationPageSources.ACTIVE_PAGE, page);
85
	}
86
87
	/*
88
	 * (non-Javadoc)
89
	 * 
90
	 * @see org.eclipse.ui.ISourceProvider#getProvidedSourceNames()
91
	 */
92
	public String[] getProvidedSourceNames() {
93
		return new String[] { IInstallationPageSources.ACTIVE_PAGE,
94
				IInstallationPageSources.ACTIVE_PAGE_ID,
95
				IInstallationPageSources.ACTIVE_PAGE_SELECTION,
96
				ACTIVE_PRODUCT_DIALOG_PAGE, ACTIVE_PRODUCT_DIALOG_PAGE_ID,
97
				ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION };
98
	}
99
100
	public void setProductDialogPage(Object page) {
101
		Map map = getCurrentState();
102
		Object pageValue, idValue;
103
		if (page instanceof ProductInfoPage) {
104
			map.put(ACTIVE_PRODUCT_DIALOG_PAGE, pageValue = page);
105
			map.put(ACTIVE_PRODUCT_DIALOG_PAGE_ID,
106
					idValue = ((ProductInfoPage) page).getId());
107
		} else {
108
			map.put(ACTIVE_PRODUCT_DIALOG_PAGE,
109
					pageValue = IEvaluationContext.UNDEFINED_VARIABLE);
110
			map.put(ACTIVE_PRODUCT_DIALOG_PAGE_ID,
111
					idValue = IEvaluationContext.UNDEFINED_VARIABLE);
112
		}
113
		fireSourceChanged(ISources.WORKBENCH, ACTIVE_PRODUCT_DIALOG_PAGE,
114
				pageValue);
115
		fireSourceChanged(ISources.WORKBENCH, ACTIVE_PRODUCT_DIALOG_PAGE_ID,
116
				idValue);
117
	}
118
119
	public void setPageSelection(Object selection) {
120
		Map map = getCurrentState();
121
		map.put(IInstallationPageSources.ACTIVE_PAGE_SELECTION, selection);
122
		fireSourceChanged(ISources.WORKBENCH,
123
				IInstallationPageSources.ACTIVE_PAGE_SELECTION, selection);
124
	}
125
126
	public void setProductDialogPageSelection(Object selection) {
127
		Map map = getCurrentState();
128
		map.put(ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION, selection);
129
		fireSourceChanged(ISources.WORKBENCH,
130
				ACTIVE_PRODUCT_DIALOG_PAGE_SELECTION, selection);
131
	}
132
133
	public void resetAll() {
134
		currentState = null;
135
		Map map = getCurrentState();
136
		fireSourceChanged(ISources.WORKBENCH, map);
137
	}
138
}
(-)Eclipse (+303 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007, 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import java.io.IOException;
15
import java.security.GeneralSecurityException;
16
import java.security.cert.Certificate;
17
import java.security.cert.X509Certificate;
18
import java.text.DateFormat;
19
import java.util.ArrayList;
20
import java.util.Date;
21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Map;
24
import java.util.Properties;
25
import java.util.StringTokenizer;
26
import java.util.Map.Entry;
27
28
import org.eclipse.core.runtime.IProgressMonitor;
29
import org.eclipse.core.runtime.IStatus;
30
import org.eclipse.core.runtime.OperationCanceledException;
31
import org.eclipse.core.runtime.Status;
32
import org.eclipse.core.runtime.jobs.Job;
33
import org.eclipse.jface.dialogs.Dialog;
34
import org.eclipse.jface.resource.JFaceResources;
35
import org.eclipse.osgi.signedcontent.SignedContent;
36
import org.eclipse.osgi.signedcontent.SignedContentFactory;
37
import org.eclipse.osgi.signedcontent.SignerInfo;
38
import org.eclipse.osgi.util.NLS;
39
import org.eclipse.swt.SWT;
40
import org.eclipse.swt.custom.StyledText;
41
import org.eclipse.swt.graphics.GC;
42
import org.eclipse.swt.graphics.Point;
43
import org.eclipse.swt.layout.GridData;
44
import org.eclipse.swt.layout.GridLayout;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.swt.widgets.Control;
47
import org.eclipse.swt.widgets.Label;
48
import org.eclipse.swt.widgets.Text;
49
import org.eclipse.ui.PlatformUI;
50
import org.eclipse.ui.internal.WorkbenchMessages;
51
import org.eclipse.ui.internal.WorkbenchPlugin;
52
import org.eclipse.ui.statushandlers.StatusManager;
53
import org.osgi.framework.BundleContext;
54
import org.osgi.framework.ServiceReference;
55
56
/**
57
 * @since 3.3
58
 * 
59
 */
60
public class BundleSigningInfo {
61
62
	private Composite composite;
63
	private Text date;
64
	private StyledText certificate;
65
	private AboutBundleData data;
66
67
	public BundleSigningInfo() {
68
	}
69
70
	public void setData(AboutBundleData data) {
71
		this.data = data;
72
		startJobs();
73
	}
74
75
	public Control createContents(Composite parent) {
76
77
		composite = new Composite(parent, SWT.BORDER);
78
		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
79
		GridLayout layout = new GridLayout(2, false);
80
		layout.marginHeight = 0;
81
		layout.marginWidth = 0;
82
		composite.setLayout(layout);
83
84
		// date
85
		{
86
			Label label = new Label(composite, SWT.NONE);
87
			label.setText(WorkbenchMessages.BundleSigningTray_Signing_Date);
88
			GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false);
89
			date = new Text(composite, SWT.READ_ONLY);
90
			GC gc = new GC(date);
91
			gc.setFont(JFaceResources.getDialogFont());
92
			Point size = gc.stringExtent(DateFormat.getDateTimeInstance()
93
					.format(new Date()));
94
			data.widthHint = size.x;
95
			gc.dispose();
96
			date.setText(WorkbenchMessages.BundleSigningTray_Working);
97
			date.setLayoutData(data);
98
		}
99
		// signer
100
		{
101
			Label label = new Label(composite, SWT.NONE);
102
			label
103
					.setText(WorkbenchMessages.BundleSigningTray_Signing_Certificate);
104
			GridData data = new GridData(SWT.BEGINNING, SWT.BEGINNING, true,
105
					false);
106
			data.horizontalSpan = 2;
107
			data = new GridData(SWT.FILL, SWT.FILL, true, true);
108
			data.horizontalSpan = 2;
109
			certificate = new StyledText(composite, SWT.READ_ONLY | SWT.MULTI
110
					| SWT.WRAP);
111
			certificate.setText(WorkbenchMessages.BundleSigningTray_Working);
112
			certificate.setLayoutData(data);
113
		}
114
		Dialog.applyDialogFont(composite);
115
116
		startJobs(); // start the jobs that will prime the content
117
		return composite;
118
	}
119
120
	/**
121
	 * 
122
	 */
123
	private void startJobs() {
124
		if (!isOpen())
125
			return;
126
		certificate.setText(WorkbenchMessages.BundleSigningTray_Working);
127
		date.setText(WorkbenchMessages.BundleSigningTray_Working);
128
		final BundleContext bundleContext = WorkbenchPlugin.getDefault()
129
				.getBundleContext();
130
		final ServiceReference factoryRef = bundleContext
131
				.getServiceReference(SignedContentFactory.class.getName());
132
		if (factoryRef == null) {
133
			StatusManager
134
					.getManager()
135
					.handle(
136
							new Status(
137
									IStatus.WARNING,
138
									WorkbenchPlugin.PI_WORKBENCH,
139
									WorkbenchMessages.BundleSigningTray_Cant_Find_Service),
140
							StatusManager.LOG);
141
			return;
142
		}
143
144
		final SignedContentFactory contentFactory = (SignedContentFactory) bundleContext
145
				.getService(factoryRef);
146
		if (contentFactory == null) {
147
			StatusManager
148
					.getManager()
149
					.handle(
150
							new Status(
151
									IStatus.WARNING,
152
									WorkbenchPlugin.PI_WORKBENCH,
153
									WorkbenchMessages.BundleSigningTray_Cant_Find_Service),
154
							StatusManager.LOG);
155
			return;
156
		}
157
158
		final AboutBundleData myData = data;
159
		final Job signerJob = new Job(NLS.bind(
160
				WorkbenchMessages.BundleSigningTray_Determine_Signer_For,
161
				myData.getId())) {
162
163
			protected IStatus run(IProgressMonitor monitor) {
164
				try {
165
					if (myData != data)
166
						return Status.OK_STATUS;
167
					SignedContent signedContent = contentFactory
168
							.getSignedContent(myData.getBundle());
169
					if (myData != data)
170
						return Status.OK_STATUS;
171
					SignerInfo[] signers = signedContent.getSignerInfos();
172
					final String signerText, dateText;
173
					if (!isOpen() && BundleSigningInfo.this.data == myData)
174
						return Status.OK_STATUS;
175
176
					if (signers.length == 0) {
177
						signerText = WorkbenchMessages.BundleSigningTray_Unsigned;
178
						dateText = WorkbenchMessages.BundleSigningTray_Unsigned;
179
					} else {
180
						Properties[] certs = parseCerts(signers[0]
181
								.getCertificateChain());
182
						if (certs.length == 0)
183
							signerText = WorkbenchMessages.BundleSigningTray_Unknown;
184
						else {
185
							StringBuffer buffer = new StringBuffer();
186
							for (Iterator i = certs[0].entrySet().iterator(); i
187
									.hasNext();) {
188
								Map.Entry entry = (Entry) i.next();
189
								buffer.append(entry.getKey());
190
								buffer.append('=');
191
								buffer.append(entry.getValue());
192
								if (i.hasNext())
193
									buffer.append('\n');
194
							}
195
							signerText = buffer.toString();
196
						}
197
198
						Date signDate = signedContent
199
								.getSigningTime(signers[0]);
200
						if (signDate != null)
201
							dateText = DateFormat.getDateTimeInstance().format(
202
									signDate);
203
						else
204
							dateText = WorkbenchMessages.BundleSigningTray_Unknown;
205
					}
206
207
					PlatformUI.getWorkbench().getDisplay().asyncExec(
208
							new Runnable() {
209
								public void run() {
210
									// check to see if the tray is still visible
211
									// and if
212
									// we're still looking at the same item
213
									if (!isOpen()
214
											&& BundleSigningInfo.this.data != myData)
215
										return;
216
									certificate.setText(signerText);
217
									date.setText(dateText);
218
								}
219
							});
220
221
				} catch (IOException e) {
222
					return new Status(IStatus.ERROR,
223
							WorkbenchPlugin.PI_WORKBENCH, e.getMessage(), e);
224
				} catch (GeneralSecurityException e) {
225
					return new Status(IStatus.ERROR,
226
							WorkbenchPlugin.PI_WORKBENCH, e.getMessage(), e);
227
				}
228
				return Status.OK_STATUS;
229
			}
230
		};
231
		signerJob.setSystem(true);
232
		signerJob.belongsTo(signerJob);
233
		signerJob.schedule();
234
235
		Job cleanup = new Job(
236
				WorkbenchMessages.BundleSigningTray_Unget_Signing_Service) {
237
238
			protected IStatus run(IProgressMonitor monitor) {
239
				try {
240
					getJobManager().join(signerJob, monitor);
241
				} catch (OperationCanceledException e) {
242
				} catch (InterruptedException e) {
243
				}
244
				bundleContext.ungetService(factoryRef);
245
				return Status.OK_STATUS;
246
			}
247
		};
248
		cleanup.setSystem(true);
249
		cleanup.schedule();
250
251
	}
252
253
	/**
254
	 * 
255
	 */
256
	private boolean isOpen() {
257
		return certificate != null && !certificate.isDisposed();
258
	}
259
260
	private Properties[] parseCerts(Certificate[] chain) {
261
		List certs = new ArrayList(chain.length);
262
		for (int i = 0; i < chain.length; i++) {
263
			if (!(chain[i] instanceof X509Certificate))
264
				continue;
265
			Map cert = parseCert(((X509Certificate) chain[i]).getSubjectDN()
266
					.getName());
267
			if (cert != null)
268
				certs.add(cert);
269
		}
270
		return (Properties[]) certs.toArray(new Properties[certs.size()]);
271
272
	}
273
274
	/**
275
	 * @param certString
276
	 * @return
277
	 */
278
	private Properties parseCert(String certString) {
279
		StringTokenizer toker = new StringTokenizer(certString, ","); //$NON-NLS-1$
280
		Properties cert = new Properties();
281
		while (toker.hasMoreTokens()) {
282
			String pair = toker.nextToken();
283
			int idx = pair.indexOf('=');
284
			if (idx > 0 && idx < pair.length() - 2) {
285
				String key = pair.substring(0, idx).trim();
286
				String value = pair.substring(idx + 1).trim();
287
				if (value.length() > 2) {
288
					if (value.charAt(0) == '\"')
289
						value = value.substring(1);
290
291
					if (value.charAt(value.length() - 1) == '\"')
292
						value = value.substring(0, value.length() - 1);
293
				}
294
				cert.setProperty(key, value);
295
			}
296
		}
297
		return cert;
298
	}
299
300
	public void dispose() {
301
		composite.dispose();
302
	}
303
}
(-)Eclipse (+647 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 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
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
11
 * 		font should be activated and used by other components.
12
 *******************************************************************************/
13
package org.eclipse.ui.internal.about;
14
15
import java.io.IOException;
16
import java.net.URL;
17
import java.util.ArrayList;
18
import java.util.Collection;
19
import java.util.HashMap;
20
import java.util.LinkedList;
21
import java.util.List;
22
import java.util.Map;
23
24
import org.eclipse.core.runtime.IPath;
25
import org.eclipse.core.runtime.IProgressMonitor;
26
import org.eclipse.core.runtime.IStatus;
27
import org.eclipse.core.runtime.Path;
28
import org.eclipse.core.runtime.Platform;
29
import org.eclipse.core.runtime.Status;
30
import org.eclipse.core.runtime.jobs.Job;
31
import org.eclipse.jface.action.Action;
32
import org.eclipse.jface.action.ActionContributionItem;
33
import org.eclipse.jface.viewers.ArrayContentProvider;
34
import org.eclipse.jface.viewers.IBaseLabelProvider;
35
import org.eclipse.jface.viewers.ISelectionChangedListener;
36
import org.eclipse.jface.viewers.IStructuredSelection;
37
import org.eclipse.jface.viewers.ITableLabelProvider;
38
import org.eclipse.jface.viewers.LabelProvider;
39
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
40
import org.eclipse.jface.viewers.SelectionChangedEvent;
41
import org.eclipse.jface.viewers.TableViewer;
42
import org.eclipse.jface.viewers.Viewer;
43
import org.eclipse.jface.viewers.ViewerComparator;
44
import org.eclipse.swt.SWT;
45
import org.eclipse.swt.custom.SashForm;
46
import org.eclipse.swt.events.SelectionAdapter;
47
import org.eclipse.swt.events.SelectionEvent;
48
import org.eclipse.swt.graphics.Image;
49
import org.eclipse.swt.layout.FillLayout;
50
import org.eclipse.swt.layout.GridData;
51
import org.eclipse.swt.widgets.Composite;
52
import org.eclipse.swt.widgets.Control;
53
import org.eclipse.swt.widgets.Label;
54
import org.eclipse.swt.widgets.Shell;
55
import org.eclipse.swt.widgets.Table;
56
import org.eclipse.swt.widgets.TableColumn;
57
import org.eclipse.ui.PlatformUI;
58
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
59
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
60
import org.eclipse.ui.internal.WorkbenchImages;
61
import org.eclipse.ui.internal.WorkbenchMessages;
62
import org.eclipse.ui.internal.WorkbenchPlugin;
63
import org.eclipse.ui.internal.util.BundleUtility;
64
import org.eclipse.ui.menus.AbstractContributionFactory;
65
import org.eclipse.ui.menus.IContributionRoot;
66
import org.eclipse.ui.progress.WorkbenchJob;
67
import org.eclipse.ui.services.IServiceLocator;
68
import org.osgi.framework.Bundle;
69
70
/**
71
 * Displays information about the product plugins.
72
 * 
73
 * PRIVATE this class is internal to the ide
74
 */
75
public class AboutPluginsPage extends TableListPage {
76
77
	public class BundleTableLabelProvider extends LabelProvider implements
78
			ITableLabelProvider {
79
80
		/**
81
		 * Queue containing bundle signing info to be resolved.
82
		 */
83
		private LinkedList resolveQueue = new LinkedList();
84
85
		/**
86
		 * Queue containing bundle data that's been resolve and needs updating.
87
		 */
88
		private List updateQueue = new ArrayList();
89
90
		/*
91
		 * this job will attempt to discover the signing state of a given bundle
92
		 * and then send it along to the update job
93
		 */
94
		private Job resolveJob = new Job(AboutPluginsPage.class.getName()) {
95
			{
96
				setSystem(true);
97
				setPriority(Job.SHORT);
98
			}
99
100
			protected IStatus run(IProgressMonitor monitor) {
101
				while (true) {
102
					// If the UI has not been created, nothing to do.
103
					if (vendorInfo == null)
104
						return Status.OK_STATUS;
105
					// If the UI has been disposed since we were asked to
106
					// render, nothing to do.
107
					Table table = vendorInfo.getTable();
108
					// the table has been disposed since we were asked to render
109
					if (table == null || table.isDisposed())
110
						return Status.OK_STATUS;
111
					AboutBundleData data = null;
112
					synchronized (resolveQueue) {
113
						if (resolveQueue.isEmpty())
114
							return Status.OK_STATUS;
115
						data = (AboutBundleData) resolveQueue.removeFirst();
116
					}
117
					try {
118
						// following is an expensive call
119
						data.isSigned();
120
121
						synchronized (updateQueue) {
122
							updateQueue.add(data);
123
						}
124
						// start the update job
125
						updateJob.schedule();
126
					} catch (IllegalStateException e) {
127
						// the bundle we're testing has been unloaded. Do
128
						// nothing.
129
					}
130
				}
131
			}
132
		};
133
134
		/*
135
		 * this job is responsible for feeding label change events into the
136
		 * viewer as they become available from the resolve job
137
		 */
138
		private Job updateJob = new WorkbenchJob(PlatformUI.getWorkbench()
139
				.getDisplay(), AboutPluginsPage.class.getName()) {
140
			{
141
				setSystem(true);
142
				setPriority(Job.DECORATE);
143
			}
144
145
			/*
146
			 * (non-Javadoc)
147
			 * 
148
			 * @see
149
			 * org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.
150
			 * runtime.IProgressMonitor)
151
			 */
152
			public IStatus runInUIThread(IProgressMonitor monitor) {
153
				while (true) {
154
					Shell dialogShell = getShell();
155
					// the shell has gone down since we were asked to render
156
					if (dialogShell == null || dialogShell.isDisposed())
157
						return Status.OK_STATUS;
158
					AboutBundleData[] data = null;
159
					synchronized (updateQueue) {
160
						if (updateQueue.isEmpty())
161
							return Status.OK_STATUS;
162
163
						data = (AboutBundleData[]) updateQueue
164
								.toArray(new AboutBundleData[updateQueue.size()]);
165
						updateQueue.clear();
166
167
					}
168
					fireLabelProviderChanged(new LabelProviderChangedEvent(
169
							BundleTableLabelProvider.this, data));
170
				}
171
			}
172
		};
173
174
		/*
175
		 * (non-Javadoc)
176
		 * 
177
		 * @see
178
		 * org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java
179
		 * .lang.Object, int)
180
		 */
181
		public Image getColumnImage(Object element, int columnIndex) {
182
			if (columnIndex == 0) {
183
				if (element instanceof AboutBundleData) {
184
					final AboutBundleData data = (AboutBundleData) element;
185
					if (data.isSignedDetermined()) {
186
						return WorkbenchImages
187
								.getImage(data.isSigned() ? IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_YES
188
										: IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_NO);
189
					}
190
191
					synchronized (resolveQueue) {
192
						resolveQueue.add(data);
193
					}
194
					resolveJob.schedule();
195
196
					return WorkbenchImages
197
							.getImage(IWorkbenchGraphicConstants.IMG_OBJ_SIGNED_UNKNOWN);
198
				}
199
			}
200
			return null;
201
		}
202
203
		/*
204
		 * (non-Javadoc)
205
		 * 
206
		 * @see
207
		 * org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.
208
		 * lang.Object, int)
209
		 */
210
		public String getColumnText(Object element, int columnIndex) {
211
			if (element instanceof AboutBundleData) {
212
				AboutBundleData data = (AboutBundleData) element;
213
				switch (columnIndex) {
214
				case 1:
215
					return data.getProviderName();
216
				case 2:
217
					return data.getName();
218
				case 3:
219
					return data.getVersion();
220
				case 4:
221
					return data.getId();
222
				}
223
			}
224
			return ""; //$NON-NLS-1$
225
		}
226
	}
227
228
	// This id should *not* be the same id used for contributing the page in
229
	// the installationPage extension. It is used by ProductInfoDialog
230
	// to ensure a different namespace for button contributions than the id
231
	// for the page appearing in the InstallationDialog
232
	private static final String ID = "productInfo.plugins"; //$NON-NLS-1$
233
234
	/**
235
	 * Table height in dialog units (value 200).
236
	 */
237
	private static final int TABLE_HEIGHT = 200;
238
239
	private static final IPath baseNLPath = new Path("$nl$"); //$NON-NLS-1$
240
241
	private static final String PLUGININFO = "about.html"; //$NON-NLS-1$
242
243
	private static final int PLUGIN_NAME_COLUMN_INDEX = 2;
244
245
	private static final int SIGNING_AREA_PERCENTAGE = 30;
246
247
	private TableViewer vendorInfo;
248
249
	private Action signingInfo;
250
251
	private String message;
252
253
	private String helpContextId = IWorkbenchHelpContextIds.ABOUT_PLUGINS_DIALOG;
254
255
	private String columnTitles[] = {
256
			WorkbenchMessages.AboutPluginsDialog_signed,
257
			WorkbenchMessages.AboutPluginsDialog_provider,
258
			WorkbenchMessages.AboutPluginsDialog_pluginName,
259
			WorkbenchMessages.AboutPluginsDialog_version,
260
			WorkbenchMessages.AboutPluginsDialog_pluginId,
261
262
	};
263
	private Bundle[] bundles = WorkbenchPlugin.getDefault().getBundles();
264
	private AboutBundleData[] bundleInfos;
265
	private SashForm sashForm;
266
	private BundleSigningInfo signingArea;
267
268
	public void setBundles(Bundle[] bundles) {
269
		this.bundles = bundles;
270
	}
271
272
	public void setHelpContextId(String id) {
273
		this.helpContextId = id;
274
	}
275
276
	public void setMessage(String message) {
277
		this.message = message;
278
	}
279
280
	/**
281
	 */
282
	protected void handleSigningInfoPressed() {
283
		if (signingArea == null) {
284
			signingArea = new BundleSigningInfo();
285
			AboutBundleData bundleInfo = (AboutBundleData) ((IStructuredSelection) vendorInfo
286
					.getSelection()).getFirstElement();
287
			signingArea.setData(bundleInfo);
288
289
			signingArea.createContents(sashForm);
290
			sashForm.setWeights(new int[] { 100 - SIGNING_AREA_PERCENTAGE,
291
					SIGNING_AREA_PERCENTAGE });
292
			signingInfo
293
					.setText(WorkbenchMessages.AboutPluginsDialog_signingInfo_hide);
294
295
		} else {
296
			// hide
297
			signingInfo
298
					.setText(WorkbenchMessages.AboutPluginsDialog_signingInfo_show);
299
			signingArea.dispose();
300
			signingArea = null;
301
			sashForm.setWeights(new int[] { 100 });
302
		}
303
	}
304
305
	protected AbstractContributionFactory makeContributionFactory() {
306
		return new AbstractContributionFactory(getInstallationDialog()
307
				.getButtonBarURI(), null) {
308
309
			public void createContributionItems(IServiceLocator serviceLocator,
310
					IContributionRoot additions) {
311
312
				signingInfo = new Action(
313
						WorkbenchMessages.AboutPluginsDialog_signingInfo_show) {
314
					public void run() {
315
						handleSigningInfoPressed();
316
					}
317
				};
318
				checkSigningEnablement();
319
				additions.addContributionItem(new ActionContributionItem(
320
						signingInfo), getInstallationDialog()
321
						.getActivePageExpression(AboutPluginsPage.this));
322
			}
323
		};
324
	}
325
326
	protected Control createPageControl(Composite parent) {
327
		initializeDialogUnits(parent);
328
329
		// create a data object for each bundle, remove duplicates, and include
330
		// only resolved bundles (bug 65548)
331
		Map map = new HashMap();
332
		for (int i = 0; i < bundles.length; ++i) {
333
			AboutBundleData data = new AboutBundleData(bundles[i]);
334
			if (BundleUtility.isReady(data.getState())
335
					&& !map.containsKey(data.getVersionedId())) {
336
				map.put(data.getVersionedId(), data);
337
			}
338
		}
339
		bundleInfos = (AboutBundleData[]) map.values().toArray(
340
				new AboutBundleData[0]);
341
		WorkbenchPlugin.class.getSigners();
342
343
		sashForm = new SashForm(parent, SWT.HORIZONTAL | SWT.SMOOTH);
344
		FillLayout layout = new FillLayout();
345
		sashForm.setLayout(layout);
346
		layout.marginHeight = 0;
347
		layout.marginWidth = 0;
348
		GridData data = new GridData(GridData.FILL_BOTH);
349
		sashForm.setLayoutData(data);
350
351
		Composite outer = createOuterComposite(sashForm);
352
		PlatformUI.getWorkbench().getHelpSystem().setHelp(outer, helpContextId);
353
354
		if (message != null) {
355
			Label label = new Label(outer, SWT.NONE);
356
			label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
357
			label.setFont(parent.getFont());
358
			label.setText(message);
359
		}
360
361
		createTable(outer);
362
		return outer;
363
	}
364
365
	/**
366
	 * Create the table part of the dialog.
367
	 * 
368
	 * @param parent
369
	 *            the parent composite to contain the dialog area
370
	 */
371
	protected void createTable(Composite parent) {
372
		vendorInfo = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL
373
				| SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
374
		vendorInfo.setUseHashlookup(true);
375
		vendorInfo.getTable().setHeaderVisible(true);
376
		vendorInfo.getTable().setLinesVisible(true);
377
		vendorInfo.getTable().setFont(parent.getFont());
378
		vendorInfo.addSelectionChangedListener(new ISelectionChangedListener() {
379
380
			public void selectionChanged(SelectionChangedEvent event) {
381
				checkSigningEnablement();
382
				AboutPluginsPage.this.selectionChanged();
383
			}
384
		});
385
386
		final TableComparator comparator = new TableComparator();
387
		vendorInfo.setComparator(comparator);
388
		int[] columnWidths = {
389
				convertHorizontalDLUsToPixels(30), // signature
390
				convertHorizontalDLUsToPixels(120),
391
				convertHorizontalDLUsToPixels(120),
392
				convertHorizontalDLUsToPixels(70),
393
				convertHorizontalDLUsToPixels(130), };
394
395
		// create table headers
396
		for (int i = 0; i < columnTitles.length; i++) {
397
			TableColumn column = new TableColumn(vendorInfo.getTable(),
398
					SWT.NULL);
399
			if (i == PLUGIN_NAME_COLUMN_INDEX) { // prime initial sorting
400
				updateTableSorting(i);
401
			}
402
			column.setWidth(columnWidths[i]);
403
			column.setText(columnTitles[i]);
404
			final int columnIndex = i;
405
			column.addSelectionListener(new SelectionAdapter() {
406
				public void widgetSelected(SelectionEvent e) {
407
					updateTableSorting(columnIndex);
408
				}
409
			});
410
		}
411
412
		vendorInfo.setContentProvider(new ArrayContentProvider());
413
		vendorInfo.setLabelProvider(new BundleTableLabelProvider());
414
415
		GridData gridData = new GridData(GridData.FILL, GridData.FILL, true,
416
				true);
417
		gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
418
		vendorInfo.getTable().setLayoutData(gridData);
419
420
		vendorInfo.setInput(bundleInfos);
421
	}
422
423
	/**
424
	 * Update the sort information on both the comparator and the table.
425
	 * 
426
	 * @param columnIndex
427
	 *            the index to sort by
428
	 * @since 3.4
429
	 */
430
	private void updateTableSorting(final int columnIndex) {
431
		TableComparator comparator = (TableComparator) vendorInfo
432
				.getComparator();
433
		// toggle direction if it's the same column
434
		if (columnIndex == comparator.getSortColumn()) {
435
			comparator.setAscending(!comparator.isAscending());
436
		}
437
		comparator.setSortColumn(columnIndex);
438
		vendorInfo.getTable().setSortColumn(
439
				vendorInfo.getTable().getColumn(columnIndex));
440
		vendorInfo.getTable().setSortDirection(
441
				comparator.isAscending() ? SWT.UP : SWT.DOWN);
442
		vendorInfo.refresh(false);
443
	}
444
445
	/**
446
	 * Return an url to the plugin's about.html file (what is shown when
447
	 * "More info" is pressed) or null if no such file exists. The method does
448
	 * nl lookup to allow for i18n.
449
	 * 
450
	 * @param bundleInfo
451
	 *            the bundle info
452
	 * @param makeLocal
453
	 *            whether to make the about content local
454
	 * @return the url or <code>null</code>
455
	 */
456
	private URL getMoreInfoURL(AboutBundleData bundleInfo, boolean makeLocal) {
457
		Bundle bundle = Platform.getBundle(bundleInfo.getId());
458
		if (bundle == null) {
459
			return null;
460
		}
461
462
		URL aboutUrl = Platform.find(bundle, baseNLPath.append(PLUGININFO),
463
				null);
464
		if (!makeLocal) {
465
			return aboutUrl;
466
		}
467
		if (aboutUrl != null) {
468
			try {
469
				URL result = Platform.asLocalURL(aboutUrl);
470
				try {
471
					// Make local all content in the "about" directory.
472
					// This is needed to handle jar'ed plug-ins.
473
					// See Bug 88240 [About] About dialog needs to extract
474
					// subdirs.
475
					URL about = new URL(aboutUrl, "about_files"); //$NON-NLS-1$
476
					if (about != null) {
477
						Platform.asLocalURL(about);
478
					}
479
				} catch (IOException e) {
480
					// skip the about dir if its not found or there are other
481
					// problems.
482
				}
483
				return result;
484
			} catch (IOException e) {
485
				// do nothing
486
			}
487
		}
488
		return null;
489
	}
490
491
	/*
492
	 * (non-Javadoc)
493
	 * 
494
	 * @see org.eclipse.ui.internal.about.ProductInfoPage#getId()
495
	 */
496
	String getId() {
497
		return ID;
498
	}
499
500
	/*
501
	 * (non-Javadoc)
502
	 * 
503
	 * @see org.eclipse.ui.internal.about.ColumnsPage#getTable()
504
	 */
505
	protected Table getTable() {
506
		return vendorInfo.getTable();
507
	}
508
509
	/*
510
	 * (non-Javadoc)
511
	 * 
512
	 * @see org.eclipse.ui.internal.about.TableListPage#getURL()
513
	 */
514
	protected URL getURL() {
515
		if (vendorInfo == null)
516
			return null;
517
518
		if (vendorInfo.getSelection().isEmpty())
519
			return null;
520
521
		AboutBundleData bundleInfo = (AboutBundleData) ((IStructuredSelection) vendorInfo
522
				.getSelection()).getFirstElement();
523
		URL url = getMoreInfoURL(bundleInfo, true);
524
525
		// only report problems if the -debug command line argument is used
526
		if (url == null && WorkbenchPlugin.DEBUG) {
527
			WorkbenchPlugin.log("Problem reading plugin info for: " //$NON-NLS-1$
528
					+ bundleInfo.getName());
529
		}
530
		return url;
531
	}
532
533
	private void checkSigningEnablement() {
534
		// enable if there is an item selected and that
535
		// item has additional info
536
		IStructuredSelection selection = (IStructuredSelection) vendorInfo
537
				.getSelection();
538
		if (selection.getFirstElement() instanceof AboutBundleData) {
539
			AboutBundleData selected = (AboutBundleData) selection
540
					.getFirstElement();
541
			signingInfo.setEnabled(true);
542
			if (signingArea != null) {
543
				signingArea.setData(selected);
544
			}
545
		} else {
546
			signingInfo.setEnabled(false);
547
		}
548
	}
549
550
	/*
551
	 * (non-Javadoc)
552
	 * 
553
	 * @see org.eclipse.ui.internal.about.TableListPage#getSelectionValue()
554
	 */
555
	protected Collection getSelectionValue() {
556
		if (vendorInfo == null)
557
			return null;
558
		IStructuredSelection selection = (IStructuredSelection) vendorInfo
559
				.getSelection();
560
		if (selection.getFirstElement() instanceof AboutBundleData) {
561
			ArrayList list = new ArrayList(1);
562
			list.add(selection.getFirstElement());
563
			return list;
564
		}
565
		return null;
566
	}
567
}
568
569
class TableComparator extends ViewerComparator {
570
571
	private int sortColumn = 0;
572
	private boolean ascending = true;
573
574
	/*
575
	 * (non-Javadoc)
576
	 * 
577
	 * @see
578
	 * org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.
579
	 * viewers.Viewer, java.lang.Object, java.lang.Object)
580
	 */
581
	public int compare(Viewer viewer, Object e1, Object e2) {
582
		if (sortColumn == 0 && e1 instanceof AboutBundleData
583
				&& e2 instanceof AboutBundleData) {
584
			AboutBundleData d1 = (AboutBundleData) e1;
585
			AboutBundleData d2 = (AboutBundleData) e2;
586
			int diff = getSignedSortValue(d1) - getSignedSortValue(d2);
587
			return ascending ? diff : -diff;
588
		}
589
		if (viewer instanceof TableViewer) {
590
			TableViewer tableViewer = (TableViewer) viewer;
591
			IBaseLabelProvider baseLabel = tableViewer.getLabelProvider();
592
			if (baseLabel instanceof ITableLabelProvider) {
593
				ITableLabelProvider tableProvider = (ITableLabelProvider) baseLabel;
594
				String e1p = tableProvider.getColumnText(e1, sortColumn);
595
				String e2p = tableProvider.getColumnText(e2, sortColumn);
596
				int result = getComparator().compare(e1p, e2p);
597
				return ascending ? result : (-1) * result;
598
			}
599
		}
600
601
		return super.compare(viewer, e1, e2);
602
	}
603
604
	/**
605
	 * @param data
606
	 * @return a sort value depending on the signed state
607
	 */
608
	private int getSignedSortValue(AboutBundleData data) {
609
		if (!data.isSignedDetermined()) {
610
			return 0;
611
		} else if (data.isSigned()) {
612
			return 1;
613
		} else {
614
			return -1;
615
		}
616
	}
617
618
	/**
619
	 * @return Returns the sortColumn.
620
	 */
621
	public int getSortColumn() {
622
		return sortColumn;
623
	}
624
625
	/**
626
	 * @param sortColumn
627
	 *            The sortColumn to set.
628
	 */
629
	public void setSortColumn(int sortColumn) {
630
		this.sortColumn = sortColumn;
631
	}
632
633
	/**
634
	 * @return Returns the ascending.
635
	 */
636
	public boolean isAscending() {
637
		return ascending;
638
	}
639
640
	/**
641
	 * @param ascending
642
	 *            The ascending to set.
643
	 */
644
	public void setAscending(boolean ascending) {
645
		this.ascending = ascending;
646
	}
647
}
(-)Eclipse (+25 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import org.eclipse.core.commands.ExecutionEvent;
15
import org.eclipse.ui.about.InstallationPage;
16
17
public class CopyHandler extends ProductInfoPageHandler {
18
19
	protected Object execute(InstallationPage page, ExecutionEvent event) {
20
		if (page instanceof ProductInfoPage) {
21
			((ProductInfoPage)page).copyToClipboard();
22
		}
23
		return null;
24
	}
25
}
(-)Eclipse (+128 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2009 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.about;
12
13
import org.eclipse.core.commands.AbstractHandler;
14
import org.eclipse.core.commands.ExecutionEvent;
15
import org.eclipse.core.commands.ExecutionException;
16
import org.eclipse.jface.resource.JFaceResources;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.dnd.Clipboard;
19
import org.eclipse.swt.dnd.TextTransfer;
20
import org.eclipse.swt.dnd.Transfer;
21
import org.eclipse.swt.layout.GridData;
22
import org.eclipse.swt.widgets.Composite;
23
import org.eclipse.swt.widgets.Control;
24
import org.eclipse.swt.widgets.Text;
25
import org.eclipse.ui.PlatformUI;
26
import org.eclipse.ui.internal.ConfigurationInfo;
27
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
28
29
/**
30
 * Displays system information about the eclipse application. The content of
31
 * what is displayed is selectable through the
32
 * <code>org.eclipse.ui.systemSummaryExtensions</code> extension point.
33
 */
34
public final class AboutSystemPage extends ProductInfoPage {
35
36
	class CopyHandler extends AbstractHandler {
37
		/*
38
		 * (non-Javadoc)
39
		 * 
40
		 * @see
41
		 * org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands
42
		 * .ExecutionEvent)
43
		 */
44
		public Object execute(ExecutionEvent event) throws ExecutionException {
45
			if (text == null) {
46
				return null;
47
			}
48
49
			Clipboard clipboard = null;
50
			try {
51
				clipboard = new Clipboard(getShell().getDisplay());
52
				String contents = text.getSelectionText();
53
				if (contents.length() == 0)
54
					contents = text.getText();
55
				clipboard.setContents(new Object[] { contents },
56
						new Transfer[] { TextTransfer.getInstance() });
57
			} finally {
58
				if (clipboard != null) {
59
					clipboard.dispose();
60
				}
61
			}
62
			return null;
63
		}
64
65
		public boolean isEnabled() {
66
			return true;
67
		}
68
	}
69
70
	// This id should *not* be the same id used for contributing the page in
71
	// the installationPage extension. It is used by ProductInfoDialog
72
	// to ensure a different namespace for button contributions than the id
73
	// for the page appearing in the InstallationDialog
74
	private static final String ID = "productInfo.system"; //$NON-NLS-1$
75
76
	private Text text;
77
78
	protected Control createPageControl(Composite parent) {
79
		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
80
				IWorkbenchHelpContextIds.SYSTEM_SUMMARY_DIALOG);
81
82
		Composite outer = createOuterComposite(parent);
83
84
		text = new Text(outer, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY
85
				| SWT.V_SCROLL | SWT.NO_FOCUS | SWT.H_SCROLL);
86
		text.setBackground(parent.getDisplay().getSystemColor(
87
				SWT.COLOR_LIST_BACKGROUND));
88
		GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL
89
				| GridData.VERTICAL_ALIGN_FILL);
90
		gridData.grabExcessVerticalSpace = true;
91
		gridData.grabExcessHorizontalSpace = true;
92
		gridData.heightHint = convertVerticalDLUsToPixels(300);
93
		gridData.widthHint = convertHorizontalDLUsToPixels(400);
94
		text.setLayoutData(gridData);
95
		text.setText(ConfigurationInfo.getSystemSummary());
96
		text.setFont(JFaceResources.getTextFont());
97
		return outer;
98
	}
99
100
	/*
101
	 * (non-Javadoc)
102
	 * 
103
	 * @see org.eclipse.ui.internal.about.ProductInfoPage#getId()
104
	 */
105
	String getId() {
106
		return ID;
107
	}
108
109
	public void copyToClipboard() {
110
		if (text == null) {
111
			return;
112
		}
113
114
		Clipboard clipboard = null;
115
		try {
116
			clipboard = new Clipboard(text.getShell().getDisplay());
117
			String contents = text.getSelectionText();
118
			if (contents.length() == 0)
119
				contents = text.getText();
120
			clipboard.setContents(new Object[] { contents },
121
					new Transfer[] { TextTransfer.getInstance() });
122
		} finally {
123
			if (clipboard != null) {
124
				clipboard.dispose();
125
			}
126
		}
127
	}
128
}
(-)Eclipse (+24 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import org.eclipse.core.commands.ExecutionEvent;
15
import org.eclipse.ui.about.InstallationPage;
16
17
public class ConfigureColumnsHandler extends ProductInfoPageHandler {
18
19
	protected Object execute(InstallationPage page, ExecutionEvent event) {
20
		if (page instanceof TableListPage)
21
			((TableListPage)page).handleColumnsPressed();
22
		return null;
23
	}
24
}
(-)Eclipse (+26 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.about;
13
14
/**
15
 * <em>This API is experimental and will change before 3.5 ships</em>
16
 * 
17
 * @since 3.5
18
 */
19
public interface IInstallationPageSources {
20
21
	public static final String ACTIVE_PAGE = "org.eclipse.ui.installationPage.activePage"; //$NON-NLS-1$
22
	public static final String ACTIVE_PAGE_ID = "org.eclipse.ui.installationPage.activePage.id"; //$NON-NLS-1$
23
	public static final String ACTIVE_PAGE_SELECTION = "org.eclipse.ui.installationPage.activePage.selection"; //$NON-NLS-1$
24
25
	
26
}
(-)Eclipse (+39 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import java.net.URL;
15
16
import org.eclipse.core.commands.ExecutionEvent;
17
import org.eclipse.jface.dialogs.MessageDialog;
18
import org.eclipse.swt.widgets.Shell;
19
import org.eclipse.ui.about.InstallationPage;
20
import org.eclipse.ui.handlers.HandlerUtil;
21
import org.eclipse.ui.internal.WorkbenchMessages;
22
23
public class OpenBrowserHandler extends ProductInfoPageHandler {
24
25
	protected Object execute(InstallationPage page, ExecutionEvent event) {
26
		Shell shell = HandlerUtil.getActiveShell(event);
27
		if (page instanceof TableListPage) {
28
			TableListPage p = (TableListPage) page;
29
			URL url = p.getURL();
30
			if (url != null && AboutUtils.openBrowser(shell, url))
31
				return null;
32
		}
33
		// nothing to show, but the user is expecting feedback.
34
		MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
35
				WorkbenchMessages.OpenBrowserHandler_NoInfoDialogTitle,
36
				WorkbenchMessages.OpenBrowserHandler_NoInfoDialogMessage);
37
		return null;
38
	}
39
}
(-)Eclipse (+270 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 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.about;
12
13
import java.io.File;
14
import java.io.FileNotFoundException;
15
import java.io.FileReader;
16
import java.io.FileWriter;
17
import java.io.IOException;
18
import java.net.MalformedURLException;
19
import java.net.URL;
20
import java.util.ArrayList;
21
import java.util.StringTokenizer;
22
23
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.IStatus;
25
import org.eclipse.core.runtime.Platform;
26
import org.eclipse.jface.dialogs.MessageDialog;
27
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.swt.widgets.Shell;
29
import org.eclipse.ui.PartInitException;
30
import org.eclipse.ui.PlatformUI;
31
import org.eclipse.ui.browser.IWebBrowser;
32
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
33
import org.eclipse.ui.internal.WorkbenchMessages;
34
import org.eclipse.ui.internal.WorkbenchPlugin;
35
import org.eclipse.ui.internal.misc.StatusUtil;
36
import org.eclipse.ui.statushandlers.StatusManager;
37
38
/**
39
 * Manages links in styled text.
40
 */
41
42
public class AboutUtils {
43
44
	private final static String ERROR_LOG_COPY_FILENAME = "log"; //$NON-NLS-1$
45
46
	/**
47
	 * Scan the contents of the about text
48
	 * 
49
	 * @param s
50
	 * @return
51
	 */
52
	public static AboutItem scan(String s) {
53
		ArrayList linkRanges = new ArrayList();
54
		ArrayList links = new ArrayList();
55
56
		// slightly modified version of jface url detection
57
		// see org.eclipse.jface.text.hyperlink.URLHyperlinkDetector
58
59
		int urlSeparatorOffset = s.indexOf("://"); //$NON-NLS-1$
60
		while (urlSeparatorOffset >= 0) {
61
62
			boolean startDoubleQuote = false;
63
64
			// URL protocol (left to "://")
65
			int urlOffset = urlSeparatorOffset;
66
			char ch;
67
			do {
68
				urlOffset--;
69
				ch = ' ';
70
				if (urlOffset > -1)
71
					ch = s.charAt(urlOffset);
72
				startDoubleQuote = ch == '"';
73
			} while (Character.isUnicodeIdentifierStart(ch));
74
			urlOffset++;
75
76
			// Right to "://"
77
			StringTokenizer tokenizer = new StringTokenizer(s
78
					.substring(urlSeparatorOffset + 3), " \t\n\r\f<>", false); //$NON-NLS-1$
79
			if (!tokenizer.hasMoreTokens())
80
				return null;
81
82
			int urlLength = tokenizer.nextToken().length() + 3
83
					+ urlSeparatorOffset - urlOffset;
84
85
			if (startDoubleQuote) {
86
				int endOffset = -1;
87
				int nextDoubleQuote = s.indexOf('"', urlOffset);
88
				int nextWhitespace = s.indexOf(' ', urlOffset);
89
				if (nextDoubleQuote != -1 && nextWhitespace != -1)
90
					endOffset = Math.min(nextDoubleQuote, nextWhitespace);
91
				else if (nextDoubleQuote != -1)
92
					endOffset = nextDoubleQuote;
93
				else if (nextWhitespace != -1)
94
					endOffset = nextWhitespace;
95
				if (endOffset != -1)
96
					urlLength = endOffset - urlOffset;
97
			}
98
99
			linkRanges.add(new int[] { urlOffset, urlLength });
100
			links.add(s.substring(urlOffset, urlOffset + urlLength));
101
102
			urlSeparatorOffset = s.indexOf("://", urlOffset + urlLength + 1); //$NON-NLS-1$
103
		}
104
		return new AboutItem(s, (int[][]) linkRanges.toArray(new int[linkRanges
105
				.size()][2]), (String[]) links
106
				.toArray(new String[links.size()]));
107
	}
108
109
	/**
110
	 * Open a browser with the argument title on the argument url. If the url
111
	 * refers to a resource within a bundle, then a temp copy of the file will
112
	 * be extracted and opened.
113
	 * 
114
	 * @see <code>Platform.asLocalUrl</code>
115
	 * @param url
116
	 *            The target url to be displayed, null will be safely ignored
117
	 * @return true if the url was successfully displayed and false otherwise
118
	 */
119
	public static boolean openBrowser(Shell shell, URL url) {
120
		if (url != null) {
121
			try {
122
				url = Platform.asLocalURL(url);
123
			} catch (IOException e) {
124
				return false;
125
			}
126
		}
127
		if (url == null) {
128
			return false;
129
		}
130
		openLink(shell, url.toString());
131
		return true;
132
	}
133
134
	/**
135
	 * Open a link
136
	 */
137
	public static void openLink(Shell shell, String href) {
138
		// format the href for an html file (file:///<filename.html>
139
		// required for Mac only.
140
		if (href.startsWith("file:")) { //$NON-NLS-1$
141
			href = href.substring(5);
142
			while (href.startsWith("/")) { //$NON-NLS-1$
143
				href = href.substring(1);
144
			}
145
			href = "file:///" + href; //$NON-NLS-1$
146
		}
147
		IWorkbenchBrowserSupport support = PlatformUI.getWorkbench()
148
				.getBrowserSupport();
149
		try {
150
			IWebBrowser browser = support.getExternalBrowser();
151
			browser.openURL(new URL(urlEncodeForSpaces(href.toCharArray())));
152
		} catch (MalformedURLException e) {
153
			openWebBrowserError(shell, href, e);
154
		} catch (PartInitException e) {
155
			openWebBrowserError(shell, href, e);
156
		}
157
	}
158
159
	/**
160
	 * This method encodes the url, removes the spaces from the url and replaces
161
	 * the same with <code>"%20"</code>. This method is required to fix Bug
162
	 * 77840.
163
	 * 
164
	 * @since 3.0.2
165
	 */
166
	private static String urlEncodeForSpaces(char[] input) {
167
		StringBuffer retu = new StringBuffer(input.length);
168
		for (int i = 0; i < input.length; i++) {
169
			if (input[i] == ' ') {
170
				retu.append("%20"); //$NON-NLS-1$
171
			} else {
172
				retu.append(input[i]);
173
			}
174
		}
175
		return retu.toString();
176
	}
177
178
	/**
179
	 * display an error message
180
	 */
181
	private static void openWebBrowserError(Shell shell, final String href,
182
			final Throwable t) {
183
		String title = WorkbenchMessages.ProductInfoDialog_errorTitle;
184
		String msg = NLS.bind(
185
				WorkbenchMessages.ProductInfoDialog_unableToOpenWebBrowser,
186
				href);
187
		IStatus status = WorkbenchPlugin.getStatus(t);
188
		StatusUtil.handleStatus(status, title + ": " + msg, StatusManager.SHOW, //$NON-NLS-1$
189
				shell);
190
	}
191
192
	public static void openErrorLogBrowser(Shell shell) {
193
		String filename = Platform.getLogFileLocation().toOSString();
194
195
		File log = new File(filename);
196
		if (log.exists()) {
197
			// Make a copy of the file with a temporary name.
198
			// Working around an issue with windows file associations/browser
199
			// malfunction whereby the browser doesn't open on ".log" and we
200
			// aren't returned an error.
201
			// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=97783
202
			File logCopy = makeDisplayCopy(log);
203
			if (logCopy != null) {
204
				AboutUtils.openLink(shell,
205
						"file:///" + logCopy.getAbsolutePath()); //$NON-NLS-1$
206
				return;
207
			}
208
			// Couldn't make copy, try to open the original log.
209
			// We try the original in this case rather than putting up an error,
210
			// because the copy could fail due to an I/O or out of space
211
			// problem.
212
			// In that case we may still be able to show the original log,
213
			// depending on the platform. The risk is that users with
214
			// configurations that have bug #97783 will still get nothing
215
			// (vs. an error) but we'd rather
216
			// try again than put up an error dialog on platforms where the
217
			// ability to view the original log works just fine.
218
			AboutUtils.openLink(shell, "file:///" + filename); //$NON-NLS-1$
219
			return;
220
		}
221
		MessageDialog.openInformation(shell,
222
				WorkbenchMessages.AboutSystemDialog_noLogTitle, NLS.bind(
223
						WorkbenchMessages.AboutSystemDialog_noLogMessage,
224
						filename));
225
	}
226
227
	/**
228
	 * Returns a copy of the given file to be used for display in a browser.
229
	 * 
230
	 * @return the file, or <code>null</code>
231
	 */
232
	private static File makeDisplayCopy(File file) {
233
		IPath path = WorkbenchPlugin.getDefault().getDataLocation();
234
		if (path == null) {
235
			return null;
236
		}
237
		path = path.append(ERROR_LOG_COPY_FILENAME);
238
		File copy = path.toFile();
239
		FileReader in = null;
240
		FileWriter out = null;
241
		try {
242
			in = new FileReader(file);
243
			// don't append data, overwrite what was there
244
			out = new FileWriter(copy);
245
			char buffer[] = new char[4096];
246
			int count;
247
			while ((count = in.read(buffer, 0, buffer.length)) > 0) {
248
				out.write(buffer, 0, count);
249
			}
250
		} catch (FileNotFoundException e) {
251
			return null;
252
		} catch (IOException e) {
253
			return null;
254
		} finally {
255
			try {
256
				if (in != null) {
257
					in.close();
258
				}
259
				if (out != null) {
260
					out.close();
261
				}
262
			} catch (IOException e) {
263
				return null;
264
			}
265
		}
266
		return copy;
267
268
	}
269
270
}
(-)Eclipse (+350 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 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.about;
12
13
import java.util.ArrayList;
14
import java.util.StringTokenizer;
15
16
import org.eclipse.jface.resource.JFaceColors;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.custom.StyleRange;
19
import org.eclipse.swt.custom.StyledText;
20
import org.eclipse.swt.events.DisposeEvent;
21
import org.eclipse.swt.events.DisposeListener;
22
import org.eclipse.swt.events.KeyAdapter;
23
import org.eclipse.swt.events.KeyEvent;
24
import org.eclipse.swt.events.MouseAdapter;
25
import org.eclipse.swt.events.MouseEvent;
26
import org.eclipse.swt.events.MouseMoveListener;
27
import org.eclipse.swt.events.TraverseEvent;
28
import org.eclipse.swt.events.TraverseListener;
29
import org.eclipse.swt.graphics.Color;
30
import org.eclipse.swt.graphics.Cursor;
31
import org.eclipse.swt.graphics.Point;
32
33
/**
34
 * Manages links in styled text.
35
 */
36
37
public class AboutTextManager {
38
39
    /**
40
     * Scan the contents of the about text
41
     * @param s 
42
     * @return 
43
     */
44
    public static AboutItem scan(String s) {
45
        ArrayList linkRanges = new ArrayList();
46
        ArrayList links = new ArrayList();
47
        
48
        // slightly modified version of jface url detection
49
        // see org.eclipse.jface.text.hyperlink.URLHyperlinkDetector
50
        
51
		int urlSeparatorOffset= s.indexOf("://"); //$NON-NLS-1$
52
		while(urlSeparatorOffset >= 0) {
53
	
54
			boolean startDoubleQuote= false;
55
	
56
			// URL protocol (left to "://")
57
			int urlOffset= urlSeparatorOffset;
58
			char ch;
59
			do {
60
				urlOffset--;
61
				ch= ' ';
62
				if (urlOffset > -1)
63
					ch= s.charAt(urlOffset);
64
				startDoubleQuote= ch == '"';
65
			} while (Character.isUnicodeIdentifierStart(ch));
66
			urlOffset++;
67
			
68
	
69
			// Right to "://"
70
			StringTokenizer tokenizer= new StringTokenizer(s.substring(urlSeparatorOffset + 3), " \t\n\r\f<>", false); //$NON-NLS-1$
71
			if (!tokenizer.hasMoreTokens())
72
				return null;
73
	
74
			int urlLength= tokenizer.nextToken().length() + 3 + urlSeparatorOffset - urlOffset;
75
	
76
			if (startDoubleQuote) {
77
				int endOffset= -1;
78
				int nextDoubleQuote= s.indexOf('"', urlOffset);
79
				int nextWhitespace= s.indexOf(' ', urlOffset);
80
				if (nextDoubleQuote != -1 && nextWhitespace != -1)
81
					endOffset= Math.min(nextDoubleQuote, nextWhitespace);
82
				else if (nextDoubleQuote != -1)
83
					endOffset= nextDoubleQuote;
84
				else if (nextWhitespace != -1)
85
					endOffset= nextWhitespace;
86
				if (endOffset != -1)
87
					urlLength= endOffset - urlOffset;
88
			}
89
			
90
			linkRanges.add(new int[] { urlOffset, urlLength });
91
			links.add(s.substring(urlOffset, urlOffset+urlLength));
92
			
93
			urlSeparatorOffset= s.indexOf("://", urlOffset+urlLength+1); //$NON-NLS-1$
94
		}
95
        return new AboutItem(s, (int[][]) linkRanges.toArray(new int[linkRanges
96
                .size()][2]), (String[]) links
97
                .toArray(new String[links.size()]));
98
    }
99
	private StyledText styledText;
100
	
101
    private Cursor handCursor;
102
103
    private Cursor busyCursor;
104
105
    private boolean mouseDown = false;
106
107
    private boolean dragEvent = false;
108
    
109
    private AboutItem item;
110
    
111
    public AboutTextManager(StyledText text) {
112
    	this.styledText = text;
113
    	createCursors();
114
    	addListeners();
115
    }
116
    
117
    private void createCursors() {
118
        handCursor = new Cursor(styledText.getDisplay(), SWT.CURSOR_HAND);
119
        busyCursor = new Cursor(styledText.getDisplay(), SWT.CURSOR_WAIT);
120
        styledText.addDisposeListener(new DisposeListener() {
121
            public void widgetDisposed(DisposeEvent e) {
122
                handCursor.dispose();
123
                handCursor = null;
124
                busyCursor.dispose();
125
                busyCursor = null;
126
            }
127
        });
128
    }
129
130
	
131
    /**
132
     * Adds listeners to the given styled text
133
     */
134
    protected void addListeners() {
135
        styledText.addMouseListener(new MouseAdapter() {
136
            public void mouseDown(MouseEvent e) {
137
                if (e.button != 1) {
138
                    return;
139
                }
140
                mouseDown = true;
141
            }
142
143
            public void mouseUp(MouseEvent e) {
144
                mouseDown = false;
145
                int offset = styledText.getCaretOffset();
146
                if (dragEvent) {
147
                    // don't activate a link during a drag/mouse up operation
148
                    dragEvent = false;
149
                    if (item != null && item.isLinkAt(offset)) {
150
                    	styledText.setCursor(handCursor);
151
                    }
152
                } else if (item != null && item.isLinkAt(offset)) {
153
                	styledText.setCursor(busyCursor);
154
                    AboutUtils.openLink(styledText.getShell(), item.getLinkAt(offset));
155
                    StyleRange selectionRange = getCurrentRange();
156
                    styledText.setSelectionRange(selectionRange.start,
157
                            selectionRange.length);
158
                    styledText.setCursor(null);
159
                }
160
            }
161
        });
162
163
        styledText.addMouseMoveListener(new MouseMoveListener() {
164
            public void mouseMove(MouseEvent e) {
165
                // Do not change cursor on drag events
166
                if (mouseDown) {
167
                    if (!dragEvent) {
168
                        StyledText text = (StyledText) e.widget;
169
                        text.setCursor(null);
170
                    }
171
                    dragEvent = true;
172
                    return;
173
                }
174
                StyledText text = (StyledText) e.widget;
175
                int offset = -1;
176
                try {
177
                    offset = text.getOffsetAtLocation(new Point(e.x, e.y));
178
                } catch (IllegalArgumentException ex) {
179
                    // leave value as -1
180
                }
181
                if (offset == -1) {
182
					text.setCursor(null);
183
				} else if (item != null && item.isLinkAt(offset)) {
184
					text.setCursor(handCursor);
185
				} else {
186
					text.setCursor(null);
187
				}
188
            }
189
        });
190
191
        styledText.addTraverseListener(new TraverseListener() {
192
            public void keyTraversed(TraverseEvent e) {
193
                switch (e.detail) {
194
                case SWT.TRAVERSE_ESCAPE:
195
                    e.doit = true;
196
                    break;
197
                case SWT.TRAVERSE_TAB_NEXT:
198
                    //Previously traverse out in the backward direction?
199
                    Point nextSelection = styledText.getSelection();
200
                    int charCount = styledText.getCharCount();
201
                    if ((nextSelection.x == charCount)
202
                            && (nextSelection.y == charCount)) {
203
                    	styledText.setSelection(0);
204
                    }
205
                    StyleRange nextRange = findNextRange();
206
                    if (nextRange == null) {
207
                        // Next time in start at beginning, also used by 
208
                        // TRAVERSE_TAB_PREVIOUS to indicate we traversed out
209
                        // in the forward direction
210
                    	styledText.setSelection(0);
211
                        e.doit = true;
212
                    } else {
213
                    	styledText.setSelectionRange(nextRange.start,
214
                                nextRange.length);
215
                        e.doit = true;
216
                        e.detail = SWT.TRAVERSE_NONE;
217
                    }
218
                    break;
219
                case SWT.TRAVERSE_TAB_PREVIOUS:
220
                    //Previously traverse out in the forward direction?
221
                    Point previousSelection = styledText.getSelection();
222
                    if ((previousSelection.x == 0)
223
                            && (previousSelection.y == 0)) {
224
                    	styledText.setSelection(styledText.getCharCount());
225
					}
226
                    StyleRange previousRange = findPreviousRange();
227
                    if (previousRange == null) {
228
                        // Next time in start at the end, also used by 
229
                        // TRAVERSE_TAB_NEXT to indicate we traversed out
230
                        // in the backward direction
231
                    	styledText.setSelection(styledText.getCharCount());
232
                        e.doit = true;
233
                    } else {
234
                    	styledText.setSelectionRange(previousRange.start,
235
                                previousRange.length);
236
                        e.doit = true;
237
                        e.detail = SWT.TRAVERSE_NONE;
238
                    }
239
                    break;
240
                default:
241
                    break;
242
                }
243
            }
244
        });
245
246
        //Listen for Tab and Space to allow keyboard navigation
247
        styledText.addKeyListener(new KeyAdapter() {
248
            public void keyPressed(KeyEvent event) {
249
                StyledText text = (StyledText) event.widget;
250
                if (event.character == ' ' || event.character == SWT.CR) {
251
                    if (item != null) {
252
                        //Be sure we are in the selection
253
                        int offset = text.getSelection().x + 1;
254
255
                        if (item.isLinkAt(offset)) {
256
                            text.setCursor(busyCursor);
257
                            AboutUtils.openLink(styledText.getShell(), item.getLinkAt(offset));
258
                            StyleRange selectionRange = getCurrentRange();
259
                            text.setSelectionRange(selectionRange.start,
260
                                    selectionRange.length);
261
                            text.setCursor(null);
262
                        }
263
                    }
264
                    return;
265
                }
266
            }
267
        });
268
    }
269
270
    /**
271
     * Gets the about item.
272
     * @return the about item
273
     */
274
    public AboutItem getItem() {
275
        return item;
276
    }
277
278
    /**
279
     * Sets the about item.
280
     * @param item about item
281
     */
282
    public void setItem(AboutItem item) {
283
        this.item = item;
284
        if (item != null) {
285
        	styledText.setText(item.getText());
286
        	setLinkRanges(item.getLinkRanges()); 
287
        }
288
    }
289
290
    /**
291
     * Find the range of the current selection.
292
     */
293
    private StyleRange getCurrentRange() {
294
        StyleRange[] ranges = styledText.getStyleRanges();
295
        int currentSelectionEnd = styledText.getSelection().y;
296
        int currentSelectionStart = styledText.getSelection().x;
297
298
        for (int i = 0; i < ranges.length; i++) {
299
            if ((currentSelectionStart >= ranges[i].start)
300
                    && (currentSelectionEnd <= (ranges[i].start + ranges[i].length))) {
301
                return ranges[i];
302
            }
303
        }
304
        return null;
305
    }
306
307
    /**
308
     * Find the next range after the current 
309
     * selection.
310
     */
311
    private StyleRange findNextRange() {
312
        StyleRange[] ranges = styledText.getStyleRanges();
313
        int currentSelectionEnd = styledText.getSelection().y;
314
315
        for (int i = 0; i < ranges.length; i++) {
316
            if (ranges[i].start >= currentSelectionEnd) {
317
				return ranges[i];
318
			}
319
        }
320
        return null;
321
    }
322
323
    /**
324
     * Find the previous range before the current selection.
325
     */
326
    private StyleRange findPreviousRange() {
327
        StyleRange[] ranges = styledText.getStyleRanges();
328
        int currentSelectionStart = styledText.getSelection().x;
329
330
        for (int i = ranges.length - 1; i > -1; i--) {
331
            if ((ranges[i].start + ranges[i].length - 1) < currentSelectionStart) {
332
				return ranges[i];
333
			}
334
        }
335
        return null;
336
    }
337
338
    /**
339
     * Sets the styled text's link (blue) ranges
340
     */
341
    private void setLinkRanges(int[][] linkRanges) {
342
        Color fg = JFaceColors.getHyperlinkText(styledText.getShell()
343
                .getDisplay());
344
        for (int i = 0; i < linkRanges.length; i++) {
345
            StyleRange r = new StyleRange(linkRanges[i][0], linkRanges[i][1],
346
                    fg, null);
347
            styledText.setStyleRange(r);
348
        }
349
    }
350
}
(-)Eclipse (+67 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 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
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
11
 *      font should be activated and used by other components.
12
 *******************************************************************************/
13
package org.eclipse.ui.internal.about;
14
15
import java.net.URL;
16
import java.util.Collection;
17
18
import org.eclipse.core.expressions.IEvaluationContext;
19
import org.eclipse.jface.internal.ConfigureColumnsDialog;
20
import org.eclipse.swt.widgets.Table;
21
import org.eclipse.ui.about.IInstallationPageSources;
22
import org.eclipse.ui.services.IServiceLocator;
23
import org.eclipse.ui.services.ISourceProviderService;
24
25
/**
26
 * Displays information about the product plugins.
27
 * 
28
 * PRIVATE This class is internal to the workbench and must not be called
29
 * outside the workbench.
30
 */
31
abstract class TableListPage extends ProductInfoPage {
32
33
	InstallationDialogSourceProvider sourceProvider;
34
35
	public void init(IServiceLocator locator) {
36
		super.init(locator);
37
		// cache the source provider and prime the selection variable
38
		ISourceProviderService sps = (ISourceProviderService) locator
39
				.getService(ISourceProviderService.class);
40
		sourceProvider = (InstallationDialogSourceProvider) sps
41
				.getSourceProvider(IInstallationPageSources.ACTIVE_PAGE_SELECTION);
42
		selectionChanged();
43
	}
44
45
	public void handleColumnsPressed() {
46
		ConfigureColumnsDialog d = new ConfigureColumnsDialog(this, getTable());
47
		d.open();
48
	}
49
50
	protected abstract URL getURL();
51
52
	protected abstract Table getTable();
53
54
	protected void selectionChanged() {
55
		Object selection = getSelectionValue();
56
		if (selection == null)
57
			selection = IEvaluationContext.UNDEFINED_VARIABLE;
58
		// This is an ugly hack, but necessary for maintaining different
59
		// selection variables in different contexts.
60
		if (getInstallationDialog() instanceof ProductInfoDialog)
61
			sourceProvider.setProductDialogPageSelection(selection);
62
		else
63
			sourceProvider.setPageSelection(selection);
64
	}
65
66
	protected abstract Collection getSelectionValue();
67
}
(-)Eclipse (+29 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import org.eclipse.core.commands.ExecutionEvent;
15
import org.eclipse.swt.widgets.Shell;
16
import org.eclipse.ui.PlatformUI;
17
import org.eclipse.ui.about.InstallationPage;
18
import org.eclipse.ui.handlers.HandlerUtil;
19
20
public class ViewErrorLogHandler extends ProductInfoPageHandler {
21
22
	protected Object execute(InstallationPage page, ExecutionEvent event) {
23
		Shell shell = HandlerUtil.getActiveShell(event);
24
		if (shell == null)
25
			shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
26
		AboutUtils.openErrorLogBrowser(shell);
27
		return null;
28
	}
29
}
(-)Eclipse (+50 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 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
12
package org.eclipse.ui.internal.about;
13
14
import org.eclipse.core.commands.AbstractHandler;
15
import org.eclipse.core.commands.ExecutionEvent;
16
import org.eclipse.core.commands.ExecutionException;
17
import org.eclipse.ui.about.IInstallationPageSources;
18
import org.eclipse.ui.about.InstallationPage;
19
import org.eclipse.ui.handlers.HandlerUtil;
20
21
abstract class ProductInfoPageHandler extends AbstractHandler {
22
	/*
23
	 * (non-Javadoc)
24
	 * 
25
	 * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands
26
	 * .ExecutionEvent)
27
	 */
28
	public Object execute(ExecutionEvent event) throws ExecutionException {
29
		InstallationPage page = getInstallationPage(event.getApplicationContext());
30
		if (page != null)
31
			return execute(page, event);
32
		return null;
33
	}
34
35
	protected InstallationPage getInstallationPage(Object executionContext) {
36
		// First look for an open product info dialog and use its page.
37
		InstallationPage page = (InstallationPage) HandlerUtil.getVariable(
38
				executionContext,
39
				InstallationDialogSourceProvider.ACTIVE_PRODUCT_DIALOG_PAGE);
40
		if (page == null) {
41
			// Look for the active page in the installation dialog
42
			page = (InstallationPage) HandlerUtil.getVariable(executionContext,
43
					IInstallationPageSources.ACTIVE_PAGE);
44
		}
45
		return page;
46
	}
47
48
	protected abstract Object execute(InstallationPage page,
49
			ExecutionEvent event);
50
}
(-)Eclipse (+516 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 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
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
11
 *      font should be activated and used by other components.
12
 *******************************************************************************/
13
package org.eclipse.ui.internal.about;
14
15
import java.net.URL;
16
import java.util.ArrayList;
17
import java.util.Collection;
18
import java.util.HashMap;
19
import java.util.Iterator;
20
import java.util.LinkedList;
21
import java.util.Map;
22
23
import org.eclipse.core.runtime.IBundleGroup;
24
import org.eclipse.core.runtime.IBundleGroupProvider;
25
import org.eclipse.core.runtime.Platform;
26
import org.eclipse.jface.action.Action;
27
import org.eclipse.jface.action.ActionContributionItem;
28
import org.eclipse.jface.resource.ImageDescriptor;
29
import org.eclipse.osgi.util.NLS;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.custom.StyledText;
32
import org.eclipse.swt.events.DisposeEvent;
33
import org.eclipse.swt.events.DisposeListener;
34
import org.eclipse.swt.events.SelectionAdapter;
35
import org.eclipse.swt.events.SelectionEvent;
36
import org.eclipse.swt.graphics.Font;
37
import org.eclipse.swt.graphics.Image;
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.Label;
43
import org.eclipse.swt.widgets.Table;
44
import org.eclipse.swt.widgets.TableColumn;
45
import org.eclipse.swt.widgets.TableItem;
46
import org.eclipse.ui.PlatformUI;
47
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
48
import org.eclipse.ui.internal.WorkbenchMessages;
49
import org.eclipse.ui.internal.dialogs.AboutPluginsDialog;
50
import org.eclipse.ui.menus.AbstractContributionFactory;
51
import org.eclipse.ui.menus.IContributionRoot;
52
import org.eclipse.ui.services.IServiceLocator;
53
import org.osgi.framework.Bundle;
54
55
/**
56
 * Displays information about the product plugins.
57
 * 
58
 * PRIVATE This class is internal to the workbench and must not be called
59
 * outside the workbench.
60
 */
61
public class AboutFeaturesPage extends TableListPage {
62
63
	// This id should *not* be the same id used for contributing the page in
64
	// the installationPage extension. It is used by ProductInfoDialog
65
	// to ensure a different namespace for button contributions than the id
66
	// for the page appearing in the InstallationDialog
67
	private static final String ID = "productInfo.features"; //$NON-NLS-1$
68
	/**
69
	 * Table height in dialog units (value 150).
70
	 */
71
	private static final int TABLE_HEIGHT = 150;
72
73
	private static final int INFO_HEIGHT = 100;
74
75
	private Table table;
76
77
	private Label imageLabel;
78
79
	private StyledText text;
80
81
	private AboutTextManager textManager;
82
83
	private Composite infoArea;
84
85
	private Map cachedImages = new HashMap();
86
87
	private AboutBundleGroupData[] bundleGroupInfos;
88
89
	private String columnTitles[] = {
90
			WorkbenchMessages.AboutFeaturesDialog_provider,
91
			WorkbenchMessages.AboutFeaturesDialog_featureName,
92
			WorkbenchMessages.AboutFeaturesDialog_version,
93
			WorkbenchMessages.AboutFeaturesDialog_featureId, };
94
95
	private int lastColumnChosen = 0; // initially sort by provider
96
97
	private boolean reverseSort = false; // initially sort ascending
98
99
	private AboutBundleGroupData lastSelection = null;
100
101
	private Action pluginsAction;
102
103
	private static Map featuresMap;
104
105
	public void setBundleGroupInfos(AboutBundleGroupData[] bundleGroupInfos) {
106
		this.bundleGroupInfos = bundleGroupInfos;
107
	}
108
109
	String getId() {
110
		return ID;
111
	}
112
113
	private void initializeBundleGroupInfos() {
114
		if (bundleGroupInfos == null) {
115
			IBundleGroupProvider[] providers = Platform
116
					.getBundleGroupProviders();
117
118
			// create a descriptive object for each BundleGroup
119
			LinkedList groups = new LinkedList();
120
			if (providers != null) {
121
				for (int i = 0; i < providers.length; ++i) {
122
					IBundleGroup[] bundleGroups = providers[i]
123
							.getBundleGroups();
124
					for (int j = 0; j < bundleGroups.length; ++j) {
125
						groups.add(new AboutBundleGroupData(bundleGroups[j]));
126
					}
127
				}
128
			}
129
			bundleGroupInfos = (AboutBundleGroupData[]) groups
130
					.toArray(new AboutBundleGroupData[0]);
131
		} else {
132
			// the order of the array may be changed due to sorting, so create a
133
			// copy, since the client set this value.
134
			AboutBundleGroupData[] clientArray = bundleGroupInfos;
135
			bundleGroupInfos = new AboutBundleGroupData[clientArray.length];
136
			System.arraycopy(clientArray, 0, bundleGroupInfos, 0,
137
					clientArray.length);
138
		}
139
		AboutData.sortByProvider(reverseSort, bundleGroupInfos);
140
	}
141
142
	/**
143
	 * The Plugins button was pressed. Open an about dialog on the plugins for
144
	 * the selected feature.
145
	 */
146
	private void handlePluginInfoPressed() {
147
		TableItem[] items = table.getSelection();
148
		if (items.length <= 0) {
149
			return;
150
		}
151
152
		AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
153
		IBundleGroup bundleGroup = info.getBundleGroup();
154
		Bundle[] bundles = bundleGroup == null ? new Bundle[0] : bundleGroup
155
				.getBundles();
156
157
		AboutPluginsDialog d = new AboutPluginsDialog(
158
				getShell(),
159
				getProductName(),
160
				bundles,
161
				WorkbenchMessages.AboutFeaturesDialog_pluginInfoTitle,
162
				NLS
163
						.bind(
164
								WorkbenchMessages.AboutFeaturesDialog_pluginInfoMessage,
165
								bundleGroup.getIdentifier()),
166
				IWorkbenchHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG);
167
		d.open();
168
	}
169
170
	protected AbstractContributionFactory makeContributionFactory() {
171
		return new AbstractContributionFactory(getInstallationDialog()
172
				.getButtonBarURI(), null) {
173
174
			public void createContributionItems(IServiceLocator serviceLocator,
175
					IContributionRoot additions) {
176
177
				pluginsAction = new Action(
178
						WorkbenchMessages.AboutFeaturesDialog_pluginsInfo) {
179
					public void run() {
180
						handlePluginInfoPressed();
181
					}
182
				};
183
				additions.addContributionItem(new ActionContributionItem(
184
						pluginsAction), getInstallationDialog().getActivePageExpression(AboutFeaturesPage.this));
185
			}
186
		};
187
	}
188
189
	protected Control createPageControl(Composite parent) {
190
		initializeDialogUnits(parent);
191
		parent.getShell().addDisposeListener(new DisposeListener() {
192
			public void widgetDisposed(DisposeEvent arg0) {
193
				disposeImages();
194
			}
195
		});
196
		PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
197
				IWorkbenchHelpContextIds.ABOUT_FEATURES_DIALOG);
198
199
		Composite outer = createOuterComposite(parent);
200
201
		createTable(outer);
202
		createInfoArea(outer);
203
		return outer;
204
	}
205
206
	/**
207
	 * Create the info area containing the image and text
208
	 */
209
	protected void createInfoArea(Composite parent) {
210
		Font font = parent.getFont();
211
212
		infoArea = new Composite(parent, SWT.NULL);
213
		GridData data = new GridData(GridData.FILL, GridData.FILL, true, true);
214
		// need to provide space for arbitrary feature infos, not just the
215
		// one selected by default
216
		data.heightHint = convertVerticalDLUsToPixels(INFO_HEIGHT);
217
		infoArea.setLayoutData(data);
218
219
		GridLayout layout = new GridLayout();
220
		layout.numColumns = 2;
221
		infoArea.setLayout(layout);
222
223
		imageLabel = new Label(infoArea, SWT.NONE);
224
		data = new GridData(GridData.FILL, GridData.BEGINNING, false, false);
225
		data.widthHint = 32;
226
		data.heightHint = 32;
227
		imageLabel.setLayoutData(data);
228
		imageLabel.setFont(font);
229
230
		// text on the right
231
		text = new StyledText(infoArea, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY);
232
		text.setCaret(null);
233
		text.setFont(parent.getFont());
234
		data = new GridData(GridData.FILL, GridData.FILL, true, true);
235
		text.setLayoutData(data);
236
		text.setFont(font);
237
		text.setCursor(null);
238
239
		textManager = new AboutTextManager(text);
240
241
		TableItem[] items = table.getSelection();
242
		if (items.length > 0) {
243
			updateInfoArea((AboutBundleGroupData) items[0].getData());
244
		}
245
	}
246
247
	/**
248
	 * Create the table part of the dialog.
249
	 * 
250
	 * @param parent
251
	 *            the parent composite to contain the dialog area
252
	 */
253
	protected void createTable(Composite parent) {
254
255
		initializeBundleGroupInfos();
256
257
		table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
258
				| SWT.FULL_SELECTION | SWT.BORDER);
259
260
		GridData gridData = new GridData(GridData.FILL, GridData.FILL, true,
261
				true);
262
		gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
263
		table.setLayoutData(gridData);
264
		table.setHeaderVisible(true);
265
266
		table.setLinesVisible(true);
267
		table.setFont(parent.getFont());
268
		table.addSelectionListener(new SelectionAdapter() {
269
			public void widgetSelected(SelectionEvent e) {
270
				AboutBundleGroupData info = (AboutBundleGroupData) e.item
271
						.getData();
272
				updateInfoArea(info);
273
				updateButtons(info);
274
				selectionChanged();
275
			}
276
		});
277
278
		int[] columnWidths = { convertHorizontalDLUsToPixels(120),
279
				convertHorizontalDLUsToPixels(120),
280
				convertHorizontalDLUsToPixels(70),
281
				convertHorizontalDLUsToPixels(130) };
282
283
		for (int i = 0; i < columnTitles.length; i++) {
284
			TableColumn tableColumn = new TableColumn(table, SWT.NULL);
285
			tableColumn.setWidth(columnWidths[i]);
286
			tableColumn.setText(columnTitles[i]);
287
			final int columnIndex = i;
288
			tableColumn.addSelectionListener(new SelectionAdapter() {
289
				public void widgetSelected(SelectionEvent e) {
290
					sort(columnIndex);
291
				}
292
			});
293
		}
294
295
		// create a table row for each bundle group
296
		String selId = lastSelection == null ? null : lastSelection.getId();
297
		int sel = 0;
298
		for (int i = 0; i < bundleGroupInfos.length; i++) {
299
			if (bundleGroupInfos[i].getId().equals(selId)) {
300
				sel = i;
301
			}
302
303
			TableItem item = new TableItem(table, SWT.NULL);
304
			item.setText(createRow(bundleGroupInfos[i]));
305
			item.setData(bundleGroupInfos[i]);
306
		}
307
308
		// if an item was specified during construction, it should be
309
		// selected when the table is created
310
		if (bundleGroupInfos.length > 0) {
311
			table.setSelection(sel);
312
			table.showSelection();
313
		}
314
	}
315
316
	private void disposeImages() {
317
		Iterator iter = cachedImages.values().iterator();
318
		while (iter.hasNext()) {
319
			Image image = (Image) iter.next();
320
			image.dispose();
321
		}
322
	}
323
324
	/**
325
	 * Update the button enablement
326
	 */
327
	private void updateButtons(AboutBundleGroupData info) {
328
329
		// called too early
330
		if (pluginsAction == null)
331
			return;
332
333
		if (info == null) {
334
			pluginsAction.setEnabled(false);
335
			return;
336
		}
337
338
		// Creating the feature map is too much just to determine enablement, so
339
		// if doesn't already exist, just enable the buttons. If this was the
340
		// wrong choice, then when the button is actually pressed an dialog will
341
		// be
342
		// opened.
343
		if (featuresMap == null) {
344
			pluginsAction.setEnabled(true);
345
			return;
346
		}
347
348
		pluginsAction.setEnabled(true);
349
	}
350
351
	/**
352
	 * Update the info area
353
	 */
354
	private void updateInfoArea(AboutBundleGroupData info) {
355
		if (info == null) {
356
			imageLabel.setImage(null);
357
			text.setText(""); //$NON-NLS-1$
358
			return;
359
		}
360
361
		ImageDescriptor desc = info.getFeatureImage();
362
		Image image = (Image) cachedImages.get(desc);
363
		if (image == null && desc != null) {
364
			image = desc.createImage();
365
			cachedImages.put(desc, image);
366
		}
367
		imageLabel.setImage(image);
368
369
		String aboutText = info.getAboutText();
370
		textManager.setItem(null);
371
		if (aboutText != null) {
372
			textManager.setItem(AboutUtils.scan(aboutText));
373
		}
374
375
		if (textManager.getItem() == null) {
376
			text.setText(WorkbenchMessages.AboutFeaturesDialog_noInformation);
377
		}
378
	}
379
380
	/**
381
	 * Select the initial selection
382
	 * 
383
	 * @param info
384
	 *            the info
385
	 */
386
	public void setInitialSelection(AboutBundleGroupData info) {
387
		lastSelection = info;
388
	}
389
390
	/**
391
	 * Sort the rows of the table based on the selected column.
392
	 * 
393
	 * @param column
394
	 *            index of table column selected as sort criteria
395
	 */
396
	private void sort(int column) {
397
		if (lastColumnChosen == column) {
398
			reverseSort = !reverseSort;
399
		} else {
400
			reverseSort = false;
401
			lastColumnChosen = column;
402
		}
403
404
		if (table.getItemCount() <= 1) {
405
			return;
406
		}
407
408
		// Remember the last selection
409
		int sel = table.getSelectionIndex();
410
		if (sel != -1) {
411
			lastSelection = bundleGroupInfos[sel];
412
		}
413
414
		switch (column) {
415
		case 0:
416
			AboutData.sortByProvider(reverseSort, bundleGroupInfos);
417
			break;
418
		case 1:
419
			AboutData.sortByName(reverseSort, bundleGroupInfos);
420
			break;
421
		case 2:
422
			AboutData.sortByVersion(reverseSort, bundleGroupInfos);
423
			break;
424
		case 3:
425
			AboutData.sortById(reverseSort, bundleGroupInfos);
426
			break;
427
		}
428
429
		refreshTable();
430
	}
431
432
	/**
433
	 * Refresh the rows of the table based on the selected column. Maintain
434
	 * selection from before sort action request.
435
	 */
436
	private void refreshTable() {
437
		TableItem[] items = table.getItems();
438
439
		// create new order of table items
440
		for (int i = 0; i < items.length; i++) {
441
			items[i].setText(createRow(bundleGroupInfos[i]));
442
			items[i].setData(bundleGroupInfos[i]);
443
		}
444
445
		// Maintain the original selection
446
		int sel = -1;
447
		if (lastSelection != null) {
448
			String oldId = lastSelection.getId();
449
			for (int k = 0; k < bundleGroupInfos.length; k++) {
450
				if (oldId.equalsIgnoreCase(bundleGroupInfos[k].getId())) {
451
					sel = k;
452
				}
453
			}
454
455
			table.setSelection(sel);
456
			table.showSelection();
457
		}
458
459
		updateInfoArea(lastSelection);
460
	}
461
462
	/**
463
	 * Return an array of strings containing the argument's information in the
464
	 * proper order for this table's columns.
465
	 * 
466
	 * @param info
467
	 *            the source information for the new row, must not be null
468
	 */
469
	private static String[] createRow(AboutBundleGroupData info) {
470
		return new String[] { info.getProviderName(), info.getName(),
471
				info.getVersion(), info.getId() };
472
	}
473
474
	/*
475
	 * (non-Javadoc)
476
	 * 
477
	 * @see org.eclipse.ui.internal.about.ColumnsPage#getTable()
478
	 */
479
	protected Table getTable() {
480
		return table;
481
	}
482
483
	/*
484
	 * (non-Javadoc)
485
	 * 
486
	 * @see org.eclipse.ui.internal.about.TableListPage#getURL()
487
	 */
488
	protected URL getURL() {
489
		if (table == null || table.isDisposed())
490
			return null;
491
		TableItem[] items = table.getSelection();
492
		if (items.length <= 0) 
493
			return null;
494
495
		AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
496
		if (info == null)
497
			return null;
498
		
499
		return info.getLicenseUrl();
500
	}
501
502
	/* (non-Javadoc)
503
	 * @see org.eclipse.ui.internal.about.TableListPage#getSelectionValue()
504
	 */
505
	protected Collection getSelectionValue() {
506
		if (table == null || table.isDisposed())
507
			return null;
508
		TableItem[] items = table.getSelection();
509
		if (items.length <= 0) {
510
			return null;
511
		}
512
		ArrayList list = new ArrayList(1);
513
		list.add(items[0].getData());
514
		return list;
515
	}	
516
}

Return to bug 246875