wxRectTracker
|
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