/***************************************************************************** * position.cpp ***************************************************************************** * Copyright (C) 2003 the VideoLAN team * $Id$ * * Authors: Cyril Deguet * Olivier Teulière * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #include "position.hpp" const std::string VarBox::m_type = "box"; SkinsRect::SkinsRect( int left, int top, int right, int bottom ): m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom ) { } Position::Position( int left, int top, int right, int bottom, const GenericRect &rRect, Ref_t refLeftTop, Ref_t refRightBottom, bool xKeepRatio, bool yKeepRatio ): m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom ), m_rRect( rRect ), m_refLeftTop( refLeftTop ), m_refRighBottom( refRightBottom ), m_xKeepRatio( xKeepRatio ), m_yKeepRatio( yKeepRatio ) { // Here is how the resizing algorithm works: // // - if we "keep the ratio" (xkeepratio="true" in the XML), the relative // position of the control in the parent box (i.e. the given rRect) is // saved, and will be kept constant. The size of the control will not // be changed, only its position may vary. To do that, we consider the // part of the box to the left of the control (for an horizontal // resizing) and the part of the box to the right of the control, // and we make sure that the ratio between their widths is constant. // // - if we don't keep the ratio, the resizing algorithm is completely // different. We consider that the top left hand corner of the control // ("lefttop" attribute in the XML) is linked to one of the 4 corners // of the parent box ("lefttop", "leftbottom", "righttop" and // "rightbottom" values for the attribute). Same thing for the bottom // right hand corner ("rightbottom" attribute). When resizing occurs, // the linked corners will move together, and this will drive the // moving/resizing of the control. // Initialize the horizontal ratio if( m_xKeepRatio ) { // First compute the width of the box minus the width of the control int freeSpace = m_rRect.getWidth() - (m_right - m_left); // Instead of computing left/right, we compute left/(left+right), // which is more convenient in my opinion. if( freeSpace != 0 ) { m_xRatio = (double)m_left / (double)freeSpace; } else { // If the control has the same size as the box, we can't compute // the ratio in the same way (otherwise we would divide by zero). // So we consider that the intent was to keep the control centered // (if you are unhappy with this, go and fix your skin :)) m_xRatio = 0.5; } } // Initial the vertical ratio if( m_yKeepRatio ) { // First compute the height of the box minus the height of the control int freeSpace = m_rRect.getHeight() - (m_bottom - m_top); // Instead of computing top/bottom, we compute top/(top+bottom), // which is more convenient in my opinion. if( freeSpace != 0 ) { m_yRatio = (double)m_top / (double)freeSpace; } else { // If the control has the same size as the box, we can't compute // the ratio in the same way (otherwise we would divide by zero). // So we consider that the intent was to keep the control centered // (if you are unhappy with this, go and fix your skin :)) m_yRatio = 0.5; } } } int Position::getLeft() const { if( m_xKeepRatio ) { // Ratio mode // First compute the width of the box minus the width of the control int freeSpace = m_rRect.getWidth() - (m_right - m_left); return m_rRect.getLeft() + (int)(m_xRatio * freeSpace); } else { switch( m_refLeftTop ) { case kLeftTop: case kLeftBottom: return m_rRect.getLeft() + m_left; case kRightTop: case kRightBottom: return m_rRect.getLeft() + m_rRect.getWidth() + m_left - 1; } // Avoid a warning return 0; } } int Position::getTop() const { if( m_yKeepRatio ) { // Ratio mode // First compute the height of the box minus the height of the control int freeSpace = m_rRect.getHeight() - (m_bottom - m_top); return m_rRect.getTop() + (int)(m_yRatio * freeSpace); } else { switch( m_refLeftTop ) { case kLeftTop: case kRightTop: return m_rRect.getTop() + m_top; case kRightBottom: case kLeftBottom: return m_rRect.getTop() + m_rRect.getHeight() + m_top - 1; } // Avoid a warning return 0; } } int Position::getRight() const { if( m_xKeepRatio ) { // Ratio mode // The width of the control being constant, we can use the result of // getLeft() (this will avoid rounding issues). return getLeft() + m_right - m_left; } else { switch( m_refRighBottom ) { case kLeftTop: case kLeftBottom: return m_rRect.getLeft() + m_right; case kRightTop: case kRightBottom: return m_rRect.getLeft() + m_rRect.getWidth() + m_right - 1; } // Avoid a warning return 0; } } int Position::getBottom() const { if( m_yKeepRatio ) { // Ratio mode // The height of the control being constant, we can use the result of // getTop() (this will avoid rounding issues). return getTop() + m_bottom - m_top; } else { switch( m_refRighBottom ) { case kLeftTop: case kRightTop: return m_rRect.getTop() + m_bottom; case kLeftBottom: case kRightBottom: return m_rRect.getTop() + m_rRect.getHeight() + m_bottom - 1; } // Avoid a warning return 0; } } int Position::getWidth() const { return getRight() - getLeft() + 1; } int Position::getHeight() const { return getBottom() - getTop() + 1; } VarBox::VarBox( intf_thread_t *pIntf, int width, int height ): Variable( pIntf ), m_width( width ), m_height( height ) { } int VarBox::getWidth() const { return m_width; } int VarBox::getHeight() const { return m_height; } void VarBox::setSize( int width, int height ) { m_width = width; m_height = height; notify(); }