001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.ui;
029
030import org.opencms.gwt.client.CmsCoreProvider;
031import org.opencms.gwt.client.Messages;
032import org.opencms.gwt.client.rpc.CmsRpcAction;
033import org.opencms.gwt.client.ui.input.CmsSelectBox;
034import org.opencms.gwt.client.util.CmsDomUtil;
035import org.opencms.gwt.shared.CmsPreviewInfo;
036import org.opencms.util.CmsStringUtil;
037import org.opencms.util.CmsUUID;
038
039import com.google.gwt.dom.client.Style;
040import com.google.gwt.dom.client.Style.Overflow;
041import com.google.gwt.dom.client.Style.Unit;
042import com.google.gwt.event.dom.client.ClickEvent;
043import com.google.gwt.event.dom.client.ClickHandler;
044import com.google.gwt.event.logical.shared.ValueChangeEvent;
045import com.google.gwt.event.logical.shared.ValueChangeHandler;
046import com.google.gwt.user.client.Window;
047import com.google.gwt.user.client.rpc.AsyncCallback;
048import com.google.gwt.user.client.ui.HTML;
049import com.google.gwt.user.client.ui.RootPanel;
050
051/**
052 * Resource preview dialog.<p>
053 */
054public final class CmsPreviewDialog extends CmsPopup {
055
056    /**
057     * Preview provider interface.<p>
058     */
059    public interface I_PreviewInfoProvider {
060
061        /**
062         * Loads the preview information for the given locale.<p>
063         *
064         * @param locale the locale for which to load the preview
065         * @param resultCallback the callback to call with the result
066         */
067        void loadPreviewForLocale(String locale, AsyncCallback<CmsPreviewInfo> resultCallback);
068    }
069
070    /** The dialog height. */
071    private static final int DIALOG_HEIGHT = 900;
072
073    /** The dialog preview content width. */
074    private static final int DIALOG_PREVIEW_CONTENT_WIDTH = 642;
075
076    /** The dialog width. */
077    private static final int DIALOG_WIDTH = 1200;
078
079    /** The select-box width. */
080    private static final int SELECTBOX_WIDTH = 120;
081
082    /** The truncation prefix. */
083    private static final String TRUNCATION_PREFIX = "PREVIEW_DIALOG";
084
085    /** The locale select box. */
086    private CmsSelectBox m_localeSelect;
087
088    /** The preview info provider. */
089    private I_PreviewInfoProvider m_previewInfoProvider;
090
091    /** The site path of the preview resource. */
092    private String m_sitePath;
093
094    /**
095     * Constructor.<p>
096     *
097     * @param caption the dialog caption
098     * @param width the dialog width
099     */
100    private CmsPreviewDialog(String caption, int width) {
101
102        super(caption, width);
103        setGlassEnabled(true);
104        setPositionFixed();
105        catchNotifications();
106        CmsPushButton closeButton = new CmsPushButton();
107        closeButton.setText(Messages.get().key(Messages.GUI_CLOSE_0));
108        closeButton.addClickHandler(new ClickHandler() {
109
110            public void onClick(ClickEvent event) {
111
112                hide();
113
114            }
115        });
116        addButton(closeButton);
117        addDialogClose(null);
118    }
119
120    /**
121     * Creates a new preview dialog instance.<p>
122     *
123     * @param previewInfo the preview information
124     *
125     * @return the new preview dialog instance
126     */
127    public static CmsPreviewDialog createPreviewDialog(CmsPreviewInfo previewInfo) {
128
129        String caption = generateCaption(previewInfo);
130        CmsPreviewDialog dialog = new CmsPreviewDialog(caption, DIALOG_WIDTH + 12);
131        dialog.initContent(previewInfo);
132        dialog.initLocales(previewInfo);
133        return dialog;
134    }
135
136    /**
137     * Shows the preview for the given resource.<p>
138     *
139     * @param previewInfo the resource preview info
140     */
141    public static void showPreviewForResource(CmsPreviewInfo previewInfo) {
142
143        if (previewInfo.isNewWindowRequired()) {
144            CmsDomUtil.openWindow(previewInfo.getPreviewUrl(), CmsDomUtil.Target.BLANK.getRepresentation(), "");
145        } else {
146
147            CmsPreviewDialog dialog = createPreviewDialog(previewInfo);
148            dialog.center();
149        }
150    }
151
152    /**
153     * Shows the preview for the given resource.<p>
154     *
155     * @param structureId the resource structure id
156     */
157    public static void showPreviewForResource(final CmsUUID structureId) {
158
159        CmsRpcAction<CmsPreviewInfo> previewAction = new CmsRpcAction<CmsPreviewInfo>() {
160
161            @Override
162            public void execute() {
163
164                CmsCoreProvider.getVfsService().getPreviewInfo(structureId, CmsCoreProvider.get().getLocale(), this);
165                start(0, true);
166            }
167
168            @Override
169            protected void onResponse(CmsPreviewInfo result) {
170
171                stop(false);
172                showPreviewForResource(result);
173            }
174        };
175        previewAction.execute();
176    }
177
178    /**
179     * Shows the preview for the given resource.<p>
180     *
181     * @param sitePath the resource site path
182     */
183    public static void showPreviewForResource(final String sitePath) {
184
185        CmsRpcAction<CmsPreviewInfo> previewAction = new CmsRpcAction<CmsPreviewInfo>() {
186
187            @Override
188            public void execute() {
189
190                CmsCoreProvider.getVfsService().getPreviewInfo(sitePath, CmsCoreProvider.get().getLocale(), this);
191                start(0, true);
192            }
193
194            @Override
195            protected void onResponse(CmsPreviewInfo result) {
196
197                stop(false);
198                showPreviewForResource(result);
199            }
200        };
201        previewAction.execute();
202    }
203
204    /**
205     * Generates the dialog caption.<p>
206     *
207     * @param previewInfo the preview info
208     *
209     * @return the caption
210     */
211    private static String generateCaption(CmsPreviewInfo previewInfo) {
212
213        return (CmsStringUtil.isNotEmptyOrWhitespaceOnly(previewInfo.getTitle()) ? previewInfo.getTitle() + " / " : "")
214            + previewInfo.getSitePath();
215    }
216
217    /**
218     * Sets the preview info provider.<p>
219     *
220     * @param provider the preview info provider instance
221     */
222    public void setPreviewInfoProvider(I_PreviewInfoProvider provider) {
223
224        m_previewInfoProvider = provider;
225    }
226
227    /**
228     * Returns the site path.<p>
229     *
230     * @return the site path
231     */
232    protected String getSitePath() {
233
234        return m_sitePath;
235    }
236
237    /**
238     * Loads preview for another locale.<p>
239     *
240     * @param locale the locale to load
241     */
242    protected void loadOtherLocale(final String locale) {
243
244        CmsRpcAction<CmsPreviewInfo> previewAction = new CmsRpcAction<CmsPreviewInfo>() {
245
246            @SuppressWarnings("synthetic-access")
247            @Override
248            public void execute() {
249
250                if (m_previewInfoProvider != null) {
251                    m_previewInfoProvider.loadPreviewForLocale(locale, this);
252                } else {
253                    CmsCoreProvider.getVfsService().getPreviewInfo(getSitePath(), locale, this);
254                }
255                start(0, true);
256            }
257
258            @Override
259            protected void onResponse(CmsPreviewInfo result) {
260
261                stop(false);
262                updatePreviewContent(result);
263            }
264        };
265        previewAction.execute();
266    }
267
268    /**
269     * Updates the preview content of the dialog.<p>
270     *
271     * @param previewInfo the preview info
272     */
273    protected void updatePreviewContent(CmsPreviewInfo previewInfo) {
274
275        setCaption(generateCaption(previewInfo));
276        initContent(previewInfo);
277        initLocales(previewInfo);
278        center();
279    }
280
281    /**
282     * Initializes the preview content.<p>
283     *
284     * @param previewInfo the preview info
285     */
286    private void initContent(CmsPreviewInfo previewInfo) {
287
288        setSitePath(previewInfo.getSitePath());
289        HTML content = new HTML();
290        Style style = content.getElement().getStyle();
291        int height = DIALOG_HEIGHT;
292        int width = DIALOG_WIDTH;
293        if (previewInfo.hasPreviewContent()) {
294            content.setHTML(previewInfo.getPreviewContent());
295            style.setOverflow(Overflow.AUTO);
296            // try to measure dimensions
297            width = DIALOG_PREVIEW_CONTENT_WIDTH;
298            style.setWidth(width, Unit.PX);
299            RootPanel.get().add(content);
300            height = content.getOffsetHeight();
301        } else {
302            content.setHTML(
303                "<iframe src=\"" + previewInfo.getPreviewUrl() + "\" style=\"height:100%; width:100%;\" />");
304        }
305        if (previewInfo.hasDimensions()) {
306            height = previewInfo.getHeight();
307            width = previewInfo.getWidth();
308        }
309        // check if window is big enough for requested dimensions
310        int availableHeight = Window.getClientHeight() - 200;
311        if (height > availableHeight) {
312            height = availableHeight;
313        }
314        int availableWidth = Window.getClientWidth() - 50;
315        if (width > availableWidth) {
316            width = availableWidth;
317        }
318        style.setHeight(height, Unit.PX);
319        style.setWidth(width, Unit.PX);
320        setWidth(width + 12);
321        setMainContent(content);
322    }
323
324    /**
325     * Initializes the locale selector if needed.<p>
326     *
327     * @param previewInfo the preview info
328     */
329    private void initLocales(CmsPreviewInfo previewInfo) {
330
331        if (m_localeSelect != null) {
332            removeButton(m_localeSelect);
333            m_localeSelect = null;
334        }
335        if (previewInfo.hasAdditionalLocales()) {
336            m_localeSelect = new CmsSelectBox(previewInfo.getLocales());
337            m_localeSelect.setFormValueAsString(previewInfo.getLocale());
338            m_localeSelect.addValueChangeHandler(new ValueChangeHandler<String>() {
339
340                public void onValueChange(ValueChangeEvent<String> event) {
341
342                    loadOtherLocale(event.getValue());
343                }
344            });
345            Style style = m_localeSelect.getElement().getStyle();
346            style.setWidth(SELECTBOX_WIDTH, Unit.PX);
347            style.setFloat(com.google.gwt.dom.client.Style.Float.LEFT);
348            style.setMargin(0, Unit.PX);
349            m_localeSelect.truncate(TRUNCATION_PREFIX, SELECTBOX_WIDTH - 20);
350            addButton(m_localeSelect);
351
352        }
353    }
354
355    /**
356     * Sets the site path.<p>
357     *
358     * @param sitePath the site path to set
359     */
360    private void setSitePath(String sitePath) {
361
362        m_sitePath = sitePath;
363    }
364}