]> git.sesse.net Git - vlc/blob - modules/gui/skins2/utils/position.cpp
5529fc7b5cb224edab9f8ad61b1ebed699034115
[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 Rect::Rect( 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, const Box &rBox,
38                     Ref_t refLeftTop, Ref_t refRightBottom, bool xKeepRatio,
39                     bool yKeepRatio ):
40     m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom ),
41     m_rBox( rBox ), m_refLeftTop( refLeftTop ),
42     m_refRighBottom( refRightBottom ), m_xKeepRatio( xKeepRatio ),
43     m_yKeepRatio( yKeepRatio )
44 {
45     // Here is how the resizing algorithm works:
46     //
47     //  - if we "keep the ratio" (xkeepratio="true" in the XML), the relative
48     //    position of the control in the layout (i.e. the given rBox) is
49     //    saved, and will be kept constant. The size of the control will not
50     //    be changed, only its position may vary. To do that, we consider the
51     //    part of the layout to the left of the control (for an horizontal
52     //    resizing) and the part of the layout to the right of the control,
53     //    and we make sure that the ratio between their widths is constant.
54     //
55     //  - if we don't keep the ratio, the resizing algorithm is completely
56     //    different. We consider that the top left hand corner of the control
57     //    ("lefttop" attribute in the XML) is linked to one of the 4 corners
58     //    of the layouts ("lefttop", "leftbottom", "righttop" and
59     //    "rightbottom" values for the attribute). Same thing for the bottom
60     //    right hand corner ("rightbottom" attribute). When resizing occurs,
61     //    the linked corners will move together, and this will drive the
62     //    moving/resizing of the control.
63
64     // Initialize the horizontal ratio
65     if( m_xKeepRatio )
66     {
67         // First compute the width of the box minus the width of the control
68         int freeSpace = m_rBox.getWidth() - (m_right - m_left);
69         // Instead of computing left/right, we compute left/(left+right),
70         // which is more convenient in my opinion.
71         if( freeSpace != 0 )
72         {
73             m_xRatio = (double)m_left / (double)freeSpace;
74         }
75         else
76         {
77             // If the control has the same size as the box, we can't compute
78             // the ratio in the same way (otherwise we would divide by zero).
79             // So we consider that the intent was to keep the control centered
80             // (if you are unhappy with this, go and fix your skin :))
81             m_xRatio = 0.5;
82         }
83     }
84
85     // Initial the vertical ratio
86     if( m_yKeepRatio )
87     {
88         // First compute the width of the box minus the width of the control
89         int freeSpace = m_rBox.getHeight() - (m_bottom - m_top);
90         // Instead of computing left/right, we compute left/(left+right),
91         // which is more convenient in my opinion.
92         if( freeSpace != 0 )
93         {
94             m_yRatio = (double)m_top / (double)freeSpace;
95         }
96         else
97         {
98             // If the control has the same size as the box, we can't compute
99             // the ratio in the same way (otherwise we would divide by zero).
100             // So we consider that the intent was to keep the control centered
101             // (if you are unhappy with this, go and fix your skin :))
102             m_yRatio = 0.5;
103         }
104     }
105
106 }
107
108
109 int Position::getLeft() const
110 {
111     if( m_xKeepRatio )
112     {
113         // Ratio mode
114         // First compute the width of the box minus the width of the control
115         int freeSpace = m_rBox.getWidth() - (m_right - m_left);
116         return (int)(m_xRatio * freeSpace);
117     }
118     else
119     {
120         switch( m_refLeftTop )
121         {
122             case kLeftTop:
123             case kLeftBottom:
124                 return m_left;
125                 break;
126             case kRightTop:
127             case kRightBottom:
128                 return m_rBox.getWidth() + m_left - 1;
129                 break;
130         }
131         // Avoid a warning
132         return 0;
133     }
134 }
135
136
137 int Position::getTop() const
138 {
139     if( m_yKeepRatio )
140     {
141         // Ratio mode
142         // First compute the height of the box minus the height of the control
143         int freeSpace = m_rBox.getHeight() - (m_bottom - m_top);
144         return (int)(m_yRatio * freeSpace);
145     }
146     else
147     {
148         switch( m_refLeftTop )
149         {
150             case kLeftTop:
151             case kRightTop:
152                 return m_top;
153                 break;
154             case kRightBottom:
155             case kLeftBottom:
156                 return m_rBox.getHeight() + m_top - 1;
157                 break;
158         }
159         // Avoid a warning
160         return 0;
161     }
162 }
163
164
165 int Position::getRight() const
166 {
167     if( m_xKeepRatio )
168     {
169         // Ratio mode
170         // The width of the control being constant, we can use the result of
171         // getLeft() (this will avoid rounding issues).
172         return getLeft() + m_right - m_left;
173     }
174     else
175     {
176         switch( m_refRighBottom )
177         {
178             case kLeftTop:
179             case kLeftBottom:
180                 return m_right;
181                 break;
182             case kRightTop:
183             case kRightBottom:
184                 return m_rBox.getWidth() + m_right - 1;
185                 break;
186         }
187         // Avoid a warning
188         return 0;
189     }
190 }
191
192
193 int Position::getBottom() const
194 {
195     if( m_yKeepRatio )
196     {
197         // Ratio mode
198         // The height of the control being constant, we can use the result of
199         // getTop() (this will avoid rounding issues).
200         return getTop() + m_bottom - m_top;
201     }
202     else
203     {
204         switch( m_refRighBottom )
205         {
206             case kLeftTop:
207             case kRightTop:
208                 return m_bottom;
209                 break;
210             case kLeftBottom:
211             case kRightBottom:
212                 return m_rBox.getHeight() + m_bottom - 1;
213                 break;
214         }
215         // Avoid a warning
216         return 0;
217     }
218 }
219
220
221 int Position::getWidth() const
222 {
223     return getRight() - getLeft() + 1;
224 }
225
226
227 int Position::getHeight() const
228 {
229     return getBottom() - getTop() + 1;
230 }
231
232
233 VarBox::VarBox( intf_thread_t *pIntf, int width, int height ):
234     Variable( pIntf ), m_width( width ), m_height( height )
235 {
236 }
237
238
239 int VarBox::getWidth() const
240 {
241     return m_width;
242 }
243
244
245 int VarBox::getHeight() const
246 {
247     return m_height;
248 }
249
250
251 void VarBox::setSize( int width, int height )
252 {
253     m_width = width;
254     m_height = height;
255     notify();
256 }
257