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.ui.apps;
029
030import org.opencms.file.CmsObject;
031import org.opencms.main.OpenCms;
032import org.opencms.ui.A_CmsUI;
033import org.opencms.ui.CmsVaadinUtils;
034import org.opencms.ui.components.CmsErrorDialog;
035
036import java.util.ArrayList;
037import java.util.Collection;
038import java.util.List;
039import java.util.Locale;
040
041import com.vaadin.ui.Button;
042import com.vaadin.ui.Button.ClickEvent;
043import com.vaadin.ui.Button.ClickListener;
044import com.vaadin.ui.Component;
045import com.vaadin.ui.CssLayout;
046import com.vaadin.ui.UI;
047import com.vaadin.ui.VerticalLayout;
048import com.vaadin.ui.dnd.DragSourceExtension;
049import com.vaadin.ui.dnd.DropTargetExtension;
050import com.vaadin.ui.dnd.event.DropEvent;
051import com.vaadin.ui.dnd.event.DropListener;
052import com.vaadin.ui.themes.ValoTheme;
053
054/**
055 * App to edit the quick launch menu.<p>
056 */
057public class CmsQuickLaunchEditor extends VerticalLayout {
058
059    /**
060     * The sorting drop listener.<p>
061     */
062    protected class LayoutDropListener implements DropListener<CssLayout> {
063
064        /** The item height. */
065        private static final int ITEM_HEIGHT = 88;
066
067        /** The item width. */
068        private static final int ITEM_WIDTH = 176;
069
070        /** The layout width. */
071        private static final int LAYOUT_WIDTH = 1158;
072
073        /** The serial version id. */
074        private static final long serialVersionUID = 8420945711551716630L;
075
076        /** The drag target ordered layout. */
077        private CssLayout m_layout;
078
079        /**
080         * Constructor.<p>
081         *
082         * @param layout the drop target layout
083         */
084        protected LayoutDropListener(CssLayout layout) {
085
086            m_layout = layout;
087        }
088
089        /**
090         * @see com.vaadin.ui.dnd.event.DropListener#drop(com.vaadin.ui.dnd.event.DropEvent)
091         */
092        public void drop(DropEvent<CssLayout> event) {
093
094            // depending on the browser window width, different margins and paddings apply
095            int layoutWidth = LAYOUT_WIDTH;
096            int windowWidth = UI.getCurrent().getPage().getBrowserWindowWidth();
097            if (windowWidth <= 983) {
098                layoutWidth = windowWidth - 22;
099            } else if (windowWidth <= 1220) {
100                layoutWidth = windowWidth - 62;
101            }
102            int top = event.getMouseEventDetails().getRelativeY();
103            int left = event.getMouseEventDetails().getRelativeX();
104            int columnCount = layoutWidth / ITEM_WIDTH;
105            int column = left / ITEM_WIDTH;
106            int row = top / ITEM_HEIGHT;
107            int index = (row * columnCount) + column;
108            if (((column * ITEM_WIDTH) + (ITEM_WIDTH / 2)) < left) {
109                index++;
110            }
111            Component sourceComponent = event.getDragSourceComponent().get();
112            int currentIndex = m_layout.getComponentIndex(sourceComponent);
113            if ((currentIndex != -1) && (currentIndex < index)) {
114                index--;
115            }
116
117            if (currentIndex == index) {
118                return;
119            }
120
121            // move component within the layout
122            m_layout.removeComponent(sourceComponent);
123            // avoid index out of bounds exceptions
124            if (m_layout.getComponentCount() < index) {
125                index = m_layout.getComponentCount();
126            }
127            m_layout.addComponent(sourceComponent, index);
128        }
129    }
130
131    /** The serial version id. */
132    private static final long serialVersionUID = -6608352673763873030L;
133
134    /** The available apps drop target wrapper. */
135    private CssLayout m_availableApps;
136
137    /** The cancel button. */
138    private Button m_reset;
139
140    /** The standard apps layout. */
141    private CssLayout m_standardApps;
142
143    /** The user apps drop target wrapper. */
144    private CssLayout m_userApps;
145
146    /**
147     * Constructor.<p>
148     */
149    public CmsQuickLaunchEditor() {
150
151        CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null);
152        DropTargetExtension<CssLayout> userDrop = new DropTargetExtension<>(m_userApps);
153        userDrop.addDropListener(new LayoutDropListener(m_userApps));
154        m_userApps.addStyleName(ValoTheme.LAYOUT_HORIZONTAL_WRAPPING);
155        DropTargetExtension<CssLayout> availablesDrop = new DropTargetExtension<>(m_availableApps);
156        availablesDrop.addDropListener(new LayoutDropListener(m_availableApps));
157        m_reset.addClickListener(new ClickListener() {
158
159            private static final long serialVersionUID = 1L;
160
161            public void buttonClick(ClickEvent event) {
162
163                resetAppIcons();
164            }
165        });
166    }
167
168    /**
169     * Initializes the app icon items.<p>
170     */
171    protected void resetAppIcons() {
172
173        CmsObject cms = A_CmsUI.getCmsObject();
174        Locale locale = UI.getCurrent().getLocale();
175        m_standardApps.removeAllComponents();
176        m_userApps.removeAllComponents();
177        m_availableApps.removeAllComponents();
178        Collection<I_CmsWorkplaceAppConfiguration> allApps = OpenCms.getWorkplaceAppManager().getWorkplaceApps();
179        Collection<I_CmsWorkplaceAppConfiguration> standardApps = OpenCms.getWorkplaceAppManager().getDefaultQuickLaunchConfigurations();
180        Collection<I_CmsWorkplaceAppConfiguration> userApps = OpenCms.getWorkplaceAppManager().getUserQuickLauchConfigurations(
181            cms);
182        for (I_CmsWorkplaceAppConfiguration config : standardApps) {
183            CmsAppVisibilityStatus visibility = config.getVisibility(cms);
184            if (visibility.isVisible()) {
185                Button button = CmsDefaultAppButtonProvider.createAppIconButton(config, locale);
186                m_standardApps.addComponent(button);
187            }
188        }
189        for (I_CmsWorkplaceAppConfiguration config : userApps) {
190            CmsAppVisibilityStatus visibility = config.getVisibility(cms);
191            if (visibility.isVisible() && visibility.isActive()) {
192                Button button = CmsDefaultAppButtonProvider.createAppIconButton(config, locale);
193                //    button.setWidth("166px");
194                DragSourceExtension<Button> extButton = new DragSourceExtension<>(button);
195                button.setData(config.getId());
196                extButton.setDataTransferText(config.getId());
197                m_userApps.addComponent(button);
198            }
199        }
200        for (I_CmsWorkplaceAppConfiguration config : allApps) {
201            CmsAppVisibilityStatus visibility = config.getVisibility(cms);
202            if (!standardApps.contains(config)
203                && !userApps.contains(config)
204                && visibility.isVisible()
205                && visibility.isActive()) {
206                Button button = CmsDefaultAppButtonProvider.createAppIconButton(config, locale);
207                //  button.setWidth("166px");
208                DragSourceExtension<Button> extButton = new DragSourceExtension<>(button);
209                button.setData(config.getId());
210                extButton.setDataTransferText(config.getId());
211                m_availableApps.addComponent(button);
212            }
213        }
214    }
215
216    /**
217     * Saves the changed apps setting.<p>
218     */
219    void saveToUser() {
220
221        List<String> apps = new ArrayList<String>();
222        int count = m_userApps.getComponentCount();
223        for (int i = 0; i < count; i++) {
224            Button button = (Button)m_userApps.getComponent(i);
225            apps.add((String)button.getData());
226        }
227
228        try {
229            OpenCms.getWorkplaceAppManager().setUserQuickLaunchApps(A_CmsUI.getCmsObject(), apps);
230        } catch (Exception e) {
231            CmsErrorDialog.showErrorDialog("Could not write user Quicklaunch apps", e);
232        }
233    }
234}