001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.core.ui.ribbonconfiguration;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.avalon.framework.configuration.Configuration;
022import org.apache.avalon.framework.configuration.ConfigurationException;
023import org.apache.cocoon.xml.AttributesImpl;
024import org.apache.cocoon.xml.XMLUtils;
025import org.slf4j.Logger;
026import org.xml.sax.ContentHandler;
027import org.xml.sax.SAXException;
028
029import org.ametys.core.ui.RibbonConfigurationManager.CONTROLSIZE;
030import org.ametys.core.ui.RibbonConfigurationManager.LAYOUTALIGN;
031import org.ametys.core.ui.RibbonManager;
032
033/**
034 * A layout of controls
035 */
036public class Layout implements Element
037{
038    /** The layout alignment */
039    protected LAYOUTALIGN _layoutAlign;
040    
041    /** The size of the control */
042    protected CONTROLSIZE _size;
043    
044    /** Number of columns used by the control upon some layouts. 1 is the common and default value */
045    protected int _cols;
046    
047    /** The elements in the layout. Can be controls or toolbars */
048    protected List<Element> _elements = new ArrayList<>();
049
050    /** Logger */
051    protected Logger _layoutLogger;
052
053    /**
054     * Creates a layout of controls
055     * @param layoutConfiguration The configuration for the layout
056     * @param ribbonManager The ribbon manager 
057     * @param logger The logger
058     * @throws ConfigurationException if an error occurred
059     */
060    public Layout(Configuration layoutConfiguration, RibbonManager ribbonManager, Logger logger) throws ConfigurationException
061    {
062        this(layoutConfiguration.getAttributeAsInteger("cols", 1), CONTROLSIZE.createsFromString(layoutConfiguration.getAttribute("size", null)), LAYOUTALIGN.createsFromString(layoutConfiguration.getAttribute("align", null)), logger);
063
064        Configuration[] elementsConfigurations = layoutConfiguration.getChildren();
065        for (Configuration elementConfiguration : elementsConfigurations)
066        {
067            if ("control".equals(elementConfiguration.getName()))
068            {
069                ControlRef control = new ControlRef(elementConfiguration, ribbonManager, _layoutLogger);
070                _elements.add(control);
071            }
072            else if ("toolbar".equals(elementConfiguration.getName()))
073            {
074                Toolbar toolbar = new Toolbar(elementConfiguration, ribbonManager, _layoutLogger);
075                _elements.add(toolbar);
076            }
077            else if (_layoutLogger.isWarnEnabled())
078            {
079                _layoutLogger.warn("During configuration of the ribbon, the layout use an unknow tag '" + elementConfiguration.getName() + "'");
080            }
081        }
082    }
083    
084    /**
085     * Create a new layout by duplicating an existing layout
086     * @param layout The original layout
087     * @param size The new layout size
088     */
089    public Layout(Layout layout, CONTROLSIZE size)
090    {
091        this(layout._cols, size, layout._layoutAlign, layout._layoutLogger);
092    }
093    
094    /**
095     * Creates a layout of controls
096     * @param cols The number of columns
097     * @param size The size
098     * @param align The alignment
099     * @param logger The logger
100     */
101    public Layout(int cols, CONTROLSIZE size, LAYOUTALIGN align, Logger logger)
102    {
103        this._layoutLogger = logger;
104        
105        this._cols = cols;
106        if (_layoutLogger.isDebugEnabled())
107        {
108            _layoutLogger.debug("Control colspan is " + this._cols);
109        }
110        
111        this._layoutAlign = align; 
112        if (_layoutLogger.isDebugEnabled())
113        {
114            _layoutLogger.debug("Control align is " + this._layoutAlign);
115        }
116        
117        _size = size;
118        if (_layoutLogger.isDebugEnabled())
119        {
120            _layoutLogger.debug("Control size is " + this._size);
121        }
122    }
123    
124    /**
125     * Get the size of the layout
126     * @return The size
127     */
128    public CONTROLSIZE getSize()
129    {
130        return _size;
131    }
132    
133    /**
134     * Get the alignment of the layout
135     * @return The alignment
136     */
137    public LAYOUTALIGN getAlign()
138    {
139        return _layoutAlign;
140    }
141    
142    
143    public int getColumns()
144    {
145        return _cols;
146    }
147    
148    @Override
149    public void setColumns(int cols)
150    {
151        _cols = cols;
152    }
153    
154    @Override
155    public List<Element> getChildren()
156    {
157        return _elements;
158    }
159    
160    @Override
161    public void toSAX(ContentHandler handler) throws SAXException
162    {
163        AttributesImpl attrs = new AttributesImpl();
164        
165        if (_layoutAlign != null)
166        {
167            attrs.addCDATAAttribute("align", _layoutAlign.toString());
168        }
169
170        if (_size != null)
171        {
172            attrs.addCDATAAttribute("size", _size.toString());
173        }
174
175        attrs.addCDATAAttribute("cols", Integer.toString(_cols));
176        
177        XMLUtils.startElement(handler, "layout", attrs);
178        
179        for (Element element : _elements)
180        {
181            element.toSAX(handler);
182        }
183        
184        XMLUtils.endElement(handler, "layout");
185    }
186
187    public boolean isSame(Element element)
188    {
189        if (!(element instanceof Layout))
190        {
191            return false;
192        }
193        
194        Layout layout = (Layout) element;
195        if (layout._cols != _cols || layout._layoutAlign != _layoutAlign || layout._size != _size)
196        {
197            return false;
198        }
199        
200        List<Element> layoutElements = layout.getChildren();
201        if (layoutElements.size() != _elements.size())
202        {
203            return false;
204        }
205        for (int i = 0; i < _elements.size(); i++)
206        {
207            Element child = _elements.get(i);
208            Element objElement = layoutElements.get(i);
209            if (child == null || objElement == null || !child.isSame(objElement))
210            {
211                return false;
212            }
213        }
214        
215        return true;
216    }
217}
218