com.ibm.xsp.extlib.designer.tooling.palette.applicationlayout.AlwStartPage.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.xsp.extlib.designer.tooling.palette.applicationlayout.AlwStartPage.java

Source

/*
 *  Copyright IBM Corp. 2014
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 * implied. See the License for the specific language governing 
 * permissions and limitations under the License.
 */
package com.ibm.xsp.extlib.designer.tooling.palette.applicationlayout;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;

import com.ibm.commons.util.StringUtil;
import com.ibm.designer.domino.navigator.NavigatorPlugin;
import com.ibm.designer.domino.xsp.registry.DesignerExtension;
import com.ibm.designer.domino.xsp.registry.DesignerExtensionUtil;
import com.ibm.xsp.extlib.designer.tooling.ExtLibToolingPlugin;
import com.ibm.xsp.extlib.designer.tooling.annotation.ExtLibLayoutExtension;
import com.ibm.xsp.extlib.designer.tooling.utils.ExtLibRegistryUtil;
import com.ibm.xsp.extlib.designer.tooling.utils.ExtLibToolingLogger;
import com.ibm.xsp.extlib.designer.tooling.utils.WizardUtils;
import com.ibm.xsp.library.StandardRegistryMaintainer;
import com.ibm.xsp.registry.FacesDefinition;
import static com.ibm.xsp.extlib.designer.tooling.constants.IExtLibRegistry.*;

/**
 * @author Gary Marjoram
 *
 */
public class AlwStartPage extends WizardPage implements ControlListener, Listener, SelectionListener {

    private static final int MARGIN = 10;
    private static final int SPACER = 3;
    private static final int DEFAULT_ROWS = 3;
    private static final String SAMPLE_TEXT = "Sample"; // $NLX-AlwStartPage.Sample-1$
    private int _textMargin = 0;
    private List<LayoutConfig> _configList = new ArrayList<LayoutConfig>();
    private Table _table;
    private Button _allRadio;
    private Button _responsiveRadio;
    private Button _nonResponsiveRadio;
    private final Image _defImage;
    private final Image _responsiveImage;
    private final Cursor _handCursor;
    private final Font _titleFont;
    private final Color _hyperlinkColor;
    private final boolean _showResponsiveIcon = false;

    /*
     * Enum for different configuration types
     */
    private static enum ConfigurationType {
        NON_RESPONSIVE, RESPONSIVE, ALL
    };

    /*
     * Constructor
     */
    protected AlwStartPage() {
        super("");
        setTitle("Application Layout"); // $NLX-AlwStartPage.ApplicationLayout-1$
        setMessage("Choose the configuration for this control.", IMessageProvider.INFORMATION); // $NLX-AlwStartPage.Choosetheconfigurationforthiscont-1$

        // Setup the title font
        _titleFont = JFaceResources.getBannerFont();

        // Setup hand cursor
        _handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);

        // Load images - Do not have to be disposed later - plugin maintains a list
        _defImage = ExtLibToolingPlugin.getImage("app_layout.jpg"); // $NON-NLS-1$
        if (_showResponsiveIcon) {
            _responsiveImage = NavigatorPlugin.getImage("navigatorIcons/navigatorChild.png"); // $NON-NLS-1$
        } else {
            _responsiveImage = null;
        }

        // Setup hyperlink color
        _hyperlinkColor = new Color(Display.getCurrent(), 0, 0, 255);
    }

    /*
     * Creates the UI for this wizard page
     */
    @Override
    public void createControl(final Composite parent) {
        // Setup the initial data
        populateConfigurationList();

        Composite container = new Composite(parent, SWT.NONE);
        GridLayout layout = WizardUtils.createGridLayout(1, 5);
        container.setLayout(layout);

        // Create the radio group
        Group group = WizardUtils.createGroup(container, 1, 3);
        (_allRadio = WizardUtils.createRadio(group, "&All", 1, this)).setSelection(true); // $NLX-AlwStartPage.All-1$
        _responsiveRadio = WizardUtils.createRadio(group, "&Responsive", 1, this); // $NLX-AlwStartPage.Responsive-1$
        _nonResponsiveRadio = WizardUtils.createRadio(group, "N&on-Responsive", 1, this); // $NLX-AlwStartPage.NonResponsive-1$

        // Create the table
        _table = new Table(container, SWT.FULL_SELECTION | SWT.BORDER | SWT.V_SCROLL | SWT.NO_SCROLL);
        _table.setHeaderVisible(false);
        _table.setLinesVisible(false);
        GridData gd = new GridData(SWT.DEFAULT);
        gd.horizontalSpan = 1;
        gd.verticalAlignment = GridData.FILL;
        gd.grabExcessVerticalSpace = true;
        gd.horizontalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = true;

        // Set the preferred height (3 rows)
        gd.heightHint = (_defImage.getBounds().height + (MARGIN * 2)) * DEFAULT_ROWS;
        _table.setLayoutData(gd);

        // Add one column
        new TableColumn(_table, SWT.NONE);

        // Add the rows
        refreshTable(ConfigurationType.ALL);

        setControl(container);
        setPageComplete(false);
    }

    /*
     * Reads the registry for app layout configurations
     */
    private void populateConfigurationList() {
        // Find all the app layout configurations
        List<FacesDefinition> list = ExtLibRegistryUtil
                .getConfigNodes(StandardRegistryMaintainer.getStandardRegistry());
        for (FacesDefinition def : list) {
            // Create a new LayoutConfig
            LayoutConfig lc = new LayoutConfig();
            lc.tagName = def.getTagName();
            lc.facesDef = def;

            DesignerExtension de = DesignerExtensionUtil.getExtension(def);
            if (de != null) {
                // There's a <designer-extension>
                lc.title = de.getDisplayName();
                lc.description = de.getDescription();
            }

            ExtLibLayoutExtension le = (ExtLibLayoutExtension) def.getExtension(LAYOUT_EXTENSION);
            if (le != null) {
                // There is a <layout-extension>
                lc.responsive = le.isResponsive();
                lc.sampleURL = le.getSampleURL();
                if (le.getImage() != null) {
                    // Get the image if any
                    ImageDescriptor id = ImageDescriptor.createFromURL(le.getImage());
                    lc.image = id.createImage();
                }
            }

            if (lc.image == null) {
                // If there's no image add a default one
                lc.image = _defImage;
            }

            if (StringUtil.isEmpty(lc.title)) {
                // Use the tagName if there's no title
                lc.title = lc.facesDef.getFirstDefaultPrefix() + ":" + lc.tagName;
            }

            // Add this configuration to the list
            _configList.add(lc);
        }

        // Sort the list
        Collections.sort(_configList, new Comparator<LayoutConfig>() {
            @Override
            public int compare(LayoutConfig lc1, LayoutConfig lc2) {
                return lc1.title.compareToIgnoreCase(lc2.title);
            }
        });
    }

    /*
     * Refreshes the table rows for a particular configuration type
     */
    private void refreshTable(final ConfigurationType ct) {
        _table.setRedraw(false);
        _table.removeAll();
        for (LayoutConfig lc : _configList) {
            boolean addItem = true;
            switch (ct) {
            case RESPONSIVE:
                addItem = lc.responsive;
                break;

            case NON_RESPONSIVE:
                addItem = !lc.responsive;
                break;

            default:
                break;
            }
            if (addItem) {
                new TableItem(_table, SWT.NONE).setData(lc);
                _textMargin = Math.max(_textMargin, getImageWidth(lc.image) + (MARGIN * 2));
            }
        }
        _table.setRedraw(true);
        setPageComplete(false);
    }

    /*
     * Function invoked when the page is about to be displayed or hidden
     */
    @Override
    public void setVisible(final boolean visible) {
        super.setVisible(visible);
        if (visible) {
            // Add the listeners
            _table.addControlListener(this);
            _table.addListener(SWT.MeasureItem, this);
            _table.addListener(SWT.PaintItem, this);
            _table.addListener(SWT.EraseItem, this);
            _table.addListener(SWT.MouseMove, this);
            _table.addListener(SWT.MouseUp, this);
            _table.addSelectionListener(this);
        } else {
            // Remove the listeners
            _table.removeSelectionListener(this);
            _table.removeListener(SWT.MouseUp, this);
            _table.removeListener(SWT.MouseMove, this);
            _table.removeListener(SWT.EraseItem, this);
            _table.removeListener(SWT.PaintItem, this);
            _table.removeListener(SWT.MeasureItem, this);
            _table.removeControlListener(this);
        }
    }

    @Override
    public void controlMoved(final ControlEvent event) {
    }

    /*
     * Function invoked when the dialog is being resized 
     */
    @Override
    public void controlResized(final ControlEvent event) {
        // Make the colum width the full width of the table
        _table.getColumn(0).setWidth(_table.getClientArea().width);
    }

    /*
     * Handles specified table events
     */
    @Override
    public void handleEvent(final Event event) {
        LayoutConfig lc;
        Point pt;
        TableItem item;
        int fullWidth = _table.getClientArea().width;

        switch (event.type) {
        case SWT.MeasureItem:
            lc = (LayoutConfig) event.item.getData();
            // Height is the max of image and text height
            event.height = Math.max(getTextAreaHeight(event.gc, fullWidth, lc), getImageHeight(lc.image))
                    + (MARGIN * 2);
            break;

        case SWT.EraseItem:
            event.detail &= ~SWT.FOREGROUND;
            // Ensure that our only column is dimensioned correctly ->
            // Have to do this here or the table will not display correctly
            // when the wizard is first opened
            if (_table.getColumn(0).getWidth() != _table.getClientArea().width) {
                _table.getColumn(0).setWidth(_table.getClientArea().width);
            }
            break;

        case SWT.PaintItem:
            lc = (LayoutConfig) event.item.getData();
            int textHeight = getTextAreaHeight(event.gc, fullWidth, lc);

            // Draw the image
            if (lc.image != null) {
                int imageOffset = (_textMargin - getImageWidth(lc.image)) / 2;
                event.gc.drawImage(lc.image, imageOffset,
                        event.y + ((event.height - getImageHeight(lc.image)) / 2));
                Rectangle rect = lc.image.getBounds();
                rect.x = imageOffset;
                rect.y = event.y + ((event.height - getImageHeight(lc.image)) / 2);
                event.gc.drawRectangle(rect);
            }

            // Draw the title
            Font origFont = event.gc.getFont();
            event.gc.setFont(_titleFont);
            int y = event.y + ((event.height - textHeight) / 2);
            event.gc.drawText(lc.title, _textMargin, y, true);

            // Draw the rssponsive thumbnail
            if (lc.responsive && _showResponsiveIcon) {
                event.gc.drawImage(_responsiveImage, _textMargin + getTextWidth(event.gc, lc.title) + SPACER, y);
                y += Math.max(getTextHeight(event.gc, "X") + SPACER, getImageHeight(_responsiveImage) + SPACER);
            } else {
                y += getTextHeight(event.gc, "X") + SPACER;
            }

            // Draw the description
            event.gc.setFont(origFont);
            for (String line : getLines(event.gc, lc.description, fullWidth - _textMargin - MARGIN)) {
                event.gc.drawText(line, _textMargin, y, true);
                y += getTextHeight(event.gc, "X");
            }
            y += SPACER;
            int x = _textMargin;

            // Draw the sample-url
            if (lc.sampleURL != null) {
                Color origColor = _table.getForeground();
                event.gc.setForeground(_hyperlinkColor);
                Point extent = event.gc.textExtent(SAMPLE_TEXT);
                event.gc.drawText(SAMPLE_TEXT, x, y, true);
                event.gc.drawLine(x, y + extent.y - 1, x + extent.x, y + extent.y - 1);
                event.gc.setForeground(origColor);
                lc.hyperlinkRect = new Rectangle(x, y, extent.x, extent.y);
            }
            break;

        case SWT.MouseMove:
            pt = new Point(event.x, event.y);
            item = _table.getItem(pt);
            if (item != null) {
                lc = (LayoutConfig) item.getData();

                // Check is mouse over a hyperlink 
                if (lc.hyperlinkRect != null) {
                    if (lc.hyperlinkRect.contains(pt)) {
                        // Change the cursor
                        _table.setCursor(_handCursor);
                        return;
                    }
                }
            }

            // Not over hyperlink, reset the cursor if required
            if (_table.getCursor() == _handCursor) {
                _table.setCursor(null);
            }
            break;

        case SWT.MouseUp:
            // If the cursor is over a hyperlink then launch the browser
            if (_table.getCursor() == _handCursor) {
                pt = new Point(event.x, event.y);
                item = _table.getItem(pt);
                if (item != null) {
                    lc = (LayoutConfig) item.getData();
                    openSampleUrl(lc.sampleURL);
                }
            }
            break;
        }
    }

    /*
     * Calculates the height of the text are for each table row
     */
    protected int getTextAreaHeight(final GC gc, final int fullWidth, final LayoutConfig lc) {
        Font origFont = gc.getFont();

        // Add the title height
        gc.setFont(_titleFont);
        int textHeight = getTextHeight(gc, "X") + SPACER;
        gc.setFont(origFont);
        if (lc.responsive && _showResponsiveIcon) {
            textHeight = Math.max(textHeight, getImageHeight(_responsiveImage) + SPACER);
        }

        // Add the description height
        int lineCount = getLines(gc, lc.description, fullWidth - _textMargin - MARGIN).length;
        textHeight += (lineCount * getTextHeight(gc, "X"));

        // Add in the footer height
        if (lc.sampleURL != null) {
            textHeight += getTextHeight(gc, "X") + SPACER;
        }

        return textHeight;
    }

    /*
     * Utility function to get text width
     */
    public static int getTextWidth(final GC gc, final String txt) {
        return gc.textExtent(txt).x;
    }

    /*
     * Utility function to get text height
     */
    public static int getTextHeight(final GC gc, final String txt) {
        return gc.textExtent(txt).y;
    }

    /*
     * Utility function to get and image width
     */
    public static int getImageWidth(final Image img) {
        if (img != null) {
            return img.getBounds().width;
        }
        return 0;
    }

    /*
     * Utility function to get an image height
     */
    public static int getImageHeight(final Image img) {
        if (img != null) {
            return img.getBounds().height;
        }
        return 0;
    }

    /*
     * Splits text into a number of lnes based on the specified width
     */
    protected static String[] getLines(final GC gc, final String text, final int width) {
        if (text == null) {
            return new String[] {};
        }

        char[] chars = text.toCharArray();
        List<String> lines = new ArrayList<String>();
        StringBuffer line = new StringBuffer();
        StringBuffer word = new StringBuffer();

        for (int i = 0; i < chars.length; i++) {
            // Handle the newline character
            if (chars[i] == '\n') {
                line.append(word);
                word.delete(0, word.length());
                lines.add(line.toString());
                line.delete(0, line.length());
                continue;
            }

            word.append(chars[i]);

            // Check for word boundary
            if (Character.isWhitespace(chars[i])) {
                // Do we need a new line for this word ?
                if (getTextWidth(gc, line.toString() + word.toString()) > width) {
                    // Yes
                    lines.add(line.toString());
                    line.delete(0, line.length());
                }
                line.append(word);
                word.delete(0, word.length());
            }
        }

        // Handle remaining word if any
        if (word.length() > 0) {
            // Do we need a new line for this word
            if (getTextWidth(gc, line.toString() + word.toString()) > width) {
                // Yes
                lines.add(line.toString());
                line.delete(0, line.length());
            }
            line.append(word);
        }

        // Handle remaining line if any
        if (line.length() > 0) {
            lines.add(line.toString());
        }

        return lines.toArray(new String[lines.size()]);
    }

    @Override
    public void widgetDefaultSelected(final SelectionEvent event) {
    }

    /*
     * Handles widget clicks
     */
    @Override
    public void widgetSelected(final SelectionEvent event) {
        if (event.widget == _allRadio) {
            refreshTable(ConfigurationType.ALL);
        } else if (event.widget == _responsiveRadio) {
            refreshTable(ConfigurationType.RESPONSIVE);
        } else if (event.widget == _nonResponsiveRadio) {
            refreshTable(ConfigurationType.NON_RESPONSIVE);
        } else if (event.widget == _table) {
            // User has clicked on a table item, enable the next button
            setPageComplete(true);
        }
        getWizard().getContainer().updateButtons();
    }

    /*
     * Returns the selected layout configuration if any
     */
    public LayoutConfig getSelectedLayoutConfig() {
        TableItem items[] = _table.getSelection();
        if (items.length > 0) {
            return (LayoutConfig) items[0].getData();
        }

        return null;
    }

    /*
     * Opens a URL in the default browser
     */
    public void openSampleUrl(URL url) {
        IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();

        try {
            IWebBrowser browser = support.getExternalBrowser();
            browser.openURL(url);
        } catch (PartInitException e) {
            if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "openSampleUrl", e,
                        "Failed to initialize browser part"); // $NON-NLS-1$ $NLE-AlwStartPage.Failedtoinitializebrowserpart-2$
            }
        } catch (Exception e) {
            if (ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.isErrorEnabled()) {
                ExtLibToolingLogger.EXT_LIB_TOOLING_LOGGER.errorp(this, "openSampleUrl", e,
                        "Failed to launch browser"); // $NON-NLS-1$ $NLE-AlwStartPage.Failedtolaunchbrowser-2$
            }
        }
    }

    @Override
    public void dispose() {
        super.dispose();

        // Dispose all Images
        for (LayoutConfig lc : _configList) {
            if ((lc.image != null) && (!lc.image.isDisposed()) && (lc.image != _defImage)) {
                lc.image.dispose();
            }
        }
    }

    /*
     * Utility class for holding layout configuration info
     */
    public class LayoutConfig {
        public Image image = null;
        public String description = "";
        public URL sampleURL = null;
        public String title = "";
        public String tagName = "";
        public boolean responsive = false;
        public FacesDefinition facesDef = null;
        public Rectangle hyperlinkRect = null;
    }
}