]> git.sesse.net Git - vlc/blob - modules/gui/skins2/utils/position.cpp
Skins2: Cosmetics
[vlc] / modules / gui / skins2 / utils / position.cpp
1 /*****************************************************************************
2  * position.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "position.hpp"
26
27
28 const string VarBox::m_type = "box";
29
30
31 SkinsRect::SkinsRect( int left, int top, int right, int bottom ):
32     m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom )
33 {
34 }
35
36
37 Position::Position( int left, int top, int right, int bottom,
38                     const GenericRect &rRect,
39                     Ref_t refLeftTop, Ref_t refRightBottom,
40                     bool xKeepRatio, bool yKeepRatio ):
41     m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom ),
42     m_rRect( rRect ), m_refLeftTop( refLeftTop ),
43     m_refRighBottom( refRightBottom ), m_xKeepRatio( xKeepRatio ),
44     m_yKeepRatio( yKeepRatio )
45 {
46     // Here is how the resizing algorithm works:
47     //
48     //  - if we "keep the ratio" (xkeepratio="true" in the XML), the relative
49     //    position of the control in the parent box (i.e. the given rRect) is
50     //    saved, and will be kept constant. The size of the control will not
51     //    be changed, only its position may vary. To do that, we consider the
52     //    part of the box to the left of the control (for an horizontal
53     //    resizing) and the part of the box to the right of the control,
54     //    and we make sure that the ratio between their widths is constant.
55     //
56     //  - if we don't keep the ratio, the resizing algorithm is completely
57     //    different. We consider that the top left hand corner of the control
58     //    ("lefttop" attribute in the XML) is linked to one of the 4 corners
59     //    of the parent box ("lefttop", "leftbottom", "righttop" and
60     //    "rightbottom" values for the attribute). Same thing for the bottom
61     //    right hand corner ("rightbottom" attribute). When resizing occurs,
62     //    the linked corners will move together, and this will drive the
63     //    moving/resizing of the control.
64
65     // Initialize the horizontal ratio
66     if( m_xKeepRatio )
67     {
68         // First compute the width of the box minus the width of the control
69         int freeSpace = m_rRect.getWidth() - (m_right - m_left);
70         // Instead of computing left/right, we compute left/(left+right),
71         // which is more convenient in my opinion.
72         if( freeSpace != 0 )
73         {
74             m_xRatio = (double)m_left / (double)freeSpace;
75         }
76         else
77         {
78             // If the control has the same size as the box, we can't compute
79             // the ratio in the same way (otherwise we would divide by zero).
80             // So we consider that the intent was to keep the control centered
81             // (if you are unhappy with this, go and fix your skin :))
82             m_xRatio = 0.5;
83         }
84     }
85
86     // Initial the vertical ratio
87     if( m_yKeepRatio )
88     {
89         // First compute the height of the box minus the height of the control
90         int freeSpace = m_rRect.getHeight() - (m_bottom - m_top);
91         // Instead of computing top/bottom, we compute top/(top+bottom),
92         // which is more convenient in my opinion.
93         if( freeSpace != 0 )
94         {
95             m_yRatio = (double)m_top / (double)freeSpace;
96         }
97         else
98         {
99             // If the control has the same size as the box, we can't compute
100             // the ratio in the same way (otherwise we would divide by zero).
101             // So we consider that the intent was to keep the control centered
102             // (if you are unhappy with this, go and fix your skin :))
103             m_yRatio = 0.5;
104         }
105     }
106
107 }
108
109
110 int Position::getLeft() const
111 {
112     if( m_xKeepRatio )
113     {
114         // Ratio mode
115         // First compute the width of the box minus the width of the control
116         int freeSpace = m_rRect.getWidth() - (m_right - m_left);
117         return m_rRect.getLeft() + (int)(m_xRatio * freeSpace);
118     }
119     else
120     {
121         switch( m_refLeftTop )
122         {
123         case kLeftTop:
124         case kLeftBottom:
125             return m_rRect.getLeft() + m_left;
126             break;
127         case kRightTop:
128         case kRightBottom:
129             return m_rRect.getLeft() + m_rRect.getWidth() + m_left - 1;
130             break;
131         }
132         // Avoid a warning
133         return 0;
134     }
135 }
136
137
138 int Position::getTop() const
139 {
140     if( m_yKeepRatio )
141     {
142         // Ratio mode
143         // First compute the height of the box minus the height of the control
144         int freeSpace = m_rRect.getHeight() - (m_bottom - m_top);
145         return m_rRect.getTop() + (int)(m_yRatio * freeSpace);
146     }
147     else
148     {
149         switch( m_refLeftTop )
150         {
151             case kLeftTop:
152             case kRightTop:
153                 return m_rRect.getTop() + m_top;
154                 break;
155             case kRightBottom:
156             case kLeftBottom:
157                 return m_rRect.getTop() + m_rRect.getHeight() + m_top - 1;
158                 break;
159         }
160         // Avoid a warning
161         return 0;
162     }
163 }
164
165
166 int Position::getRight() const
167 {
168     if( m_xKeepRatio )
169     {
170         // Ratio mode
171         // The width of the control being constant, we can use the result of
172         // getLeft() (this will avoid rounding issues).
173         return getLeft() + m_right - m_left;
174     }
175     else
176     {
177         switch( m_refRighBottom )
178         {
179             case kLeftTop:
180             case kLeftBottom:
181                 return m_rRect.getLeft() + m_right;
182                 break;
183             case kRightTop:
184             case kRightBottom:
185                 return m_rRect.getLeft() + m_rRect.getWidth() + m_right - 1;
186                 break;
187         }
188         // Avoid a warning
189         return 0;
190     }
191 }
192
193
194 int Position::getBottom() const
195 {
196     if( m_yKeepRatio )
197     {
198         // Ratio mode
199         // The height of the control being constant, we can use the result of
200         // getTop() (this will avoid rounding issues).
201         return getTop() + m_bottom - m_top;
202     }
203     else
204     {
205         switch( m_refRighBottom )
206         {
207             case kLeftTop:
208             case kRightTop:
209                 return m_rRect.getTop() + m_bottom;
210                 break;
211             case kLeftBottom:
212             case kRightBottom:
213                 return m_rRect.getTop() + m_rRect.getHeight() + m_bottom - 1;
214                 break;
215         }
216         // Avoid a warning
217         return 0;
218     }
219 }
220
221
222 int Position::getWidth() const
223 {
224     return getRight() - getLeft() + 1;
225 }
226
227
228 int Position::getHeight() const
229 {
230     return getBottom() - getTop() + 1;
231 }
232
233
234 VarBox::VarBox( intf_thread_t *pIntf, int width, int height ):
235     Variable( pIntf ), m_width( width ), m_height( height )
236 {
237 }
238
239
240 int VarBox::getWidth() const
241 {
242     return m_width;
243 }
244
245
246 int VarBox::getHeight() const
247 {
248     return m_height;
249 }
250
251
252 void VarBox::setSize( int width, int height )
253 {
254     m_width = width;
255     m_height = height;
256     notify();
257 }
258