View Javadoc
1   /**
2    * This file Copyright (c) 2015-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.vaadin.gwt.client.layout.thumbnaillayout.widget;
35  
36  import com.google.gwt.dom.client.Element;
37  import com.google.gwt.dom.client.ImageElement;
38  import com.google.gwt.dom.client.Node;
39  import com.google.gwt.dom.client.Style;
40  import com.google.gwt.user.client.DOM;
41  import com.vaadin.client.ComputedStyle;
42  
43  /**
44   * Tracks the base sizes of the thumbnails set from the server, applies those to all the thumbnails,
45   * calculates the resulting actual size. Also is capable of applying a scaling ratio to the thumbnails.
46   */
47  class ThumbnailsSizeKeeper {
48  
49      private static final int MAX_SIZE = 250;
50  
51      private int calculatedWidth;
52  
53      private int calculatedHeight;
54  
55      private int baseWidth;
56  
57      private int baseHeight;
58  
59      private Element thumbnailParent;
60  
61      private float ratio;
62  
63      private int unscaledWidth;
64  
65      private int unscaledHeight;
66      private int verticalDecorations;
67      private int horizontalDecorations;
68  
69      ThumbnailsSizeKeeper(Element thumbnailParent) {
70          this.thumbnailParent = thumbnailParent;
71      }
72  
73      void scale(float ratio) {
74          this.ratio = ratio;
75          updateCalculatedOffsetSizes();
76          doUpdateAllThumbnailsSize(calculatedWidth, calculatedHeight);
77      }
78  
79      public void scaleToWidth(int width) {
80          int targetWidth = Math.min(width, MAX_SIZE);
81          if (baseWidth < MAX_SIZE) {
82              scale((float)(targetWidth - unscaledWidth) / (MAX_SIZE - baseWidth));
83          }
84      }
85  
86      int height() {
87          return this.calculatedHeight + verticalDecorations;
88      }
89  
90      int width() {
91          return this.calculatedWidth + horizontalDecorations;
92      }
93  
94      boolean updateAllThumbnailsSize(int width, int height) {
95          if (this.baseHeight != height || this.baseWidth != width) {
96              this.baseHeight = height;
97              this.baseWidth = width;
98  
99              doUpdateAllThumbnailsSize(width, height);
100             updateCalculatedOffsetSizes();
101             return true;
102         }
103 
104         return false;
105     }
106 
107     void applySizeToThumbnail(Element thumbnail) {
108         doSetThumbnailSize(scaleDimension(baseWidth, ratio), scaleDimension(baseHeight, ratio), thumbnail);
109     }
110 
111     private int scaleDimension(int minValue, double ratio) {
112         if (minValue == MAX_SIZE) {
113             return MAX_SIZE;
114         }
115         return (int) ((MAX_SIZE - minValue) * ratio + minValue);
116     }
117 
118     private void doUpdateAllThumbnailsSize(int width, int height) {
119         Node element = thumbnailParent.getFirstChildElement();
120         while (element != null) {
121             doSetThumbnailSize(width, height, Element.as(element));
122             element = element.getNextSibling();
123         }
124     }
125 
126     private void doSetThumbnailSize(int width, int height, Element element) {
127         final Style style = element.getStyle();
128         style.setFontSize(width * 0.75d, Style.Unit.PX);
129         style.setWidth(width, Style.Unit.PX);
130         style.setHeight(height, Style.Unit.PX);
131 
132         Style imageStyle = element.getElementsByTagName(ImageElement.TAG).getItem(0).getStyle();
133         imageStyle.setProperty("maxWidth", width + "px");
134         imageStyle.setProperty("maxHeight", height + "px");
135     }
136 
137     private void updateCalculatedOffsetSizes() {
138         ComputedStyle cs;
139 
140         int[] padding;
141         int[] border;
142         int[] margin;
143 
144         if (thumbnailParent.getChildCount() > 0) {
145             final Element firstThumbnail = Element.as(thumbnailParent.getFirstChild());
146             cs = new ComputedStyle(firstThumbnail);
147 
148             padding = cs.getPadding();
149             border = cs.getBorder();
150             margin = cs.getMargin();
151         } else {
152             final Element stub = Element.as(DOM.createDiv());
153             stub.addClassName("thumbnail");
154             thumbnailParent.appendChild(stub);
155             cs = new ComputedStyle(stub);
156             padding = cs.getPadding();
157             border = cs.getBorder();
158             margin = cs.getMargin();
159 
160             thumbnailParent.removeChild(stub);
161         }
162 
163 
164         horizontalDecorations = padding[1] + padding[3] + border[1] + border[3] + margin[1] + margin[3];
165         verticalDecorations = padding[0] + padding[2] + border[0] + border[2] + margin[0] + margin[2];
166 
167         this.unscaledWidth = baseWidth + horizontalDecorations;
168         this.unscaledHeight = baseHeight + verticalDecorations;
169 
170         this.calculatedWidth = scaleDimension(baseWidth, ratio);
171         this.calculatedHeight = scaleDimension(baseHeight, ratio);
172 
173     }
174 
175     float getScaleRatio() {
176         return ratio;
177     }
178 
179     int getUnscaledWidth() {
180         return unscaledWidth;
181     }
182 
183     int getUnscaledHeight() {
184         return unscaledHeight;
185     }
186 }