wxRectTracker
RectTrackerRatio.cpp
Go to the documentation of this file.
00001 /* ****************************************************************************
00002  * RectTrackerRatio.cpp                                                       *
00003  *                                                                            *
00004  * (c) 2004-2008 - Rémi Peyronnet <remi+rphoto@via.ecp.fr>                    *
00005  *                                                                            *
00006  * RectTracker was originally designed for RPhoto, but can be used separately *
00007  * It is a control similar to the CRectTracker of MS MFC.                     *
00008  *                                                                            *
00009  * Licence : wxWindows (based on L-GPL)                                       *
00010  *                                                                            *
00011  * ************************************************************************** */
00012 
00013 
00014 #include "RectTrackerRatio.h"
00015 
00016 IMPLEMENT_CLASS(wxRectTrackerRatio, wxRectTracker)
00017 
00018 wxRectTrackerRatio::wxRectTrackerRatio(wxWindow * parent, wxFrame * frame) 
00019             : wxRectTracker(parent, frame)
00020 {
00021     SetRatio(0);
00022     SetGuideRatio(0);
00023     SetOrientation(0);
00024 }
00025 
00026 wxRectTrackerRatio::~wxRectTrackerRatio()
00027 {
00028 }
00029 
00030 long wxRectTrackerRatio::CalcRectDist(wxRect r1, wxRect r2)
00031 {
00032     int d;
00033     d = 0;
00034     d += (r1.x - r2.x) * (r1.x - r2.x);
00035     d += (r1.y - r2.y) * (r1.y - r2.y);
00036     d += (r1.width - r2.width) * (r1.width - r2.width);
00037     d += (r1.height - r2.height) * (r1.height - r2.height);
00038     return d;
00039 }
00040 
00041 wxRect wxRectTrackerRatio::CalcRectNearer(wxRect rr, wxRect r1, wxRect r2)
00042 {
00043     if (CalcRectDist(rr, r2) < CalcRectDist(rr, r1))
00044              return r2;
00045         else return r1;
00046 }
00047 
00048 void wxRectTrackerRatio::AdjustTrackerRectRatio(wxRect &curRect, int handler, bool expand)
00049 {
00050     wxRect rectPort, rectLand, rectWidth, rectHeight, rectTmp;
00051 
00052     if (ratio <= 0) return;
00053 
00054     // Calc the best two rects
00055     // - rectWidth
00056     rectPort = rectLand = curRect;
00057     rectPort.width = (int) (rectPort.height * ratio);
00058     rectLand.width = (int) (rectLand.height / ratio);
00059     if ((handler & RT_HANDLER_MID_LEFT) != 0)
00060     {
00061         rectPort.x += curRect.width - rectPort.width;
00062         rectLand.x += curRect.width - rectLand.width;
00063     }
00064     //   * Portrait or Landscape ?
00065     switch(orientation)
00066     {
00067     case -1:    rectTmp = rectLand; break;
00068     case 1:     rectTmp = rectPort; break;
00069     default:    rectTmp = CalcRectNearer(curRect, rectPort, rectLand); break;
00070     }
00071     rectWidth = rectTmp;
00072     // - rectHeight (ugly cut'n paste)
00073     rectPort = rectLand = curRect;
00074     rectPort.height = (int) (rectPort.width / ratio);
00075     rectLand.height = (int) (rectLand.width * ratio);
00076     if ((handler & RT_HANDLER_TOP_MID) != 0)
00077     {
00078         rectPort.y += curRect.height - rectPort.height;
00079         rectLand.y += curRect.height - rectLand.height;
00080     }
00081     //   * Portrait or Landscape ?
00082     switch(orientation)
00083     {
00084     case -1:    rectTmp = rectLand; break;
00085     case 1:     rectTmp = rectPort; break;
00086     default:    rectTmp = CalcRectNearer(curRect, rectPort, rectLand); break;
00087     }
00088     rectHeight = rectTmp;
00089 
00090     switch(handler)
00091     {
00092     case RT_HANDLER_TOP_MID:
00093     case RT_HANDLER_BOTTOM_MID:
00094         curRect = (expand)?rectWidth:rectHeight;
00095         break;
00096     case RT_HANDLER_MID_RIGHT:
00097     case RT_HANDLER_MID_LEFT:
00098         curRect = (expand)?rectHeight:rectWidth;
00099         break;
00100     default:
00101         if (!expand)
00102         {
00103             if (curRect.height < rectHeight.height) rectHeight.height = -12000;
00104             if (curRect.width < rectWidth.width) rectWidth.width = -12000;
00105         }
00106         curRect = CalcRectNearer(curRect, rectHeight, rectWidth);
00107     }
00108 
00109 }
00110 
00111 void wxRectTrackerRatio::AdjustTrackerRectFixed(wxRect &curRect, int handler)
00112 {
00113     // Adjust Width
00114     curRect.x += (curRect.width - fixedWidth);
00115     curRect.width = fixedWidth;
00116     if (curRect.x < m_maxRect.x) curRect.x = m_maxRect.x;
00117     if ((curRect.x + curRect.width) > (m_maxRect.x + m_maxRect.width)) curRect.x = m_maxRect.x + m_maxRect.width - curRect.width;
00118     // Adjust Height
00119     curRect.y += (curRect.height - fixedHeight);
00120     curRect.height = fixedHeight;
00121     if (curRect.y < m_maxRect.y) curRect.y = m_maxRect.y;
00122     if ((curRect.y + curRect.height) > (m_maxRect.y + m_maxRect.height)) curRect.y = m_maxRect.y + m_maxRect.height - curRect.height;
00123 }
00124 
00125 void wxRectTrackerRatio::AdjustTrackerRect(wxRect &curRect, int handler)
00126 {
00127     wxRectTracker::AdjustTrackerRect(curRect, handler);
00128     if ((fixedWidth > 0 ) && (fixedHeight > 0))
00129     {
00130         AdjustTrackerRectFixed(curRect, handler);
00131     }    
00132     if (ratio > 0)
00133     {
00134         // First Pass
00135         AdjustTrackerRectRatio(curRect, handler, true);
00136         // Second Pass - Adjust if new rect has been out of the max rect.
00137         wxRectTracker::AdjustTrackerRect(curRect, handler);
00138         AdjustTrackerRectRatio(curRect, handler, false);
00139     }
00140 }
00141 
00142 void wxRectTrackerRatio::SetRatio(double ratio)
00143 {
00144     this->fixedWidth = this->fixedHeight = -1; // Remove fixed mode
00145     if ((ratio > 0) && (ratio < 1)) ratio = 1 / ratio;
00146     this->ratio = ratio;
00147     SetHandlerMask(RT_MASK_ALL);
00148 }
00149 
00150 
00151 void wxRectTrackerRatio::SetGuideRatio(double ratio)
00152 {
00153     if (ratio > 1) ratio = 1 / ratio;
00154     this->guideRatio = ratio;
00155 }
00156 
00157 void wxRectTrackerRatio::SetOrientation(int orientation)
00158 {
00159     this->orientation = orientation;
00160     if (this->fixedWidth != -1) SetFixedSize(this->fixedWidth, this->fixedHeight);
00161 }
00162 
00163 void wxRectTrackerRatio::SetFixedSize(int width, int height)
00164 {
00165     int tmp;
00166     this->fixedWidth = width;
00167     this->fixedHeight = height;
00168     // Switch orientation if one was given
00169     if ( ((orientation == -1) && (this->fixedWidth > this->fixedHeight)) ||
00170          ((orientation == 1) && (this->fixedWidth < this->fixedHeight))   )
00171     {
00172         tmp = this->fixedWidth;
00173         this->fixedWidth = this->fixedHeight;
00174         this->fixedHeight = tmp;
00175     }
00176     SetHandlerMask(RT_MASK_NONE);
00177 }    
00178 
00179 
00180 // DrawRect operates with a wxPaintDC => Window coordinates
00181 void wxRectTrackerRatio::DrawRect(wxDC & dc, int x, int y, int w, int h)
00182 {
00183     wxRectTracker::DrawRect(dc, x, y, w, h);
00184     // Rect
00185     if (this->guideRatio != 0)
00186     {
00187         dc.SetBrush(*wxTRANSPARENT_BRUSH);
00188         dc.SetPen(*wxGREY_PEN);
00189         dc.DrawLine(x  ,y + h*this->guideRatio  ,x+w,y + h*this->guideRatio   );
00190         dc.DrawLine(x  ,y + h*(1-this->guideRatio)  ,x+w,y + h*(1-this->guideRatio));
00191         dc.DrawLine(x+w*this->guideRatio  ,y  ,x+w*this->guideRatio  ,y+h);
00192         dc.DrawLine(x+w*(1-this->guideRatio)  ,y  ,x+w*(1-this->guideRatio)  ,y+h);
00193     }
00194 }
00195 
00196 // DrawTracker operates with the parent's wxWindowDC => Parent coordinates
00197 void wxRectTrackerRatio::DrawTracker(wxDC & dc, int x, int y, int w, int h)
00198 {
00199     wxRectTracker::DrawTracker(dc, x, y, w, h);
00200     if (this->guideRatio != 0)
00201     {
00202         /* useless with wxEvtHandler
00203         // Convert coordinates if scrolled
00204         if (wxDynamicCast(GetParent(),wxScrolledWindow) != NULL)
00205         {
00206             wxDynamicCast(GetParent(),wxScrolledWindow)->CalcScrolledPosition(x, y, &x, &y);
00207         }
00208         */
00209         // Inverted Rect
00210         dc.SetLogicalFunction(wxINVERT);
00211         dc.SetBrush(*wxTRANSPARENT_BRUSH);
00212         dc.SetPen(*wxGREY_PEN);
00213         dc.DrawLine(x  ,y + h*this->guideRatio  ,x+w,y + h*this->guideRatio   );
00214         if (this->guideRatio != 0.5) dc.DrawLine(x  ,y + h*(1-this->guideRatio)  ,x+w,y + h*(1-this->guideRatio));
00215         dc.DrawLine(x+w*this->guideRatio  ,y  ,x+w*this->guideRatio  ,y+h);
00216         if (this->guideRatio != 0.5) dc.DrawLine(x+w*(1-this->guideRatio)  ,y  ,x+w*(1-this->guideRatio)  ,y+h);
00217         dc.SetLogicalFunction(wxCOPY);
00218     }
00219 }
00220