2 * Copyright (C) 2011 The Android Open Source Project
\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
8 * http://www.apache.org/licenses/LICENSE-2.0
\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
17 package com.android.sdkuilib.internal.repository.sdkman2;
\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
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
65 import java.util.ArrayList;
\r
68 * This is the private implementation of the UpdateWindow
\r
69 * for the second version of the SDK Manager.
\r
71 * This window features only one embedded page, the combined installed+available package list.
\r
73 public class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow {
\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
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
88 // --- UI members ---
\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
100 * Creates a new window. Caller must call open(), which will block.
\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
108 public SdkUpdaterWindowImpl2(
\r
112 SdkInvocationContext context) {
\r
113 mParentShell = parentShell;
\r
114 mContext = context;
\r
115 mUpdaterData = new UpdaterData(osSdkRoot, sdkLog);
\r
119 * Creates a new window. Caller must call open(), which will block.
\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
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
129 public SdkUpdaterWindowImpl2(
\r
131 UpdaterData updaterData,
\r
132 SdkInvocationContext context) {
\r
133 mParentShell = parentShell;
\r
134 mContext = context;
\r
135 mUpdaterData = updaterData;
\r
139 * Opens the window.
\r
140 * @wbp.parser.entryPoint
\r
142 public void open() {
\r
143 if (mParentShell == null) {
\r
144 Display.setAppName(APP_NAME); //$hide$ (hide from SWT designer)
\r
148 preCreateContent();
\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
164 dispose(); //$hide$
\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
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
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
190 mShell.setMinimumSize(new Point(500, 300));
\r
191 mShell.setSize(700, 500);
\r
192 mShell.setText(APP_NAME);
\r
194 ShellSizeAndPos.loadSizeAndPos(mShell, SIZE_POS_PREFIX);
\r
197 private void createContents() {
\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
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
206 mProgressBar = new ProgressBar(composite1, SWT.NONE);
\r
207 mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
\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
213 Composite composite2 = new Composite(mShell, SWT.NONE);
\r
214 composite2.setLayout(new GridLayout(2, false));
\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
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
239 private void createMenuBar() {
\r
241 Menu menuBar = new Menu(mShell, SWT.BAR);
\r
242 mShell.setMenuBar(menuBar);
\r
244 MenuItem menuBarPackages = new MenuItem(menuBar, SWT.CASCADE);
\r
245 menuBarPackages.setText("Packages");
\r
247 Menu menuPkgs = new Menu(menuBarPackages);
\r
248 menuBarPackages.setMenu(menuPkgs);
\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
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
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
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
278 new MenuItem(menuPkgs, SWT.SEPARATOR);
\r
280 MenuItem sortByApi = new MenuItem(menuPkgs,
\r
281 MenuAction.SORT_API_LEVEL.getMenuStyle());
\r
283 MenuAction.SORT_API_LEVEL.getMenuTitle());
\r
284 mPkgPage.registerMenuAction(
\r
285 MenuAction.SORT_API_LEVEL, sortByApi);
\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
294 new MenuItem(menuPkgs, SWT.SEPARATOR);
\r
296 MenuItem reload = new MenuItem(menuPkgs,
\r
297 MenuAction.RELOAD.getMenuStyle());
\r
299 MenuAction.RELOAD.getMenuTitle());
\r
300 mPkgPage.registerMenuAction(
\r
301 MenuAction.RELOAD, reload);
\r
303 MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE);
\r
304 menuBarTools.setText("Tools");
\r
306 Menu menuTools = new Menu(menuBarTools);
\r
307 menuBarTools.setMenu(menuTools);
\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
314 public void widgetSelected(SelectionEvent event) {
\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
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
335 new MenuBarWrapper(APP_NAME, menuTools) {
\r
337 public void onPreferencesMenuSelected() {
\r
338 showRegisteredPage(Purpose.SETTINGS);
\r
342 public void onAboutMenuSelected() {
\r
343 showRegisteredPage(Purpose.ABOUT_BOX);
\r
347 public void printError(String format, Object... args) {
\r
348 if (mUpdaterData != null) {
\r
349 mUpdaterData.getSdkLog().error(null, format, args);
\r
353 } catch (Exception e) {
\r
354 mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar");
\r
355 e.printStackTrace();
\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
371 * Creates the log window.
\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
377 private void createLogWindow() {
\r
378 mLogWindow = new LogWindow(mShell,
\r
379 mContext == SdkInvocationContext.IDE ? mUpdaterData.getSdkLog() : null);
\r
384 // -- Start of internal part ----------
\r
385 // Hide everything down-below from SWT designer
\r
388 // --- Public API -----------
\r
392 * Registers an extra page for the updater window.
\r
394 * Pages must derive from {@link Composite} and implement a constructor that takes
\r
395 * a single parent {@link Composite} argument.
\r
397 * All pages must be registered before the call to {@link #open()}.
\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
402 @SuppressWarnings("unchecked")
\r
403 public void registerPage(Class<? extends UpdaterPage> pageClass,
\r
405 if (mExtraPages == null) {
\r
406 mExtraPages = new ArrayList<Pair<Class<? extends UpdaterPage>, Purpose>>();
\r
408 Pair<?, Purpose> value = Pair.of(pageClass, purpose);
\r
409 mExtraPages.add((Pair<Class<? extends UpdaterPage>, Purpose>) value);
\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
417 public void setInitialPage(Class<? extends Composite> pageClass) {
\r
418 // Unused in this case. This window display only one page.
\r
422 * Sets whether the auto-update wizard will be shown when opening the window.
\r
424 * This must be called before the call to {@link #open()}.
\r
426 public void setRequestAutoUpdate(boolean requestAutoUpdate) {
\r
427 mRequestAutoUpdate = requestAutoUpdate;
\r
431 * Adds a new listener to be notified when a change is made to the content of the SDK.
\r
433 public void addListener(ISdkChangeListener listener) {
\r
434 mUpdaterData.addListeners(listener);
\r
438 * Removes a new listener to be notified anymore when a change is made to the content of
\r
441 public void removeListener(ISdkChangeListener listener) {
\r
442 mUpdaterData.removeListener(listener);
\r
445 // --- Internals & UI Callbacks -----------
\r
448 * Called before the UI is created.
\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
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
462 * Returns true if we should show the window.
\r
464 private boolean postCreateContent() {
\r
465 ProgressViewFactory factory = new ProgressViewFactory();
\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
475 public void log(String log) {
\r
476 mLogWindow.log(log);
\r
479 public void logVerbose(String log) {
\r
480 mLogWindow.logVerbose(log);
\r
483 public void logError(String log) {
\r
484 mLogWindow.logError(log);
\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
504 factory.setProgressView(
\r
505 new ProgressView(mStatusText, mProgressBar, mButtonStop, logAdapter));
\r
506 mUpdaterData.setTaskFactory(factory);
\r
508 setWindowImage(mShell);
\r
511 initializeSettings();
\r
513 if (mUpdaterData.checkIfInitFailed()) {
\r
517 mUpdaterData.broadcastOnSdkLoaded();
\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
528 // Tell the one page its the selected one
\r
529 mPkgPage.onPageSelected();
\r
535 * Creates the icon of the window shell.
\r
537 * @param shell The shell on which to put the icon
\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
545 if (mUpdaterData != null) {
\r
546 ImageFactory imgFactory = mUpdaterData.getImageFactory();
\r
547 if (imgFactory != null) {
\r
548 shell.setImage(imgFactory.getImageByName(imageName));
\r
554 * Called by the main loop when the window has been disposed.
\r
556 private void dispose() {
\r
557 mLogWindow.close();
\r
558 mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog());
\r
562 * Callback called when the window shell is disposed.
\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
574 * Used to initialize the sources.
\r
576 private void setupSources() {
\r
577 mUpdaterData.setupDefaultSources();
\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
586 private void initializeSettings() {
\r
587 mSettingsController = mUpdaterData.getSettingsController();
\r
588 mSettingsController.loadSettings();
\r
589 mSettingsController.applySettings();
\r
592 private void onToggleLogWindow() {
\r
593 // toggle visibility
\r
594 mLogWindow.setVisible(!mLogWindow.isVisible());
\r
595 mButtonShowLog.setState(mLogWindow.isVisible() ? 1 : 0);
\r
598 private void onStopSelected() {
\r
602 private void showRegisteredPage(Purpose purpose) {
\r
603 if (mExtraPages == null) {
\r
607 Class<? extends UpdaterPage> clazz = null;
\r
609 for (Pair<Class<? extends UpdaterPage>, Purpose> extraPage : mExtraPages) {
\r
610 if (extraPage.getSecond() == purpose) {
\r
611 clazz = extraPage.getFirst();
\r
616 if (clazz != null) {
\r
617 PageDialog d = new PageDialog(mShell, clazz, purpose == Purpose.SETTINGS);
\r
622 private void onAvdManager() {
\r
623 ITaskFactory oldFactory = mUpdaterData.getTaskFactory();
\r
626 AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1(
\r
629 AvdInvocationContext.SDK_MANAGER);
\r
631 for (Pair<Class<? extends UpdaterPage>, Purpose> page : mExtraPages) {
\r
632 win.registerPage(page.getFirst(), page.getSecond());
\r
636 } catch (Exception e) {
\r
637 mUpdaterData.getSdkLog().error(e, "AVD Manager window error");
\r
639 mUpdaterData.setTaskFactory(oldFactory);
\r
643 // End of hiding from SWT Designer
\r
649 * Dialog used to display either the About page or the Settings (aka Options) page
\r
650 * with a "close" button.
\r
652 private class PageDialog extends SwtBaseDialog {
\r
654 private final Class<? extends UpdaterPage> mPageClass;
\r
655 private final boolean mIsSettingsPage;
\r
657 protected PageDialog(
\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
667 protected void createContents() {
\r
668 Shell shell = getShell();
\r
669 setWindowImage(shell);
\r
671 GridLayoutBuilder.create(shell).columns(2);
\r
673 UpdaterPage content = UpdaterPage.newInstance(
\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
684 if (mIsSettingsPage && content instanceof ISettingsPage) {
\r
685 mSettingsController.setSettingsPage((ISettingsPage) content);
\r
688 getShell().setText(
\r
689 String.format("%1$s - %2$s", APP_NAME, content.getPageTitle()));
\r
691 Label filler = new Label(shell, SWT.NONE);
\r
692 GridDataBuilder.create(filler).hFill().hGrab();
\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
699 public void widgetSelected(SelectionEvent e) {
\r
706 protected void postCreate() {
\r
711 protected void close() {
\r
712 if (mIsSettingsPage) {
\r
713 mSettingsController.setSettingsPage(null);
\r