org.eclipse.epp.internal.mpc.ui.wizards.ItemButtonController.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.epp.internal.mpc.ui.wizards.ItemButtonController.java

Source

/*******************************************************************************
 * Copyright (c) 2010 The Eclipse Foundation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    The Eclipse Foundation - initial API and implementation
 *    Yatta Solutions - bug 432803: public API
 *******************************************************************************/
package org.eclipse.epp.internal.mpc.ui.wizards;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.eclipse.epp.internal.mpc.ui.catalog.MarketplaceNodeCatalogItem;
import org.eclipse.epp.mpc.ui.Operation;
import org.eclipse.equinox.internal.p2.discovery.model.CatalogItem;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;

/**
 * A controller that controls the multi-state install/uninstall button
 *
 * @author David Green
 */
@SuppressWarnings("rawtypes")
class ItemButtonController {
    private enum ButtonState {
        INSTALL(Messages.ItemButtonController_install, Operation.NONE, false), //
        UNINSTALL(Messages.ItemButtonController_uninstall, Operation.NONE, false), //
        INSTALL_PENDING(Messages.ItemButtonController_installPending, Operation.INSTALL, false), //
        UNINSTALL_PENDING(Messages.ItemButtonController_uninstallPending, Operation.UNINSTALL, false), //
        DISABLED(Messages.ItemButtonController_install, Operation.NONE, true), //
        UPDATE_DISABLED(Messages.ItemButtonController_update, Operation.NONE, true), //
        UPDATE(Messages.ItemButtonController_update, Operation.NONE, false), //
        UPDATE_PENDING(Messages.ItemButtonController_updatePending, Operation.UPDATE, false), //
        CHANGE(Messages.ItemButtonController_change, Operation.NONE, false), //
        CHANGE_PENDING(Messages.ItemButtonController_changePending, Operation.CHANGE, false);

        final String label;

        private final Operation operation;

        private final boolean disabled;

        private ButtonState(String label, Operation operation, boolean disabled) {
            this.label = label;
            this.operation = operation;
            this.disabled = disabled;
        }

        public ButtonState nextState() {
            switch (this) {
            case INSTALL:
                return INSTALL_PENDING;
            case INSTALL_PENDING:
                return INSTALL;
            case UNINSTALL:
                return UNINSTALL_PENDING;
            case UNINSTALL_PENDING:
                return UNINSTALL;
            case UPDATE:
                return UPDATE_PENDING;
            case UPDATE_PENDING:
                return UPDATE;
            case CHANGE:
                return CHANGE_PENDING;
            case CHANGE_PENDING:
                return CHANGE;
            }
            return this;
        }

        public ButtonState noActionState() {
            switch (this) {
            case INSTALL_PENDING:
                return INSTALL;
            case UNINSTALL_PENDING:
                return UNINSTALL;
            case UPDATE_PENDING:
                return UPDATE;
            case CHANGE_PENDING:
                return CHANGE;
            }
            return this;
        }

    }

    private final DiscoveryItem item;

    private final DropDownButton button;

    private ButtonState primaryState;

    private List<ButtonState> selectableStates;

    private final Menu menu;

    @SuppressWarnings("unused")
    private final MarketplaceViewer viewer;

    public ItemButtonController(MarketplaceViewer marketplaceViewer, DiscoveryItem discoveryItem,
            DropDownButton button) {
        this.item = discoveryItem;
        this.button = button;
        this.viewer = marketplaceViewer;

        updateButtonState();
        menu = createMenu(button.getButton());
        updateAppearance();
        button.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (e.detail == SWT.ARROW) {
                    menuClicked();
                } else {
                    buttonClicked(primaryState);
                }
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                widgetSelected(e);
            }
        });
    }

    private Menu createMenu(Button button) {
        final Menu menu = new Menu(button);
        createMenuItems(menu);
        button.addDisposeListener(new DisposeListener() {

            public void widgetDisposed(DisposeEvent e) {
                menu.dispose();
            }
        });
        return menu;
    }

    private void createMenuItems(Menu menu) {
        if (selectableStates != null) {
            for (ButtonState state : selectableStates) {
                MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
                menuItem.setData(state);
                menuItem.setText(state.label);
                menuItem.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent e) {
                        buttonClicked((ButtonState) e.widget.getData());
                    }
                });
            }
        }
    }

    private void updateMenuItems() {
        MenuItem[] items = menu.getItems();
        for (MenuItem menuItem : items) {
            menuItem.dispose();
        }
        createMenuItems(menu);
    }

    private void menuClicked() {
        List<ButtonState> selectableStates = getSelectableStates();
        if (selectableStates.isEmpty()) {
            buttonClicked(primaryState);
            return;
        }
        Rectangle rect = button.getButton().getBounds();
        Point p = button.getButton().toDisplay(rect.x, rect.y + rect.height);
        menu.setLocation(p.x - rect.x, p.y - rect.y);
        menu.setVisible(true);
    }

    private void buttonClicked(ButtonState primary) {
        if (primary != ButtonState.DISABLED) {
            primary = primary.nextState();
            item.maybeModifySelection(primary.operation);
        }
        refresh();
    }

    private void updateButtonState() {
        primaryState = ButtonState.DISABLED;
        MarketplaceNodeCatalogItem catalogItem = (MarketplaceNodeCatalogItem) item.getData();
        if (catalogItem.getInstallableUnits().isEmpty()) {
            primaryState = ButtonState.DISABLED;
        } else {
            Operation operation = item.getSelectedOperation();
            boolean installed = isItemInstalled();
            selectableStates = Collections.emptyList();
            if (installed) {
                switch (operation) {
                case UPDATE:
                    primaryState = ButtonState.UPDATE_PENDING;
                    break;
                case UNINSTALL:
                    primaryState = ButtonState.UNINSTALL_PENDING;
                    break;
                case CHANGE:
                    primaryState = ButtonState.CHANGE_PENDING;
                    break;
                case NONE:
                    primaryState = ButtonState.UPDATE;
                    if (hasUpdateAvailable()) {
                        selectableStates = hasOptionalFeatures()
                                ? Arrays.asList(ButtonState.CHANGE, ButtonState.UNINSTALL)
                                : Collections.singletonList(ButtonState.UNINSTALL);
                    } else {
                        primaryState = hasOptionalFeatures() ? ButtonState.CHANGE : ButtonState.UNINSTALL;
                        selectableStates = hasOptionalFeatures() ? Collections.singletonList(ButtonState.UNINSTALL)
                                : Collections.<ButtonState>emptyList();
                    }
                    break;
                }
            } else {
                switch (operation) {
                case INSTALL:
                    primaryState = ButtonState.INSTALL_PENDING;
                    break;
                case NONE:
                    primaryState = ButtonState.INSTALL;
                    break;
                }
                if (!isItemAvailable()) {
                    primaryState = ButtonState.DISABLED;
                }
            }
        }
    }

    private List<ButtonState> getSelectableStates() {
        if (selectableStates == null) {
            updateButtonState();
        }
        return selectableStates;
    }

    private boolean hasUpdateAvailable() {
        Boolean available = ((MarketplaceNodeCatalogItem) item.getData()).getUpdateAvailable();
        return available == null || available.booleanValue();
    }

    private boolean hasOptionalFeatures() {
        Boolean optional = ((MarketplaceNodeCatalogItem) item.getData()).getHasOptionalFeatures();
        return isItemInstalled() && (optional == null || optional.booleanValue());
    }

    private boolean isItemInstalled() {
        return ((CatalogItem) item.getData()).isInstalled();
    }

    private boolean isItemAvailable() {
        Boolean available = ((CatalogItem) item.getData()).getAvailable();
        return available == null || available;
    }

    private void updateAppearance() {
        boolean relayout = false;
        Button control = button.getButton();
        if (!primaryState.label.equals(button.getText())) {
            if (primaryState == ButtonState.INSTALL) { //bold
                button.setFont(JFaceResources.getFontRegistry().getBold("")); //$NON-NLS-1$
            } else if (primaryState.noActionState() == primaryState) { // no "pending" state
                button.setFont(JFaceResources.getFontRegistry().defaultFont());
            } else { //"pending" state - italic
                button.setFont(JFaceResources.getFontRegistry().getItalic("")); //$NON-NLS-1$
            }
            button.setText(primaryState.label);

            Point preferredSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT);
            int preferredWidth = preferredSize.x + 10;//Give a bit of extra padding for bold or italic font
            ((GridData) control.getLayoutData()).minimumWidth = preferredWidth;

            relayout = true;
        }
        control.setEnabled(!primaryState.disabled);
        // button image? Due to platform limitations we can't set the button color

        boolean menu = !getSelectableStates().isEmpty();
        if (menu != button.isShowArrow()) {
            relayout = true;
            button.setShowArrow(menu);
        }
        if (relayout) {
            item.layout(true, false);
        }
    }

    public void refresh() {
        updateButtonState();
        updateMenuItems();
        updateAppearance();
    }

}