OSDN Git Service

SDK Manager: Fix disabled quit menu on Mac. Do not merge.
[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.DIALOG_TRIM | 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     private void createMenuBar() {\r
240 \r
241         Menu menuBar = new Menu(mShell, SWT.BAR);\r
242         mShell.setMenuBar(menuBar);\r
243 \r
244         MenuItem menuBarPackages = new MenuItem(menuBar, SWT.CASCADE);\r
245         menuBarPackages.setText("Packages");\r
246 \r
247         Menu menuPkgs = new Menu(menuBarPackages);\r
248         menuBarPackages.setMenu(menuPkgs);\r
249 \r
250         MenuItem showUpdatesNew = new MenuItem(menuPkgs,\r
251                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle());\r
252         showUpdatesNew.setText(\r
253                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle());\r
254         mPkgPage.registerMenuAction(\r
255                 MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew);\r
256 \r
257         MenuItem showInstalled = new MenuItem(menuPkgs,\r
258                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle());\r
259         showInstalled.setText(\r
260                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle());\r
261         mPkgPage.registerMenuAction(\r
262                 MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled);\r
263 \r
264         MenuItem showObsoletePackages = new MenuItem(menuPkgs,\r
265                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle());\r
266         showObsoletePackages.setText(\r
267                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuTitle());\r
268         mPkgPage.registerMenuAction(\r
269                 MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages);\r
270 \r
271         MenuItem showArchives = new MenuItem(menuPkgs,\r
272                 MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle());\r
273         showArchives.setText(\r
274                 MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle());\r
275         mPkgPage.registerMenuAction(\r
276                 MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives);\r
277 \r
278         new MenuItem(menuPkgs, SWT.SEPARATOR);\r
279 \r
280         MenuItem sortByApi = new MenuItem(menuPkgs,\r
281                 MenuAction.SORT_API_LEVEL.getMenuStyle());\r
282         sortByApi.setText(\r
283                 MenuAction.SORT_API_LEVEL.getMenuTitle());\r
284         mPkgPage.registerMenuAction(\r
285                 MenuAction.SORT_API_LEVEL, sortByApi);\r
286 \r
287         MenuItem sortBySource = new MenuItem(menuPkgs,\r
288                 MenuAction.SORT_SOURCE.getMenuStyle());\r
289         sortBySource.setText(\r
290                 MenuAction.SORT_SOURCE.getMenuTitle());\r
291         mPkgPage.registerMenuAction(\r
292                 MenuAction.SORT_SOURCE, sortBySource);\r
293 \r
294         new MenuItem(menuPkgs, SWT.SEPARATOR);\r
295 \r
296         MenuItem reload = new MenuItem(menuPkgs,\r
297                 MenuAction.RELOAD.getMenuStyle());\r
298         reload.setText(\r
299                 MenuAction.RELOAD.getMenuTitle());\r
300         mPkgPage.registerMenuAction(\r
301                 MenuAction.RELOAD, reload);\r
302 \r
303         MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE);\r
304         menuBarTools.setText("Tools");\r
305 \r
306         Menu menuTools = new Menu(menuBarTools);\r
307         menuBarTools.setMenu(menuTools);\r
308 \r
309         if (mContext == SdkInvocationContext.STANDALONE) {\r
310             MenuItem manageAvds = new MenuItem(menuTools, SWT.NONE);\r
311             manageAvds.setText("Manage AVDs...");\r
312             manageAvds.addSelectionListener(new SelectionAdapter() {\r
313                 @Override\r
314                 public void widgetSelected(SelectionEvent event) {\r
315                     onAvdManager();\r
316                 }\r
317             });\r
318         }\r
319 \r
320         MenuItem manageSources = new MenuItem(menuTools,\r
321                 MenuAction.SHOW_ADDON_SITES.getMenuStyle());\r
322         manageSources.setText(\r
323                 MenuAction.SHOW_ADDON_SITES.getMenuTitle());\r
324         mPkgPage.registerMenuAction(\r
325                 MenuAction.SHOW_ADDON_SITES, manageSources);\r
326 \r
327         if (mContext == SdkInvocationContext.STANDALONE) {\r
328             // Note: when invoked from an IDE, the SwtMenuBar library isn't\r
329             // available. This means this source should not directly import\r
330             // any of SwtMenuBar classes, otherwise the whole window class\r
331             // would fail to load. The MenuBarWrapper below helps to make\r
332             // that indirection.\r
333 \r
334             try {\r
335                 new MenuBarWrapper(APP_NAME, menuTools) {\r
336                     @Override\r
337                     public void onPreferencesMenuSelected() {\r
338                         showRegisteredPage(Purpose.SETTINGS);\r
339                     }\r
340 \r
341                     @Override\r
342                     public void onAboutMenuSelected() {\r
343                         showRegisteredPage(Purpose.ABOUT_BOX);\r
344                     }\r
345 \r
346                     @Override\r
347                     public void printError(String format, Object... args) {\r
348                         if (mUpdaterData != null) {\r
349                             mUpdaterData.getSdkLog().error(null, format, args);\r
350                         }\r
351                     }\r
352                 };\r
353             } catch (Exception e) {\r
354                 mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar");\r
355                 e.printStackTrace();\r
356             }\r
357         }\r
358     }\r
359 \r
360     private Image getImage(String filename) {\r
361         if (mUpdaterData != null) {\r
362             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
363             if (imgFactory != null) {\r
364                 return imgFactory.getImageByName(filename);\r
365             }\r
366         }\r
367         return null;\r
368     }\r
369 \r
370     /**\r
371      * Creates the log window.\r
372      * <p/>\r
373      * If this is invoked from an IDE, we also define a secondary logger so that all\r
374      * messages flow to the IDE log. This may or may not be what we want in the end\r
375      * (e.g. a middle ground would be to repeat error, and ignore normal/verbose)\r
376      */\r
377     private void createLogWindow() {\r
378         mLogWindow = new LogWindow(mShell,\r
379                 mContext == SdkInvocationContext.IDE ? mUpdaterData.getSdkLog() : null);\r
380         mLogWindow.open();\r
381     }\r
382 \r
383 \r
384     // -- Start of internal part ----------\r
385     // Hide everything down-below from SWT designer\r
386     //$hide>>$\r
387 \r
388     // --- Public API -----------\r
389 \r
390 \r
391     /**\r
392      * Registers an extra page for the updater window.\r
393      * <p/>\r
394      * Pages must derive from {@link Composite} and implement a constructor that takes\r
395      * a single parent {@link Composite} argument.\r
396      * <p/>\r
397      * All pages must be registered before the call to {@link #open()}.\r
398      *\r
399      * @param pageClass The {@link Composite}-derived class that will implement the page.\r
400      * @param purpose The purpose of this page, e.g. an about box, settings page or generic.\r
401      */\r
402     @SuppressWarnings("unchecked")\r
403     public void registerPage(Class<? extends UpdaterPage> pageClass,\r
404             Purpose purpose) {\r
405         if (mExtraPages == null) {\r
406             mExtraPages = new ArrayList<Pair<Class<? extends UpdaterPage>, Purpose>>();\r
407         }\r
408         Pair<?, Purpose> value = Pair.of(pageClass, purpose);\r
409         mExtraPages.add((Pair<Class<? extends UpdaterPage>, Purpose>) value);\r
410     }\r
411 \r
412     /**\r
413      * Indicate the initial page that should be selected when the window opens.\r
414      * This must be called before the call to {@link #open()}.\r
415      * If null or if the page class is not found, the first page will be selected.\r
416      */\r
417     public void setInitialPage(Class<? extends Composite> pageClass) {\r
418         // Unused in this case. This window display only one page.\r
419     }\r
420 \r
421     /**\r
422      * Sets whether the auto-update wizard will be shown when opening the window.\r
423      * <p/>\r
424      * This must be called before the call to {@link #open()}.\r
425      */\r
426     public void setRequestAutoUpdate(boolean requestAutoUpdate) {\r
427         mRequestAutoUpdate = requestAutoUpdate;\r
428     }\r
429 \r
430     /**\r
431      * Adds a new listener to be notified when a change is made to the content of the SDK.\r
432      */\r
433     public void addListener(ISdkChangeListener listener) {\r
434         mUpdaterData.addListeners(listener);\r
435     }\r
436 \r
437     /**\r
438      * Removes a new listener to be notified anymore when a change is made to the content of\r
439      * the SDK.\r
440      */\r
441     public void removeListener(ISdkChangeListener listener) {\r
442         mUpdaterData.removeListener(listener);\r
443     }\r
444 \r
445     // --- Internals & UI Callbacks -----------\r
446 \r
447     /**\r
448      * Called before the UI is created.\r
449      */\r
450     private void preCreateContent() {\r
451         mUpdaterData.setWindowShell(mShell);\r
452         // We need the UI factory to create the UI\r
453         mUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay()));\r
454         // Note: we can't create the TaskFactory yet because we need the UI\r
455         // to be created first, so this is done in postCreateContent().\r
456     }\r
457 \r
458     /**\r
459      * Once the UI has been created, initializes the content.\r
460      * This creates the pages, selects the first one, setups sources and scans for local folders.\r
461      *\r
462      * Returns true if we should show the window.\r
463      */\r
464     private boolean postCreateContent() {\r
465         ProgressViewFactory factory = new ProgressViewFactory();\r
466 \r
467         // This class delegates all logging to the mLogWindow window\r
468         // and filters errors to make sure the window is visible when\r
469         // an error is logged.\r
470         ILogUiProvider logAdapter = new ILogUiProvider() {\r
471             public void setDescription(String description) {\r
472                 mLogWindow.setDescription(description);\r
473             }\r
474 \r
475             public void log(String log) {\r
476                 mLogWindow.log(log);\r
477             }\r
478 \r
479             public void logVerbose(String log) {\r
480                 mLogWindow.logVerbose(log);\r
481             }\r
482 \r
483             public void logError(String log) {\r
484                 mLogWindow.logError(log);\r
485 \r
486                 // Run the window visibility check/toggle on the UI thread.\r
487                 // Note: at least on Windows, it seems ok to check for the window visibility\r
488                 // on a sub-thread but that doesn't seem cross-platform safe. We shouldn't\r
489                 // have a lot of error logging, so this should be acceptable. If not, we could\r
490                 // cache the visibility state.\r
491                 mShell.getDisplay().syncExec(new Runnable() {\r
492                     public void run() {\r
493                         if (!mLogWindow.isVisible()) {\r
494                             // Don't toggle the window visibility directly.\r
495                             // Instead use the same action as the log-toggle button\r
496                             // so that the button's state be kept in sync.\r
497                             onToggleLogWindow();\r
498                         }\r
499                     }\r
500                 });\r
501             }\r
502         };\r
503 \r
504         factory.setProgressView(\r
505                 new ProgressView(mStatusText, mProgressBar, mButtonStop, logAdapter));\r
506         mUpdaterData.setTaskFactory(factory);\r
507 \r
508         setWindowImage(mShell);\r
509 \r
510         setupSources();\r
511         initializeSettings();\r
512 \r
513         if (mUpdaterData.checkIfInitFailed()) {\r
514             return false;\r
515         }\r
516 \r
517         mUpdaterData.broadcastOnSdkLoaded();\r
518 \r
519         if (mRequestAutoUpdate) {\r
520             mUpdaterData.updateOrInstallAll_WithGUI(\r
521                     null /*selectedArchives*/,\r
522                     false /* includeObsoletes */,\r
523                     mContext == SdkInvocationContext.IDE ?\r
524                             UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT :\r
525                                 UpdaterData.TOOLS_MSG_UPDATED_FROM_SDKMAN);\r
526         }\r
527 \r
528         // Tell the one page its the selected one\r
529         mPkgPage.onPageSelected();\r
530 \r
531         return true;\r
532     }\r
533 \r
534     /**\r
535      * Creates the icon of the window shell.\r
536      *\r
537      * @param shell The shell on which to put the icon\r
538      */\r
539     private void setWindowImage(Shell shell) {\r
540         String imageName = "android_icon_16.png"; //$NON-NLS-1$\r
541         if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) {\r
542             imageName = "android_icon_128.png"; //$NON-NLS-1$\r
543         }\r
544 \r
545         if (mUpdaterData != null) {\r
546             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
547             if (imgFactory != null) {\r
548                 shell.setImage(imgFactory.getImageByName(imageName));\r
549             }\r
550         }\r
551     }\r
552 \r
553     /**\r
554      * Called by the main loop when the window has been disposed.\r
555      */\r
556     private void dispose() {\r
557         mLogWindow.close();\r
558         mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog());\r
559     }\r
560 \r
561     /**\r
562      * Callback called when the window shell is disposed.\r
563      */\r
564     private void onAndroidSdkUpdaterDispose() {\r
565         if (mUpdaterData != null) {\r
566             ImageFactory imgFactory = mUpdaterData.getImageFactory();\r
567             if (imgFactory != null) {\r
568                 imgFactory.dispose();\r
569             }\r
570         }\r
571     }\r
572 \r
573     /**\r
574      * Used to initialize the sources.\r
575      */\r
576     private void setupSources() {\r
577         mUpdaterData.setupDefaultSources();\r
578     }\r
579 \r
580     /**\r
581      * Initializes settings.\r
582      * This must be called after addExtraPages(), which created a settings page.\r
583      * Iterate through all the pages to find the first (and supposedly unique) setting page,\r
584      * and use it to load and apply these settings.\r
585      */\r
586     private void initializeSettings() {\r
587         mSettingsController = mUpdaterData.getSettingsController();\r
588         mSettingsController.loadSettings();\r
589         mSettingsController.applySettings();\r
590     }\r
591 \r
592     private void onToggleLogWindow() {\r
593         // toggle visibility\r
594         mLogWindow.setVisible(!mLogWindow.isVisible());\r
595         mButtonShowLog.setState(mLogWindow.isVisible() ? 1 : 0);\r
596     }\r
597 \r
598     private void onStopSelected() {\r
599         // TODO\r
600     }\r
601 \r
602     private void showRegisteredPage(Purpose purpose) {\r
603         if (mExtraPages == null) {\r
604             return;\r
605         }\r
606 \r
607         Class<? extends UpdaterPage> clazz = null;\r
608 \r
609         for (Pair<Class<? extends UpdaterPage>, Purpose> extraPage : mExtraPages) {\r
610             if (extraPage.getSecond() == purpose) {\r
611                 clazz = extraPage.getFirst();\r
612                 break;\r
613             }\r
614         }\r
615 \r
616         if (clazz != null) {\r
617             PageDialog d = new PageDialog(mShell, clazz, purpose == Purpose.SETTINGS);\r
618             d.open();\r
619         }\r
620     }\r
621 \r
622     private void onAvdManager() {\r
623         ITaskFactory oldFactory = mUpdaterData.getTaskFactory();\r
624 \r
625         try {\r
626             AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1(\r
627                     mShell,\r
628                     mUpdaterData,\r
629                     AvdInvocationContext.SDK_MANAGER);\r
630 \r
631             for (Pair<Class<? extends UpdaterPage>, Purpose> page : mExtraPages) {\r
632                 win.registerPage(page.getFirst(), page.getSecond());\r
633             }\r
634 \r
635             win.open();\r
636         } catch (Exception e) {\r
637             mUpdaterData.getSdkLog().error(e, "AVD Manager window error");\r
638         } finally {\r
639             mUpdaterData.setTaskFactory(oldFactory);\r
640         }\r
641     }\r
642 \r
643     // End of hiding from SWT Designer\r
644     //$hide<<$\r
645 \r
646     // -----\r
647 \r
648     /**\r
649      * Dialog used to display either the About page or the Settings (aka Options) page\r
650      * with a "close" button.\r
651      */\r
652     private class PageDialog extends SwtBaseDialog {\r
653 \r
654         private final Class<? extends UpdaterPage> mPageClass;\r
655         private final boolean mIsSettingsPage;\r
656 \r
657         protected PageDialog(\r
658                 Shell parentShell,\r
659                 Class<? extends UpdaterPage> pageClass,\r
660                 boolean isSettingsPage) {\r
661             super(parentShell, SWT.APPLICATION_MODAL, null /*title*/);\r
662             mPageClass = pageClass;\r
663             mIsSettingsPage = isSettingsPage;\r
664         }\r
665 \r
666         @Override\r
667         protected void createContents() {\r
668             Shell shell = getShell();\r
669             setWindowImage(shell);\r
670 \r
671             GridLayoutBuilder.create(shell).columns(2);\r
672 \r
673             UpdaterPage content = UpdaterPage.newInstance(\r
674                     mPageClass,\r
675                     shell,\r
676                     SWT.NONE,\r
677                     mUpdaterData.getSdkLog());\r
678             GridDataBuilder.create(content).fill().grab().hSpan(2);\r
679             if (content.getLayout() instanceof GridLayout) {\r
680                 GridLayout gl = (GridLayout) content.getLayout();\r
681                 gl.marginHeight = gl.marginWidth = 0;\r
682             }\r
683 \r
684             if (mIsSettingsPage && content instanceof ISettingsPage) {\r
685                 mSettingsController.setSettingsPage((ISettingsPage) content);\r
686             }\r
687 \r
688             getShell().setText(\r
689                     String.format("%1$s - %2$s", APP_NAME, content.getPageTitle()));\r
690 \r
691             Label filler = new Label(shell, SWT.NONE);\r
692             GridDataBuilder.create(filler).hFill().hGrab();\r
693 \r
694             Button close = new Button(shell, SWT.PUSH);\r
695             close.setText("Close");\r
696             GridDataBuilder.create(close);\r
697             close.addSelectionListener(new SelectionAdapter() {\r
698                 @Override\r
699                 public void widgetSelected(SelectionEvent e) {\r
700                     close();\r
701                 }\r
702             });\r
703         }\r
704 \r
705         @Override\r
706         protected void postCreate() {\r
707             // pass\r
708         }\r
709 \r
710         @Override\r
711         protected void close() {\r
712             if (mIsSettingsPage) {\r
713                 mSettingsController.setSettingsPage(null);\r
714             }\r
715             super.close();\r
716         }\r
717     }\r
718 }\r