OSDN Git Service

Fix android.bat for Windows SDK.
[android-x86/sdk.git] / sdkmanager / libs / sdkuilib / src / com / android / sdkuilib / internal / repository / SdkUpdaterWindowImpl2.java
1 /*\r
2  * Copyright (C) 2011 The Android Open Source Project\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 package com.android.sdkuilib.internal.repository;\r
18 \r
19 \r
20 import com.android.sdklib.ISdkLog;\r
21 import com.android.sdklib.SdkConstants;\r
22 import com.android.sdklib.internal.repository.ITaskFactory;\r
23 import com.android.sdkuilib.internal.repository.PackagesPage.MenuAction;\r
24 import com.android.sdkuilib.internal.repository.UpdaterPage.Purpose;\r
25 import com.android.sdkuilib.internal.repository.icons.ImageFactory;\r
26 import com.android.sdkuilib.internal.tasks.ProgressView;\r
27 import com.android.sdkuilib.internal.tasks.ProgressViewFactory;\r
28 import com.android.sdkuilib.internal.widgets.ImgDisabledButton;\r
29 import com.android.sdkuilib.internal.widgets.ToggleButton;\r
30 import com.android.sdkuilib.repository.ISdkChangeListener;\r
31 import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext;\r
32 import com.android.sdkuilib.ui.GridDataBuilder;\r
33 import com.android.sdkuilib.ui.GridLayoutBuilder;\r
34 import com.android.sdkuilib.ui.SwtBaseDialog;\r
35 import com.android.util.Pair;\r
36 \r
37 import org.eclipse.swt.SWT;\r
38 import org.eclipse.swt.events.DisposeEvent;\r
39 import org.eclipse.swt.events.DisposeListener;\r
40 import org.eclipse.swt.events.SelectionAdapter;\r
41 import org.eclipse.swt.events.SelectionEvent;\r
42 import org.eclipse.swt.graphics.Image;\r
43 import org.eclipse.swt.graphics.Point;\r
44 import org.eclipse.swt.layout.GridData;\r
45 import org.eclipse.swt.layout.GridLayout;\r
46 import org.eclipse.swt.widgets.Button;\r
47 import org.eclipse.swt.widgets.Composite;\r
48 import org.eclipse.swt.widgets.Display;\r
49 import org.eclipse.swt.widgets.Event;\r
50 import org.eclipse.swt.widgets.Label;\r
51 import org.eclipse.swt.widgets.Listener;\r
52 import org.eclipse.swt.widgets.Menu;\r
53 import org.eclipse.swt.widgets.MenuItem;\r
54 import org.eclipse.swt.widgets.ProgressBar;\r
55 import org.eclipse.swt.widgets.Shell;\r
56 \r
57 import java.util.ArrayList;\r
58 \r
59 /**\r
60  * This is the private implementation of the UpdateWindow\r
61  * for the second version of the SDK Manager.\r
62  * <p/>\r
63  * This window features only one embedded page, the combined installed+available package list.\r
64  */\r
65 public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow {\r
66 \r
67     private static final String APP_NAME = "Android SDK Manager";\r
68     private final Shell mParentShell;\r
69     private final SdkInvocationContext mContext;\r
70     /** Internal data shared between the window and its pages. */\r
71     private final UpdaterData mUpdaterData;\r
72     /** A list of extra pages to instantiate. Each entry is an object array with 2 elements:\r
73      *  the string title and the Composite class to instantiate to create the page. */\r
74     private ArrayList<Pair<Class<? extends UpdaterPage>, Purpose>> mExtraPages;\r
75     /** Sets whether the auto-update wizard will be shown when opening the window. */\r
76     private boolean mRequestAutoUpdate;\r
77 \r
78     // --- UI members ---\r
79 \r
80     protected Shell mShell;\r
81     private PackagesPage mPkgPage;\r
82     private ProgressBar mProgressBar;\r
83     private Label mStatusText;\r
84     private ImgDisabledButton mButtonStop;\r
85     private ToggleButton mButtonDetails;\r
86     private SettingsController mSettingsController;\r
87 \r
88     /**\r
89      * Creates a new window. Caller must call open(), which will block.\r
90      *\r
91      * @param parentShell Parent shell.\r
92      * @param sdkLog Logger. Cannot be null.\r
93      * @param osSdkRoot The OS path to the SDK root.\r
94      * @param context The {@link SdkInvocationContext} to change the behavior depending on who's\r
95      *  opening the SDK Manager.\r
96      */\r
97     public SdkUpdaterWindowImpl2(\r
98             Shell parentShell,\r
99             ISdkLog sdkLog,\r
100             String osSdkRoot,\r
101             SdkInvocationContext context) {\r
102         mParentShell = parentShell;\r
103         mContext = context;\r
104         mUpdaterData = new UpdaterData(osSdkRoot, sdkLog);\r
105     }\r
106 \r
107     /**\r
108      * Creates a new window. Caller must call open(), which will block.\r
109      * <p/>\r
110      * This is to be used when the window is opened from {@link AvdManagerWindowImpl1}\r
111      * to share the same {@link UpdaterData} structure.\r
112      *\r
113      * @param parentShell Parent shell.\r
114      * @param updaterData The parent's updater data.\r
115      * @param context The {@link SdkInvocationContext} to change the behavior depending on who's\r
116      *  opening the SDK Manager.\r
117      */\r
118     public SdkUpdaterWindowImpl2(\r
119             Shell parentShell,\r
120             UpdaterData updaterData,\r
121             SdkInvocationContext context) {\r
122         mParentShell = parentShell;\r
123         mContext = context;\r
124         mUpdaterData = updaterData;\r
125     }\r
126 \r
127     /**\r
128      * Opens the window.\r
129      * @wbp.parser.entryPoint\r
130      */\r
131     public void open() {\r
132         if (mParentShell == null) {\r
133             Display.setAppName(APP_NAME); //$hide$ (hide from SWT designer)\r
134         }\r
135 \r
136         createShell();\r
137         preCreateContent();\r
138         createContents();\r
139         createMenuBar();\r
140         mShell.open();\r
141         mShell.layout();\r
142 \r
143         if (postCreateContent()) {    //$hide$ (hide from SWT designer)\r
144             Display display = Display.getDefault();\r
145             while (!mShell.isDisposed()) {\r
146                 if (!display.readAndDispatch()) {\r
147                     display.sleep();\r
148                 }\r
149             }\r
150         }\r
151 \r
152         dispose();  //$hide$\r
153     }\r
154 \r
155     private void createShell() {\r
156         mShell = new Shell(mParentShell, SWT.SHELL_TRIM);\r
157         mShell.addDisposeListener(new DisposeListener() {\r
158             public void widgetDisposed(DisposeEvent e) {\r
159                 onAndroidSdkUpdaterDispose();    //$hide$ (hide from SWT designer)\r
160             }\r
161         });\r
162 \r
163         GridLayout glShell = new GridLayout(2, false);\r
164         glShell.verticalSpacing = 0;\r
165         glShell.horizontalSpacing = 0;\r
166         glShell.marginWidth = 0;\r
167         glShell.marginHeight = 0;\r
168         mShell.setLayout(glShell);\r
169 \r
170         mShell.setMinimumSize(new Point(500, 300));\r
171         mShell.setSize(700, 500);\r
172         mShell.setText(APP_NAME);\r
173     }\r
174 \r
175     private void createContents() {\r
176 \r
177         mPkgPage = new PackagesPage(mShell, SWT.NONE, mUpdaterData);\r
178         mPkgPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));\r
179 \r
180         Composite composite1 = new Composite(mShell, SWT.NONE);\r
181         composite1.setLayout(new GridLayout(1, false));\r
182         composite1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));\r
183 \r
184         mProgressBar = new ProgressBar(composite1, SWT.NONE);\r
185         mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));\r
186 \r
187         mStatusText = new Label(composite1, SWT.NONE);\r
188         mStatusText.setText("Status Placeholder");  //$NON-NLS-1$ placeholder\r
189         mStatusText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));\r
190 \r
191         Composite composite2 = new Composite(mShell, SWT.NONE);\r
192         composite2.setLayout(new GridLayout(2, false));\r
193 \r
194         mButtonStop = new ImgDisabledButton(composite2, SWT.NONE,\r
195                 getImage("stop_enabled_16.png"),   //$NON-NLS-1$\r
196                 getImage("stop_disabled_16.png"));   //$NON-NLS-1$\r
197         mButtonStop.addListener(SWT.Selection, new Listener() {\r
198             public void handleEvent(Event event) {\r
199                 onStopSelected();\r
200             }\r
201         });\r
202 \r
203         mButtonDetails = new ToggleButton(composite2, SWT.NONE,\r
204                 getImage("collapsed_16.png"),   //$NON-NLS-1$\r
205                 getImage("expanded_16.png"));   //$NON-NLS-1$\r
206         mButtonDetails.addListener(SWT.Selection, new Listener() {\r
207             public void handleEvent(Event event) {\r
208                 onToggleDetails();\r
209             }\r
210         });\r
211     }\r
212 \r
213     private void createMenuBar() {\r
214 \r
215         Menu menuBar = new Menu(mShell, SWT.BAR);\r
216         mShell.setMenuBar(menuBar);\r
217 \r
218         MenuItem menuBarPackages = new MenuItem(menuBar, SWT.CASCADE);\r
219         menuBarPackages.setText("Packages");\r
220 \r
221         Menu menuPkgs = new Menu(menuBarPackages);\r
222         menuBarPackages.setMenu(menuPkgs);\r
223 \r
224         MenuItem showUpdatesNew = new MenuItem(menuPkgs,\r
225                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle());\r
226         showUpdatesNew.setText(\r
227                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle());\r
228         mPkgPage.registerMenuAction(\r
229                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew);\r
230 \r
231         MenuItem showInstalled = new MenuItem(menuPkgs,\r
232                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle());\r
233         showInstalled.setText(\r
234                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle());\r
235         mPkgPage.registerMenuAction(\r
236                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled);\r
237 \r
238         MenuItem showObsoletePackages = new MenuItem(menuPkgs,\r
239                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle());\r
240         showObsoletePackages.setText(\r
241                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuTitle());\r
242         mPkgPage.registerMenuAction(\r
243                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages);\r
244 \r
245         MenuItem showArchives = new MenuItem(menuPkgs,\r
246                 MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle());\r
247         showArchives.setText(\r
248                 MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle());\r
249         mPkgPage.registerMenuAction(\r
250                 MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives);\r
251 \r
252         new MenuItem(menuPkgs, SWT.SEPARATOR);\r
253 \r
254         MenuItem sortByApi = new MenuItem(menuPkgs,\r
255                 MenuAction.SORT_API_LEVEL.getMenuStyle());\r
256         sortByApi.setText(\r
257                 MenuAction.SORT_API_LEVEL.getMenuTitle());\r
258         mPkgPage.registerMenuAction(\r
259                 MenuAction.SORT_API_LEVEL, sortByApi);\r
260 \r
261         MenuItem sortBySource = new MenuItem(menuPkgs,\r
262                 MenuAction.SORT_SOURCE.getMenuStyle());\r
263         sortBySource.setText(\r
264                 MenuAction.SORT_SOURCE.getMenuTitle());\r
265         mPkgPage.registerMenuAction(\r
266                 MenuAction.SORT_SOURCE, sortBySource);\r
267 \r
268         new MenuItem(menuPkgs, SWT.SEPARATOR);\r
269 \r
270         MenuItem reload = new MenuItem(menuPkgs,\r
271                 MenuAction.RELOAD.getMenuStyle());\r
272         reload.setText(\r
273                 MenuAction.RELOAD.getMenuTitle());\r
274         mPkgPage.registerMenuAction(\r
275                 MenuAction.RELOAD, reload);\r
276 \r
277         MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE);\r
278         menuBarTools.setText("Tools");\r
279 \r
280         Menu menuTools = new Menu(menuBarTools);\r
281         menuBarTools.setMenu(menuTools);\r
282 \r
283         if (mContext == SdkInvocationContext.STANDALONE) {\r
284             MenuItem manageAvds = new MenuItem(menuTools, SWT.NONE);\r
285             manageAvds.setText("Manage AVDs...");\r
286             manageAvds.addSelectionListener(new SelectionAdapter() {\r
287                 @Override\r
288                 public void widgetSelected(SelectionEvent event) {\r
289                     onAvdManager();\r
290                 }\r
291             });\r
292         }\r
293 \r
294         MenuItem manageSources = new MenuItem(menuTools,\r
295                 MenuAction.SHOW_ADDON_SITES.getMenuStyle());\r
296         manageSources.setText(\r
297                 MenuAction.SHOW_ADDON_SITES.getMenuTitle());\r
298         mPkgPage.registerMenuAction(\r
299                 MenuAction.SHOW_ADDON_SITES, manageSources);\r
300 \r
301         if (mContext == SdkInvocationContext.STANDALONE) {\r
302             // Note: when invoked from an IDE, the SwtMenuBar library isn't\r
303             // available. This means this source should not directly import\r
304             // any of SwtMenuBar classes, otherwise the whole window class\r
305             // would fail to load. The MenuBarWrapper below helps to make\r
306             // that indirection.\r
307 \r
308             try {\r
309                 new MenuBarWrapper(APP_NAME, menuTools) {\r
310                     @Override\r
311                     public void onPreferencesMenuSelected() {\r
312                         showRegisteredPage(Purpose.SETTINGS);\r
313                     }\r
314 \r
315                     @Override\r
316                     public void onAboutMenuSelected() {\r
317                         showRegisteredPage(Purpose.ABOUT_BOX);\r
318                     }\r
319 \r
320                     @Override\r
321                     public void printError(String format, Object... args) {\r
322                         if (mUpdaterData != null) {\r
323                             mUpdaterData.getSdkLog().error(null, format, args);\r
324                         }\r
325                     }\r
326                 };\r
327             } catch (Exception e) {\r
328                 mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar");\r
329                 e.printStackTrace();\r
330             }\r
331         }\r
332     }\r
333 \r
334     private Image getImage(String filename) {\r
335         if (mUpdaterData != null) {\r
336             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
337             if (imgFactory != null) {\r
338                 return imgFactory.getImageByName(filename);\r
339             }\r
340         }\r
341         return null;\r
342     }\r
343 \r
344 \r
345     // -- Start of internal part ----------\r
346     // Hide everything down-below from SWT designer\r
347     //$hide>>$\r
348 \r
349     // --- Public API -----------\r
350 \r
351 \r
352     /**\r
353      * Registers an extra page for the updater window.\r
354      * <p/>\r
355      * Pages must derive from {@link Composite} and implement a constructor that takes\r
356      * a single parent {@link Composite} argument.\r
357      * <p/>\r
358      * All pages must be registered before the call to {@link #open()}.\r
359      *\r
360      * @param pageClass The {@link Composite}-derived class that will implement the page.\r
361      * @param purpose The purpose of this page, e.g. an about box, settings page or generic.\r
362      */\r
363     @SuppressWarnings("unchecked")\r
364     public void registerPage(Class<? extends UpdaterPage> pageClass,\r
365             Purpose purpose) {\r
366         if (mExtraPages == null) {\r
367             mExtraPages = new ArrayList<Pair<Class<? extends UpdaterPage>, Purpose>>();\r
368         }\r
369         Pair<?, Purpose> value = Pair.of(pageClass, purpose);\r
370         mExtraPages.add((Pair<Class<? extends UpdaterPage>, Purpose>) value);\r
371     }\r
372 \r
373     /**\r
374      * Indicate the initial page that should be selected when the window opens.\r
375      * This must be called before the call to {@link #open()}.\r
376      * If null or if the page class is not found, the first page will be selected.\r
377      */\r
378     public void setInitialPage(Class<? extends Composite> pageClass) {\r
379         // Unused in this case. This window display only one page.\r
380     }\r
381 \r
382     /**\r
383      * Sets whether the auto-update wizard will be shown when opening the window.\r
384      * <p/>\r
385      * This must be called before the call to {@link #open()}.\r
386      */\r
387     public void setRequestAutoUpdate(boolean requestAutoUpdate) {\r
388         mRequestAutoUpdate = requestAutoUpdate;\r
389     }\r
390 \r
391     /**\r
392      * Adds a new listener to be notified when a change is made to the content of the SDK.\r
393      */\r
394     public void addListener(ISdkChangeListener listener) {\r
395         mUpdaterData.addListeners(listener);\r
396     }\r
397 \r
398     /**\r
399      * Removes a new listener to be notified anymore when a change is made to the content of\r
400      * the SDK.\r
401      */\r
402     public void removeListener(ISdkChangeListener listener) {\r
403         mUpdaterData.removeListener(listener);\r
404     }\r
405 \r
406     // --- Internals & UI Callbacks -----------\r
407 \r
408     /**\r
409      * Called before the UI is created.\r
410      */\r
411     private void preCreateContent() {\r
412         mUpdaterData.setWindowShell(mShell);\r
413         // We need the UI factory to create the UI\r
414         mUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay()));\r
415         // Note: we can't create the TaskFactory yet because we need the UI\r
416         // to be created first, so this is done in postCreateContent().\r
417     }\r
418 \r
419     /**\r
420      * Once the UI has been created, initializes the content.\r
421      * This creates the pages, selects the first one, setup sources and scan for local folders.\r
422      *\r
423      * Returns true if we should show the window.\r
424      */\r
425     private boolean postCreateContent() {\r
426         ProgressViewFactory factory = new ProgressViewFactory();\r
427         factory.setProgressView(new ProgressView(\r
428                 mStatusText, mProgressBar, mButtonStop,\r
429                 mContext == SdkInvocationContext.IDE ? mUpdaterData.getSdkLog() : null));\r
430         mUpdaterData.setTaskFactory(factory);\r
431 \r
432         setWindowImage(mShell);\r
433 \r
434         setupSources();\r
435         initializeSettings();\r
436 \r
437         if (mUpdaterData.checkIfInitFailed()) {\r
438             return false;\r
439         }\r
440 \r
441         mUpdaterData.broadcastOnSdkLoaded();\r
442 \r
443         if (mRequestAutoUpdate) {\r
444             mUpdaterData.updateOrInstallAll_WithGUI(\r
445                     null /*selectedArchives*/,\r
446                     false /* includeObsoletes */);\r
447         }\r
448 \r
449         // Tell the one page its the selected one\r
450         mPkgPage.onPageSelected();\r
451 \r
452         return true;\r
453     }\r
454 \r
455     /**\r
456      * Creates the icon of the window shell.\r
457      *\r
458      * @param shell The shell on which to put the icon\r
459      */\r
460     private void setWindowImage(Shell shell) {\r
461         String imageName = "android_icon_16.png"; //$NON-NLS-1$\r
462         if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) {\r
463             imageName = "android_icon_128.png"; //$NON-NLS-1$\r
464         }\r
465 \r
466         if (mUpdaterData != null) {\r
467             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
468             if (imgFactory != null) {\r
469                 shell.setImage(imgFactory.getImageByName(imageName));\r
470             }\r
471         }\r
472     }\r
473 \r
474     /**\r
475      * Called by the main loop when the window has been disposed.\r
476      */\r
477     private void dispose() {\r
478         mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog());\r
479     }\r
480 \r
481     /**\r
482      * Callback called when the window shell is disposed.\r
483      */\r
484     private void onAndroidSdkUpdaterDispose() {\r
485         if (mUpdaterData != null) {\r
486             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
487             if (imgFactory != null) {\r
488                 imgFactory.dispose();\r
489             }\r
490         }\r
491     }\r
492 \r
493     /**\r
494      * Used to initialize the sources.\r
495      */\r
496     private void setupSources() {\r
497         mUpdaterData.setupDefaultSources();\r
498     }\r
499 \r
500     /**\r
501      * Initializes settings.\r
502      * This must be called after addExtraPages(), which created a settings page.\r
503      * Iterate through all the pages to find the first (and supposedly unique) setting page,\r
504      * and use it to load and apply these settings.\r
505      */\r
506     private void initializeSettings() {\r
507         mSettingsController = mUpdaterData.getSettingsController();\r
508         mSettingsController.loadSettings();\r
509         mSettingsController.applySettings();\r
510     }\r
511 \r
512     private void onToggleDetails() {\r
513         mButtonDetails.setState(1 - mButtonDetails.getState());\r
514     }\r
515 \r
516     private void onStopSelected() {\r
517         // TODO\r
518     }\r
519 \r
520     private void showRegisteredPage(Purpose purpose) {\r
521         if (mExtraPages == null) {\r
522             return;\r
523         }\r
524 \r
525         Class<? extends UpdaterPage> clazz = null;\r
526 \r
527         for (Pair<Class<? extends UpdaterPage>, Purpose> extraPage : mExtraPages) {\r
528             if (extraPage.getSecond() == purpose) {\r
529                 clazz = extraPage.getFirst();\r
530                 break;\r
531             }\r
532         }\r
533 \r
534         if (clazz != null) {\r
535             PageDialog d = new PageDialog(mShell, clazz, purpose == Purpose.SETTINGS);\r
536             d.open();\r
537         }\r
538     }\r
539 \r
540     private void onAvdManager() {\r
541         ITaskFactory oldFactory = mUpdaterData.getTaskFactory();\r
542 \r
543         try {\r
544             AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1(\r
545                     mShell,\r
546                     mUpdaterData,\r
547                     AvdManagerWindowImpl1.AvdInvocationContext.SDK_MANAGER);\r
548 \r
549             for (Pair<Class<? extends UpdaterPage>, Purpose> page : mExtraPages) {\r
550                 win.registerPage(page.getFirst(), page.getSecond());\r
551             }\r
552 \r
553             win.open();\r
554         } catch (Exception e) {\r
555             mUpdaterData.getSdkLog().error(e, "AVD Manager window error");\r
556         } finally {\r
557             mUpdaterData.setTaskFactory(oldFactory);\r
558         }\r
559     }\r
560 \r
561     // End of hiding from SWT Designer\r
562     //$hide<<$\r
563 \r
564     // -----\r
565 \r
566     /**\r
567      * Dialog used to display either the About page or the Settings (aka Options) page\r
568      * with a "close" button.\r
569      */\r
570     private class PageDialog extends SwtBaseDialog {\r
571 \r
572         private final Class<? extends UpdaterPage> mPageClass;\r
573         private final boolean mIsSettingsPage;\r
574 \r
575         protected PageDialog(\r
576                 Shell parentShell,\r
577                 Class<? extends UpdaterPage> pageClass,\r
578                 boolean isSettingsPage) {\r
579             super(parentShell, SWT.APPLICATION_MODAL, null /*title*/);\r
580             mPageClass = pageClass;\r
581             mIsSettingsPage = isSettingsPage;\r
582         }\r
583 \r
584         @Override\r
585         protected void createContents() {\r
586             Shell shell = getShell();\r
587             setWindowImage(shell);\r
588 \r
589             GridLayoutBuilder.create(shell).columns(2);\r
590 \r
591             UpdaterPage content = UpdaterPage.newInstance(\r
592                     mPageClass,\r
593                     shell,\r
594                     SWT.NONE,\r
595                     mUpdaterData.getSdkLog());\r
596             GridDataBuilder.create(content).fill().grab().hSpan(2);\r
597             if (content.getLayout() instanceof GridLayout) {\r
598                 GridLayout gl = (GridLayout) content.getLayout();\r
599                 gl.marginHeight = gl.marginWidth = 0;\r
600             }\r
601 \r
602             if (mIsSettingsPage && content instanceof ISettingsPage) {\r
603                 mSettingsController.setSettingsPage((ISettingsPage) content);\r
604             }\r
605 \r
606             getShell().setText(\r
607                     String.format("%1$s - %2$s", APP_NAME, content.getPageTitle()));  //$NON-NLS-1$\r
608 \r
609             Label filler = new Label(shell, SWT.NONE);\r
610             GridDataBuilder.create(filler).hFill().hGrab();\r
611 \r
612             Button close = new Button(shell, SWT.PUSH);\r
613             close.setText("Close");\r
614             GridDataBuilder.create(close);\r
615             close.addSelectionListener(new SelectionAdapter() {\r
616                 @Override\r
617                 public void widgetSelected(SelectionEvent e) {\r
618                     close();\r
619                 }\r
620             });\r
621         }\r
622 \r
623         @Override\r
624         protected void postCreate() {\r
625             // pass\r
626         }\r
627 \r
628         @Override\r
629         protected void close() {\r
630             if (mIsSettingsPage) {\r
631                 mSettingsController.setSettingsPage(null);\r
632             }\r
633             super.close();\r
634         }\r
635     }\r
636 }\r