OSDN Git Service

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