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.I_CmsButton.ButtonColor;
034import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
035import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
036import org.opencms.gwt.shared.CmsListInfoBean;
037import org.opencms.gwt.shared.CmsListInfoBean.LockIcon;
038import org.opencms.gwt.shared.CmsLockReportInfo;
039import org.opencms.util.CmsUUID;
040
041import com.google.gwt.event.dom.client.ClickEvent;
042import com.google.gwt.event.dom.client.ClickHandler;
043import com.google.gwt.event.logical.shared.CloseEvent;
044import com.google.gwt.event.logical.shared.CloseHandler;
045import com.google.gwt.event.logical.shared.OpenEvent;
046import com.google.gwt.event.logical.shared.OpenHandler;
047import com.google.gwt.user.client.Command;
048import com.google.gwt.user.client.ui.FlowPanel;
049import com.google.gwt.user.client.ui.PopupPanel;
050
051/**
052 * The lock report dialog.<p>
053 *
054 * @since 8.0.1
055 */
056public final class CmsLockReportDialog extends CmsPopup {
057
058    /**
059     * Handles the scroll panel height.<p>
060     */
061    private class HeightHandler implements CloseHandler<CmsListItemWidget>, OpenHandler<CmsListItemWidget> {
062
063        /**
064         * Constructor.<p>
065         */
066        protected HeightHandler() {
067
068            // nothing to do
069        }
070
071        /**
072         * @see com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt.event.logical.shared.CloseEvent)
073         */
074        public void onClose(CloseEvent<CmsListItemWidget> event) {
075
076            adjustHeight();
077        }
078
079        /**
080         * @see com.google.gwt.event.logical.shared.OpenHandler#onOpen(com.google.gwt.event.logical.shared.OpenEvent)
081         */
082        public void onOpen(OpenEvent<CmsListItemWidget> event) {
083
084            adjustHeight();
085        }
086    }
087
088    /** The text metrics key. */
089    private static final String TEXT_METRICS_KEY = "CMS_LOCK_REPORT_DIALOG_METRICS";
090
091    /** The close button. */
092    private CmsPushButton m_closeButton;
093
094    /** Command executed on resource unlock. */
095    private Command m_onUnlock;
096
097    /** The resource item widget. */
098    private CmsListItemWidget m_resourceItem;
099
100    /** The scroll panel. */
101    private FlowPanel m_scrollPanel;
102
103    /** The structure id of the resource to report on. */
104    private CmsUUID m_structureId;
105
106    /** The unlock button. */
107    private CmsPushButton m_unlockButton;
108
109    /**
110     * Constructor.<p>
111     *
112     * @param title the title for the dialog (a default value will be used if this is null)
113     * @param structureId the structure id of the resource to unlock
114     * @param onUnlock command to execute after unlocking
115     * @param optionalOnCloseCommand optional action to execute when the dialog is closed
116     */
117    private CmsLockReportDialog(
118        String title,
119        CmsUUID structureId,
120        Command onUnlock,
121        final Command optionalOnCloseCommand) {
122
123        super(title != null ? title : Messages.get().key(Messages.GUI_LOCK_REPORT_TITLE_0));
124        m_structureId = structureId;
125        m_onUnlock = onUnlock;
126        m_closeButton = new CmsPushButton();
127        m_closeButton.setText(Messages.get().key(Messages.GUI_CANCEL_0));
128        m_closeButton.setUseMinWidth(true);
129        m_closeButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.BLUE);
130        m_closeButton.addClickHandler(new ClickHandler() {
131
132            /**
133             * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
134             */
135            public void onClick(ClickEvent event) {
136
137                hide();
138            }
139        });
140        addButton(m_closeButton);
141        addDialogClose(null);
142        if (optionalOnCloseCommand != null) {
143            addCloseHandler(new CloseHandler<PopupPanel>() {
144
145                public void onClose(CloseEvent<PopupPanel> event) {
146
147                    optionalOnCloseCommand.execute();
148
149                }
150            });
151        }
152        m_unlockButton = new CmsPushButton();
153        m_unlockButton.setText(Messages.get().key(Messages.GUI_UNLOCK_0));
154        m_unlockButton.setUseMinWidth(true);
155        m_unlockButton.setButtonStyle(ButtonStyle.TEXT, ButtonColor.RED);
156        m_unlockButton.addClickHandler(new ClickHandler() {
157
158            /**
159             * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
160             */
161            public void onClick(ClickEvent event) {
162
163                unlock();
164            }
165        });
166        m_unlockButton.setVisible(false);
167        addButton(m_unlockButton);
168        setGlassEnabled(true);
169    }
170
171    /**
172     * Opens the lock report dialog for the given resource.<p>
173     *
174     * @param title the dialog title (will use a default value if null)
175     * @param structureId the structure id of the resource
176     * @param onUnlock the command to execute after the has been unlocked
177     * @param optionalOnCloseCommand the optional command to execute when the lock report dialog is closed
178     */
179    public static void openDialogForResource(
180        String title,
181        final CmsUUID structureId,
182        Command onUnlock,
183        Command optionalOnCloseCommand) {
184
185        final CmsLockReportDialog dialog = new CmsLockReportDialog(
186            title,
187            structureId,
188            onUnlock,
189            optionalOnCloseCommand);
190        CmsRpcAction<CmsLockReportInfo> action = new CmsRpcAction<CmsLockReportInfo>() {
191
192            @Override
193            public void execute() {
194
195                start(0, true);
196                CmsCoreProvider.getVfsService().getLockReportInfo(structureId, this);
197            }
198
199            @Override
200            public void onFailure(Throwable t) {
201
202                stop(false);
203                dialog.hide();
204                super.onFailure(t);
205            }
206
207            @Override
208            protected void onResponse(CmsLockReportInfo result) {
209
210                stop(false);
211                dialog.initContent(result);
212            }
213        };
214        dialog.center();
215        action.execute();
216
217    }
218
219    /**
220     * Adjusts the height of the scroll panel.<p>
221     */
222    protected void adjustHeight() {
223
224        if ((m_scrollPanel != null) && (m_resourceItem != null)) {
225            m_scrollPanel.getElement().getStyle().setPropertyPx(
226                "maxHeight",
227                getAvailableHeight(m_resourceItem.getOffsetHeight()));
228        }
229        center();
230    }
231
232    /**
233     * Returns the structure id of the resource to report on.<p>
234     *
235     * @return the structure id
236     */
237    protected CmsUUID getStructureId() {
238
239        return m_structureId;
240    }
241
242    /**
243     * Initializes the dialog content with the give report info.<p>
244     *
245     * @param reportInfo the report info
246     */
247    protected void initContent(CmsLockReportInfo reportInfo) {
248
249        FlowPanel content = new FlowPanel();
250
251        m_resourceItem = new CmsListItemWidget(reportInfo.getResourceInfo());
252        HeightHandler heightHandler = new HeightHandler();
253        m_resourceItem.addOpenHandler(heightHandler);
254        m_resourceItem.addCloseHandler(heightHandler);
255        content.add(m_resourceItem);
256        m_scrollPanel = new FlowPanel();
257        m_scrollPanel.setStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().border());
258        m_scrollPanel.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
259        m_scrollPanel.addStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().logReportScrollPanel());
260        CmsList<CmsListItem> list = null;
261        CmsMessageWidget message = new CmsMessageWidget();
262        m_scrollPanel.add(message);
263        message.setMessageText(
264            getMessageForLock(
265                reportInfo.getResourceInfo().getLockIcon(),
266                !reportInfo.getLockedResourceInfos().isEmpty()));
267        if (!reportInfo.getLockedResourceInfos().isEmpty()
268            || ((reportInfo.getResourceInfo().getLockIcon() != null)
269                && (reportInfo.getResourceInfo().getLockIcon() != LockIcon.NONE))) {
270            m_unlockButton.setVisible(true);
271        }
272        // only show the unlock button if the resource or a descending resource is locked
273        if (!reportInfo.getLockedResourceInfos().isEmpty()) {
274            m_unlockButton.setText(Messages.get().key(Messages.GUI_UNLOCK_ALL_0));
275            list = new CmsList<CmsListItem>();
276            for (CmsListInfoBean lockedInfo : reportInfo.getLockedResourceInfos()) {
277                CmsListItemWidget listItemWidget = new CmsListItemWidget(lockedInfo);
278                listItemWidget.addOpenHandler(heightHandler);
279                listItemWidget.addCloseHandler(heightHandler);
280                list.addItem(new CmsListItem(listItemWidget));
281            }
282            m_scrollPanel.add(list);
283        }
284
285        content.add(m_scrollPanel);
286        setMainContent(content);
287        if (isShowing()) {
288            m_resourceItem.truncate(TEXT_METRICS_KEY, CmsPopup.DEFAULT_WIDTH - 10);
289            if (list != null) {
290                list.truncate(TEXT_METRICS_KEY, CmsPopup.DEFAULT_WIDTH - 10);
291            }
292            adjustHeight();
293        }
294    }
295
296    /**
297     * Executed on unlock.<p>
298     */
299    protected void onUnlock() {
300
301        if (m_onUnlock != null) {
302            m_onUnlock.execute();
303        }
304        hide();
305    }
306
307    /**
308     * Unlocks the resource and all descending resources.<p>
309     */
310    protected void unlock() {
311
312        CmsRpcAction<Void> action = new CmsRpcAction<Void>() {
313
314            @Override
315            public void execute() {
316
317                CmsCoreProvider.getVfsService().forceUnlock(getStructureId(), this);
318            }
319
320            @Override
321            public void onFailure(Throwable t) {
322
323                hide();
324                super.onFailure(t);
325            }
326
327            @Override
328            protected void onResponse(Void result) {
329
330                onUnlock();
331            }
332        };
333        m_closeButton.disable(Messages.get().key(Messages.GUI_LOADING_0));
334        m_unlockButton.disable(Messages.get().key(Messages.GUI_LOADING_0));
335        action.execute();
336    }
337
338    /**
339     * Returns the dialog message for the given lock.<p>
340     *
341     * @param lockIcon the lock icon
342     * @param hasLockedChildren <code>true</code> if the given resource has locked children
343     *
344     * @return the dialog message
345     */
346    private String getMessageForLock(LockIcon lockIcon, boolean hasLockedChildren) {
347
348        String result = "";
349        if (!hasLockedChildren && ((lockIcon == null) || (lockIcon == LockIcon.NONE))) {
350            result = Messages.get().key(Messages.GUI_LOCK_REPORT_NOTHING_LOCKED_0);
351        } else if ((lockIcon == LockIcon.OPEN) || (lockIcon == LockIcon.SHARED_OPEN)) {
352            if (hasLockedChildren) {
353                result = Messages.get().key(Messages.GUI_LOCK_REPORT_UNLOCK_ALL_MESSAGE_0);
354            } else {
355                result = Messages.get().key(Messages.GUI_LOCK_REPORT_UNLOCK_MESSAGE_0);
356            }
357        } else {
358            if (hasLockedChildren) {
359                result = Messages.get().key(Messages.GUI_LOCK_REPORT_STEAL_ALL_LOCKS_MESSAGE_0);
360            } else {
361                result = Messages.get().key(Messages.GUI_LOCK_REPORT_STEAL_LOCK_MESSAGE_0);
362            }
363        }
364        return result;
365    }
366
367}