nl.mpi.tg.eg.experiment.client.view.ComplexView.java Source code

Java tutorial

Introduction

Here is the source code for nl.mpi.tg.eg.experiment.client.view.ComplexView.java

Source

/*
 * Copyright (C) 2015 Language In Interaction
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package nl.mpi.tg.eg.experiment.client.view;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;
//import com.google.gwt.event.dom.client.DragStartEvent;
//import com.google.gwt.event.dom.client.DragStartHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ButtonBase;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InsertPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import nl.mpi.tg.eg.experiment.client.Messages;
import nl.mpi.tg.eg.experiment.client.listener.PresenterEventListner;
import nl.mpi.tg.eg.experiment.client.listener.SingleShotEventListner;
import nl.mpi.tg.eg.experiment.client.listener.StimulusButton;
import nl.mpi.tg.eg.experiment.client.listener.TouchInputCapture;

/**
 * @since Jan 8, 2015 5:01:05 PM (creation date)
 * @author Peter Withers <p.withers@psych.ru.nl>
 */
public class ComplexView extends SimpleView {

    private Label recordingLabel = null;
    private HorizontalPanel horizontalPanel = null;
    private VerticalPanel regionPanel = null;
    private final HashMap<String, VerticalPanel> regionPanels = new HashMap<>();
    private final ArrayList<FlexTable> gridPanelList = new ArrayList<>();
    private final ArrayList<VerticalPanel> cellPanelList = new ArrayList<>();

    private class ImageEntry {

        final Element imageElement;
        final int percentOfPage;

        public ImageEntry(final Element imageElement, int percentOfPage) {
            this.imageElement = imageElement;
            this.percentOfPage = percentOfPage;
        }

    }

    protected final Messages messages = GWT.create(Messages.class);
    final protected VerticalPanel outerPanel;
    final ArrayList<HandlerRegistration> domHandlerArray = new ArrayList<>();
    private final ArrayList<ImageEntry> scaledImagesList = new ArrayList<>();

    public ComplexView() {
        super();
        outerPanel = new VerticalPanel();
        //
        //        outerPanel.getElement().setDraggable(Element.DRAGGABLE_TRUE);
        //        outerPanel.addDragStartHandler(new DragStartHandler() {
        //
        //            @Override
        //            public void onDragStart(DragStartEvent event) {
        //                // TODO Auto-generated method stub
        //                event.setData("text", "i am widget1");
        //            }
        //        ;
        //        });
        setContent(outerPanel);
    }

    private void clearAllRegions() {
        regionPanels.clear();
        regionPanel = null;
    }

    public void startRegion(final String regionId, final String styleName) {
        VerticalPanel regionTemp = regionPanels.get(regionId);
        if (regionTemp == null) {
            regionTemp = new VerticalPanel();
            regionPanels.put(regionId, regionTemp);
        }
        if (regionTemp.getParent() == null) {
            getActivePanel().add(regionTemp);
        }
        if (regionTemp != null) {
            regionTemp.setStyleName(styleName);
        }
        regionPanel = regionTemp;
    }

    public void endRegion() {
        regionPanel = null;
    }

    public void setRegionStyle(final String regionId, final String styleName) {
        VerticalPanel regionTemp = regionPanels.get(regionId);
        if (regionTemp != null) {
            regionTemp.setStyleName(styleName);
        }
    }

    public void clearRegion(final String regionId) {
        VerticalPanel regionTemp = regionPanels.get(regionId);
        if (regionTemp != null) {
            regionTemp.clear();
        }
    }

    public FlexTable gridPanel() {
        final int index = gridPanelList.size() - 1;
        return (index >= 0) ? gridPanelList.get(index) : null;
    }

    public VerticalPanel cellPanel() {
        // a cell can exist outside a table in some older experiments, so we keep one outer cell in relation to the gridPanelList
        return (cellPanelList.size() > gridPanelList.size()) ? cellPanelList.get(gridPanelList.size()) : null;
    }

    public void startCell(String styleName) {
        VerticalPanel cellPanel = new VerticalPanel();
        cellPanelList.set(gridPanelList.size(), cellPanel);
        if (styleName != null && !styleName.isEmpty()) {
            cellPanel.addStyleName(styleName);
        }
        cellPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
        if (gridPanel() != null) {
            gridPanel().addCell(gridPanel().getRowCount() - 1);
            gridPanel().setWidget(gridPanel().getRowCount() - 1,
                    gridPanel().getCellCount(gridPanel().getRowCount() - 1) - 1, cellPanel);
        } else {
            horizontalPanel.add(cellPanel);
        }
    }

    public void endCell() {
        cellPanelList.set(gridPanelList.size(), null);
    }

    public void startRow() {
        if (gridPanel() != null) {
            gridPanel().insertRow(gridPanel().getRowCount());
        } else {
            startHorizontalPanel();
        }
    }

    public void endRow() {
        if (gridPanel() == null) {
            endHorizontalPanel();
        }
    }

    public Widget startTable(final String styleName) {
        FlexTable gridPanel = new FlexTable();
        if (styleName != null && !styleName.isEmpty()) {
            gridPanel.addStyleName(styleName);
        }
        getActivePanel().add(gridPanel);
        gridPanelList.add(gridPanel);
        while (cellPanelList.size() < gridPanelList.size() + 1) {
            cellPanelList.add(null);
        }
        return gridPanel();
    }

    public void endTable() {
        cellPanelList.set(gridPanelList.size(), null);
        gridPanelList.remove(gridPanelList.size() - 1);
    }

    public void startHorizontalPanel() {
        horizontalPanel = new HorizontalPanel();
        horizontalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
        outerPanel.add(horizontalPanel);
    }

    public void endHorizontalPanel() {
        horizontalPanel = null;
    }

    protected InsertPanel.ForIsWidget getActivePanel() {
        return (regionPanel != null) ? regionPanel
                : (cellPanel() != null) ? cellPanel() : (horizontalPanel != null) ? horizontalPanel : outerPanel;
    }

    public void clearPageAndTimers(String styleName) {
        outerPanel.clear();
        if (styleName != null && !styleName.isEmpty()) {
            outerPanel.setStyleName(styleName);
        } else {
            outerPanel.setStyleName("contentBody");
        }
        removeFooterButtons();
        clearDomHandlers();
        scaledImagesList.clear();
        clearAllRegions();
    }

    public void addText(String textString) {
        HTML html = new HTML(new SafeHtmlBuilder().appendEscapedLines(textString).toSafeHtml());
        getActivePanel().add(html);
    }

    public HTML addHtmlText(String textString, String styleName) {
        HTML html = new HTML(new SafeHtmlBuilder().appendHtmlConstant(textString).toSafeHtml());
        if (styleName != null && !styleName.isEmpty()) {
            html.addStyleName(styleName);
        }
        getActivePanel().add(html);
        return html;
    }

    //    public HTML addHighlightedText(String textString) {
    //        HTML html = new HTML(new SafeHtmlBuilder().appendEscapedLines(textString).toSafeHtml());
    //        html.addStyleName("highlightedText");
    //        getActivePanel().add(html);
    //        return html;
    //    }
    public void addPadding() {
        getActivePanel().add(new HTML("&nbsp;"));
    }

    public void setRecorderState(String message, boolean isRecording) {
        if (recordingLabel == null) {
            recordingLabel = new Label();
        }
        recordingLabel.setStyleName((isRecording) ? "recordingLabel" : "notRecordingLabel");
        if (isRecording || message != null) {
            recordingLabel.setText((message != null && !message.isEmpty()) ? message : "");
            outerPanel.add(recordingLabel);
        } else {
            outerPanel.remove(recordingLabel);
        }
    }

    public void addWidget(IsWidget isWidget) {
        getActivePanel().add(isWidget);
    }

    protected void addSizeAttributes(final Element imageElement, int percentOfPage, int maxHeight, int maxWidth) {
        imageElement.getStyle().setProperty("imageOrientation", "from-image"); // the image-orientation style is not supported by most browsers yet
        if (percentOfPage > 0) {
            scaledImagesList.add(new ImageEntry(imageElement, percentOfPage));
            //            image.getElement().getStyle().setProperty("width", percentOfPage + "%");
            //            image.getElement().getStyle().setProperty("height", "auto");
            resizeImage(imageElement, Window.getClientHeight(), Window.getClientWidth(), percentOfPage);
        } else {
            if (maxWidth > 0) {
                imageElement.getStyle().setProperty("maxWidth", maxWidth + "%");
            }
            if (maxHeight > 0) {
                imageElement.getStyle().setProperty("maxHeight", maxHeight + "%");
            }
        }
    }

    public void addImage(SafeUri imagePath, final SafeUri linkUrl, int percentOfPage, int maxHeight, int maxWidth,
            String align) {
        final Image image = new Image(imagePath);
        addSizeAttributes(image.getElement(), percentOfPage, maxHeight, maxWidth);
        final SingleShotEventListner singleShotEventListner = new SingleShotEventListner() {

            @Override
            protected void singleShotFired() {
                Window.open(linkUrl.asString(), "_system", "");
            }
        };
        image.addClickHandler(singleShotEventListner);
        image.addTouchStartHandler(singleShotEventListner);
        image.addTouchMoveHandler(singleShotEventListner);
        image.addTouchEndHandler(singleShotEventListner);
        getActivePanel().add(image);
    }

    public void centrePage() {
        outerPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
    }

    public void addLink(String label, final String target) {
        final Anchor anchor = new Anchor(new SafeHtmlBuilder().appendEscapedLines(label).toSafeHtml());
        // this link relies on the org.apache.cordova.inappbrowser which offers secure viewing of external html pages and handles user navigation such as back navigation.
        // in this case the link will be opend in the system browser rather than in the cordova application.
        getActivePanel().add(anchor);
        final SingleShotEventListner singleShotEventListner = new SingleShotEventListner() {

            @Override
            protected void singleShotFired() {
                Window.open(target, "_system", "");
            }
        };
        anchor.addClickHandler(singleShotEventListner);
        anchor.addTouchStartHandler(singleShotEventListner);
        anchor.addTouchMoveHandler(singleShotEventListner);
        anchor.addTouchEndHandler(singleShotEventListner);
        anchor.addStyleName("pageLink");
    }

    public StimulusButton addOptionButton(final PresenterEventListner presenterListener) {
        StimulusButton nextButton = getOptionButton(presenterListener);
        if (presenterListener.getStyleName() != null && !presenterListener.getStyleName().isEmpty()) {
            nextButton.addStyleName(presenterListener.getStyleName());
        }
        getActivePanel().add(nextButton.getWidget());
        return nextButton;
    }

    public StimulusButton addFooterButton(final PresenterEventListner presenterListener) {
        StimulusButton nextButton = getOptionButton(presenterListener);
        if (presenterListener.getStyleName() != null && !presenterListener.getStyleName().isEmpty()) {
            nextButton.addStyleName(presenterListener.getStyleName());
        } else {
            nextButton.addStyleName("footerButton");
        }
        addToFooter(nextButton.getWidget());
        return nextButton;
    }

    public List<StimulusButton> addRatingButtons(final List<PresenterEventListner> presenterListeners,
            final String ratingLabelLeft, final String ratingLabelRight, boolean footerButtons, String styleName,
            final String buttonGroupName, final String savedValue, final HorizontalPanel buttonsStylePanel) {
        final ArrayList<StimulusButton> stimulusButtonList = new ArrayList<>();
        final VerticalPanel verticalPanel = new VerticalPanel();
        final HorizontalPanel labelsPanel = new HorizontalPanel();
        if (ratingLabelLeft != null) {
            labelsPanel.add(new Label(ratingLabelLeft));
        }
        if (ratingLabelRight != null) {
            final Label label = new Label(ratingLabelRight);
            labelsPanel.add(label);
            label.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
        }
        final HorizontalPanel buttonsPanel = (buttonsStylePanel != null) ? buttonsStylePanel
                : new HorizontalPanel();
        for (PresenterEventListner listener : presenterListeners) {
            // stimulusRatingRadio needs stimulusFreeText objects to validate them
            StimulusButton nextButton = (buttonGroupName != null)
                    ? getRadioButton(listener, buttonGroupName, savedValue)
                    : getOptionButton(listener);
            if (styleName != null && !styleName.isEmpty()) {
                nextButton.addStyleName(styleName);
            } else if (footerButtons) {
                nextButton.addStyleName("footerButton");
            }
            buttonsPanel.add(nextButton.getWidget());
            buttonsPanel.setCellWidth(nextButton.getWidget(), (100 / presenterListeners.size()) + "%");
            stimulusButtonList.add(nextButton);
        }
        verticalPanel.setWidth("100%");
        labelsPanel.setWidth("100%");
        buttonsPanel.setWidth("100%");
        verticalPanel.add(labelsPanel);
        verticalPanel.add(buttonsPanel);
        if (footerButtons) {
            addToFooter(verticalPanel);
        } else {
            addWidget(verticalPanel);
        }
        return stimulusButtonList;
    }

    public void addTouchInputCapture(TouchInputCapture touchInputCapture) {
        //        RootPanel root = RootPanel.get();
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, TouchStartEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, TouchMoveEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, TouchEndEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, TouchCancelEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, MouseMoveEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, MouseDownEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, MouseUpEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, MouseOutEvent.getType()));
        //        domHandlerArray.add(root.addDomHandler(touchInputCapture, MouseOverEvent.getType()));
        domHandlerArray.add(Event.addNativePreviewHandler(touchInputCapture));
    }

    private void addHotKeyListner(final PresenterEventListner presenterListener,
            final SingleShotEventListner singleShotEventListner) {
        if (presenterListener.getHotKey() > 0) {
            RootPanel root = RootPanel.get();
            domHandlerArray.add(root.addDomHandler(new KeyDownHandler() {
                @Override
                public void onKeyDown(KeyDownEvent event) {
                    final int nativeKeyCode = event.getNativeKeyCode();
                    // we map 190 which is the period key to the numeric period key
                    if (((nativeKeyCode == 190) ? KeyCodes.KEY_NUM_PERIOD : nativeKeyCode) == presenterListener
                            .getHotKey()) {
                        event.stopPropagation();
                        //                        clearDomHandlers();
                        singleShotEventListner.eventFired();
                    }
                }
            }, KeyDownEvent.getType()));
        }
    }

    public StimulusButton getOptionButton(final PresenterEventListner presenterListener) {
        final Button nextButton = new Button(presenterListener.getLabel());
        return configureButton(nextButton, presenterListener);
    }

    public StimulusButton getRadioButton(final PresenterEventListner presenterListener,
            final String buttonGroupName, final String savedValue) {
        final RadioButton nextButton = new RadioButton(buttonGroupName, presenterListener.getLabel());
        nextButton.setValue(presenterListener.getLabel().equals(savedValue));
        return configureButton(nextButton, presenterListener);
    }

    private StimulusButton configureButton(final ButtonBase nextButton,
            final PresenterEventListner presenterListener) {
        nextButton.addStyleName("optionButton");
        nextButton.setEnabled(true);
        final SingleShotEventListner singleShotEventListner = new SingleShotEventListner() {

            @Override
            protected void singleShotFired() {
                if (nextButton.isEnabled()) {
                    nextButton.addStyleName("optionButtonActivated");
                    presenterListener.eventFired(nextButton, this);
                    if (nextButton instanceof RadioButton) {
                        ((RadioButton) nextButton).setValue(Boolean.TRUE);
                    }
                }
                resetSingleShot();
            }
        };
        nextButton.addClickHandler(singleShotEventListner);
        nextButton.addTouchStartHandler(singleShotEventListner);
        nextButton.addTouchMoveHandler(singleShotEventListner);
        nextButton.addTouchEndHandler(singleShotEventListner);
        addHotKeyListner(presenterListener, singleShotEventListner);
        return new StimulusButton() {

            @Override
            public Widget getWidget() {
                return nextButton;
            }

            @Override
            public void addStyleName(String styleName) {
                if (styleName != null && !styleName.isEmpty()) {
                    nextButton.addStyleName(styleName);
                }
            }

            @Override
            public void removeStyleName(String styleName) {
                nextButton.removeStyleName(styleName);
            }

            @Override
            public void setEnabled(boolean enabled) {
                nextButton.setEnabled(enabled);
            }

            @Override
            public boolean isEnabled() {
                return nextButton.isEnabled();
            }

            @Override
            public void setVisible(boolean visible) {
                nextButton.setVisible(visible);
            }

            @Override
            public void triggerSingleShotEventListner() {
                singleShotEventListner.eventFired();
            }
        };
    }

    public void clearDomHandlers() {
        // todo: make sure this is cleared before the screen exits
        for (HandlerRegistration domHandler : domHandlerArray) {
            domHandler.removeHandler();
        }
        domHandlerArray.clear();
    }

    public StimulusButton addImageButton(final PresenterEventListner presenterListener, final SafeUri imagePath,
            final boolean isTouchZone) {
        final Image image = new Image(imagePath);
        final Button imageButton = new Button();
        imageButton.getElement().appendChild(image.getElement());
        if (presenterListener.getStyleName() != null && !presenterListener.getStyleName().isEmpty()) {
            image.addStyleName(presenterListener.getStyleName());
        }
        imageButton.addStyleName(
                (presenterListener.getStyleName() == null || presenterListener.getStyleName().isEmpty())
                        ? "imageButton"
                        : presenterListener.getStyleName());
        getActivePanel().add(imageButton);
        final SingleShotEventListner singleShotEventListner = new SingleShotEventListner() {

            @Override
            protected void singleShotFired() {
                if (imageButton.isEnabled()) {
                    presenterListener.eventFired(imageButton, this);
                }
                resetSingleShot();
            }
        };
        if (!isTouchZone) {
            imageButton.setEnabled(true);
            imageButton.addClickHandler(singleShotEventListner);
            imageButton.addTouchStartHandler(singleShotEventListner);
            imageButton.addTouchMoveHandler(singleShotEventListner);
            imageButton.addTouchEndHandler(singleShotEventListner);
            addHotKeyListner(presenterListener, singleShotEventListner);
        } else {
            // setting this to false breaks the touch input capture
            //            imageButton.setEnabled(false);
        }
        final StimulusButton stimulusButton = new StimulusButton() {
            boolean isEnabled = true;

            @Override
            public Widget getWidget() {
                return imageButton;
            }

            @Override
            public void addStyleName(String styleName) {
                if (styleName != null && !styleName.isEmpty()) {
                    imageButton.addStyleName(styleName);
                    image.addStyleName(styleName);
                }
            }

            @Override
            public void removeStyleName(String styleName) {
                imageButton.removeStyleName(styleName);
                image.removeStyleName(styleName);
            }

            @Override
            public void setEnabled(boolean enabled) {
                isEnabled = enabled;
                if (!isTouchZone) {
                    imageButton.setEnabled(enabled);
                }
            }

            @Override
            public boolean isEnabled() {
                return isEnabled;
            }

            @Override
            public void setVisible(boolean visible) {
                imageButton.setVisible(visible);
            }

            @Override
            public void triggerSingleShotEventListner() {
                if (isEnabled) {
                    if (isTouchZone) {
                        presenterListener.eventFired(imageButton, null);
                    } else {
                        singleShotEventListner.eventFired();
                    }
                }
            }
        };
        return stimulusButton;
    }

    public HorizontalPanel addProgressBar(int minimum, int value, int maximum) {
        final HorizontalPanel bargraphOuter = new HorizontalPanel();
        final HorizontalPanel bargraphInner = new HorizontalPanel();
        bargraphOuter.setWidth("100%");
        bargraphOuter.setHeight("10px");
        bargraphInner.setWidth((int) (100.0 / maximum * value) + "%");
        bargraphInner.setHeight("10px");
        bargraphOuter.setStyleName("bargraphOuter");
        bargraphInner.setStyleName("bargraphInner");
        bargraphOuter.add(bargraphInner);
        getActivePanel().add(bargraphOuter);
        return bargraphInner;
    }

    public void updateProgressBar(HorizontalPanel bargraphInner, int minimum, int value, int maximum) {
        bargraphInner.setWidth((int) (100.0 / maximum * value) + "%");
    }

    public void showHtmlPopup(String popupText, final PresenterEventListner... buttonListeners) {
        final PopupPanel popupPanel = new PopupPanel(false); // the close action to this panel causes background buttons to be clicked
        popupPanel.setGlassEnabled(true);
        popupPanel.setStylePrimaryName("svgPopupPanel");
        final VerticalPanel popupverticalPanel = new VerticalPanel();
        final HTML htmlText = new HTML(new SafeHtmlBuilder().appendHtmlConstant(popupText).toSafeHtml());
        htmlText.setStylePrimaryName("popupTextBox");
        popupverticalPanel.add(htmlText);

        popupverticalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
        final HorizontalPanel buttonPanel = new HorizontalPanel();
        for (final PresenterEventListner buttonListener : buttonListeners) {
            final SingleShotEventListner okSingleShotEventListner = new SingleShotEventListner() {

                @Override
                protected void singleShotFired() {
                    popupPanel.hide();
                    buttonListener.eventFired(null, null);
                }
            };
            final Button okButton = new Button(buttonListener.getLabel());
            if (buttonListener.getStyleName() != null && !buttonListener.getStyleName().isEmpty()) {
                okButton.addStyleName(buttonListener.getStyleName());
            }
            okButton.addClickHandler(okSingleShotEventListner);
            okButton.addTouchStartHandler(okSingleShotEventListner);
            okButton.addTouchMoveHandler(okSingleShotEventListner);
            okButton.addTouchEndHandler(okSingleShotEventListner);
            buttonPanel.add(okButton);
        }
        popupverticalPanel.add(buttonPanel);
        popupPanel.setWidget(popupverticalPanel);
        popupPanel.setPopupPositionAndShow(new PopupPanel.PositionCallback() {

            @Override
            public void setPosition(int offsetWidth, int offsetHeight) {
                final int topPosition = Window.getClientHeight() / 2 - offsetHeight;
                // topPosition is used to make sure the dialogue is above the half way point on the screen to avoid the software keyboard covering the box
                // topPosition is also checked to make sure it does not show above the top of the page
                popupPanel.setPopupPosition(Window.getClientWidth() / 2 - offsetWidth / 2,
                        (topPosition < 0) ? 0 : topPosition);
            }
        });
    }

    public void addTextField(String value, boolean readOnly) {
        final TextBox textBox = new TextBox();
        textBox.setReadOnly(readOnly);
        textBox.setStylePrimaryName("metadataOK");
        textBox.setText(value);
        getActivePanel().add(textBox);
    }

    @Override
    protected void parentResized(int height, int width, String units) {
        super.parentResized(height, width, units);
        for (ImageEntry imageEntry : scaledImagesList) {
            resizeImage(imageEntry.imageElement, height, width, imageEntry.percentOfPage);
        }
    }

    private void resizeImage(final Element imageElement, int height, int width, int percentOfPage) {
        imageElement.getStyle().clearHeight();
        imageElement.getStyle().clearWidth();
        imageElement.getStyle().setProperty("maxHeight",
                (height - HEADER_SIZE - HEADER_SIZE - 50
                        - 50 /* the  "- 50 - 50" comes from contentBody in the CSS */) * (percentOfPage / 100.0)
                        + "px");
        imageElement.getStyle().setProperty("maxWidth", (width * (percentOfPage / 100.0)) + "px");
    }
}