00001
00002
00003
00004
00005
00013 #ifndef HLAYOUT_H
00014 #define HLAYOUT_H
00015
00016 #include "HArray.h"
00017 #include "HWindow.h"
00018
00019 struct HLayoutInfo
00020 {
00021 uint32 uFlags;
00022 HPoint dimMin;
00023 HRect rBounds;
00024 HWidget * pWidget;
00025 };
00032 class HLayout : public HWindow<HLayout>,
00033 public HArray<HLayoutInfo>
00034 {
00035 typedef HWindow<HLayout> base_class;
00036 static StringPtr ClassName(void) { return "HLayout"; }
00037 public:
00038 typedef enum
00039 {
00040 FIXED = 0,
00041 GROW_X = 1 << 0,
00042 MOVE_X = 1 << 1,
00043 GROW_Y = 1 << 2,
00044 MOVE_Y = 1 << 3,
00045
00046 GROW_XY = (GROW_X | GROW_Y),
00047 MOVE_XY = (MOVE_X | MOVE_Y),
00048
00049 DOCK_LEFT = 1 << 4,
00050 DOCK_TOP = 1 << 5,
00051 DOCK_RIGHT = 1 << 6,
00052 DOCK_BOTTOM = 1 << 7,
00053
00054 DOCK_ALL = (DOCK_LEFT | DOCK_TOP | DOCK_RIGHT | DOCK_BOTTOM)
00055 } Style;
00056
00057
00058
00059 protected:
00060 typedef HArray<HLayoutInfo>::iterator InfoIter;
00061
00063 HRect m_rClient;
00064
00065
00066
00067 public:
00068 HLayout(void) : base_class()
00069 {
00070 m_rClient.SetEmpty();
00071 this->clear();
00072 }
00073
00074 virtual
00075 ~HLayout(void)
00076 { }
00077
00078
00079
00080 public:
00090 ErrCode
00091 Add(HWidget * pWidget, uint32 uFlags = FIXED, int32 nMinXDim = 0, int32 nMinYDim = 0)
00092 {
00093 HLayoutInfo info;
00094 HRect rBounds;
00095 ErrCode ec = HError::NoError();
00096
00097
00098 ASSERT( !((uFlags & MOVE_X) && (uFlags & GROW_X)) );
00099 ASSERT( !((uFlags & MOVE_Y) && (uFlags & GROW_Y)) );
00100
00101 try
00102 {
00103 if (NULL_PTR(pWidget))
00104 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00105
00106 if (findWidget(pWidget) != Humble::BAD_INDEX)
00107 HError::Throw(ERR_DUPLICATE, __FILE__, __LINE__);
00108
00109 pWidget->GetClientBounds(rBounds);
00110
00111 DEBUG_LOG("HLayout::Add() => widget #%lu has bounds %s\n",
00112 GetSize(), rBounds.ToString());
00113
00114 MEM_ZERO(&info, sizeof(HLayoutInfo));
00115
00116 info.uFlags = uFlags;
00117 info.rBounds = rBounds;
00118 info.pWidget = pWidget;
00119 if (nMinXDim > 0)
00120 info.dimMin.x = nMinXDim;
00121 if (nMinYDim > 0)
00122 info.dimMin.y = nMinYDim;
00123
00124 this->Append(info);
00125 }
00126 catch (const std::exception & e)
00127 {
00128 DEBUG_LOG("HLayout[%p]::Add() => caught %s\n", this, e.what());
00129 if ((ec = ErrCode( HError::GetLastError() )) == NO_ERROR)
00130 ec = HError::Set(ERR_STL_EXCEPTION, __FILE__, __LINE__);
00131 }
00132
00133 return ec;
00134 }
00144 virtual ErrCode
00145 Draw(HRect & rDirty)
00146 {
00147 ErrCode ec = HError::NoError();
00148 HRect rClient;
00149
00150 if (GetBounds(rClient))
00151 {
00152 (void) m_gc.SetColors(m_clrBG, m_clrFG);
00153 (void) m_gc.FillRect(rClient);
00154 }
00155
00156 return ec;
00157 }
00164 ErrCode
00165 Remove(HWidget * pWidget)
00166 {
00167 uint32 udx;
00168 ErrCode ec = HError::NoError();
00169
00170 try
00171 {
00172 if (NULL_PTR(pWidget))
00173 HError::Throw(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00174
00175 if ((udx = findWidget(pWidget)) == Humble::BAD_INDEX)
00176 HError::Throw(ERR_NOT_FOUND, __FILE__, __LINE__);
00177
00178 this->RemoveAt(udx);
00179 DEBUG_LOG("HLayout::Remove() => removed widget #%lu.\n", udx);
00180 }
00181 catch (const std::exception & e)
00182 {
00183 DEBUG_LOG("HLayout[%p]::Add() => caught %s\n", this, e.what());
00184 if ((ec = ErrCode( HError::GetLastError() )) == NO_ERROR)
00185 ec = HError::Set(ERR_STL_EXCEPTION, __FILE__, __LINE__);
00186 }
00187
00188 return ec;
00189 }
00195 virtual ErrCode
00196 UpdateLayout(void)
00197 {
00198 HRect rClient;
00199 ErrCode ec = HError::NoError();
00200
00201 if (!GetClientBounds(rClient) || rClient.IsEmpty())
00202 {
00203 DEBUG_LOG("HLayout::UpdateLayout() => invalid client\n");
00204 return ec;
00205 }
00206
00207 if (m_rClient.IsEmpty())
00208 {
00209 m_rClient = rClient;
00210 DEBUG_LOG( "HLayout::UpdateLayout() => initial client is %s\n",
00211 m_rClient.ToString());
00212 return ec;
00213 }
00214
00215 const int32 nXDelta = rClient.x2 - m_rClient.x2;
00216 const int32 nYDelta = rClient.y2 - m_rClient.y2;
00217
00218 for (InfoIter it = this->begin(); it != this->end(); ++it)
00219 {
00220 HLayoutInfo info = *it;
00221
00222 if (NULL_PTR(info.pWidget))
00223 {
00224 DEBUG_LOG("HLayout::UpdateLayout() => widget #%lu is NULL!\n",
00225 indexOf(it));
00226 continue;
00227 }
00228
00229 if (info.uFlags & GROW_X)
00230 info.rBounds.x2 += nXDelta;
00231 else if (info.uFlags & MOVE_X)
00232 {
00233 info.rBounds.x1 += nXDelta;
00234 info.rBounds.x2 += nXDelta;
00235 }
00236
00237 if (info.uFlags & GROW_Y)
00238 info.rBounds.y2 += nYDelta;
00239 else if (info.uFlags & MOVE_Y)
00240 {
00241 info.rBounds.y1 += nYDelta;
00242 info.rBounds.y2 += nYDelta;
00243 }
00244
00245 if (info.uFlags & DOCK_LEFT)
00246 info.rBounds.x1 = rClient.x1;
00247 if (info.uFlags & DOCK_TOP)
00248 info.rBounds.y1 = rClient.y1;
00249 if (info.uFlags & DOCK_RIGHT)
00250 info.rBounds.x2 = rClient.x2;
00251 if (info.uFlags & DOCK_BOTTOM)
00252 info.rBounds.y2 = rClient.y2;
00253
00254
00255
00256 if (info.dimMin.x > 0 && info.rBounds.GetWidth() < info.dimMin.x)
00257 info.rBounds.x2 = info.rBounds.x1 + info.dimMin.x;
00258
00259 if (info.dimMin.y > 0 && info.rBounds.GetHeight() < info.dimMin.y)
00260 info.rBounds.y2 = info.rBounds.y1 + info.dimMin.y;
00261
00262 if (info.rBounds.IsNotEmpty() && info.rBounds != it->rBounds)
00263 {
00264 *it = info;
00265 info.pWidget->SetBounds(info.rBounds);
00266 }
00267 }
00268
00269 m_rClient = rClient;
00270 return ec;
00271 }
00272 protected:
00278 uint32
00279 findWidget(HWidget * pWidget)
00280 {
00281 uint32 udx = 0;
00282 for (InfoIter it = this->begin(); it != this->end(); ++it, ++udx)
00283 if (it->pWidget == pWidget)
00284 return udx;
00285
00286 return Humble::BAD_INDEX;
00287 }
00288
00289
00290
00291 public:
00297 inline HWidget * GetNthWidget(uint32 udx) const
00298 { return validIndex(udx) ? at(udx).pWidget : NULL; }
00305 ErrCode SetWidgetMinHeight(HWidget * pWidget, int32 nMinYDim = 0)
00306 {
00307 ErrCode ec = HError::NoError();
00308
00309 if (nMinYDim >= 0 &&
00310 GOOD_PTR(pWidget))
00311 {
00312 uint32 udx = findWidget(pWidget);
00313
00314 if (udx != Humble::BAD_INDEX)
00315 at(udx).dimMin.y = nMinYDim;
00316 else
00317 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00318 }
00319 else
00320 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00321
00322 return ec;
00323 }
00330 ErrCode SetWidgetMinWidth(HWidget * pWidget, int32 nMinXDim = 0)
00331 {
00332 ErrCode ec = HError::NoError();
00333
00334 if (nMinXDim >= 0 &&
00335 GOOD_PTR(pWidget))
00336 {
00337 uint32 udx = findWidget(pWidget);
00338
00339 if (udx != Humble::BAD_INDEX)
00340 at(udx).dimMin.x = nMinXDim;
00341 else
00342 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00343 }
00344 else
00345 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00346
00347 return ec;
00348 }
00356 ErrCode SetWidgetMinSize(HWidget * pWidget, int32 nMinXDim = 0, int32 nMinYDim = 0)
00357 {
00358 ErrCode ec = HError::NoError();
00359
00360 if (nMinXDim >= 0 &&
00361 nMinYDim >= 0 &&
00362 GOOD_PTR(pWidget))
00363 {
00364 uint32 udx = findWidget(pWidget);
00365
00366 if (udx != Humble::BAD_INDEX)
00367 at(udx).dimMin = HPoint(nMinXDim, nMinYDim);
00368 else
00369 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00370 }
00371 else
00372 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00373
00374 return ec;
00375 }
00382 ErrCode SetWidgetStyle(HWidget * pWidget, uint32 uFlags)
00383 {
00384 ErrCode ec = HError::NoError();
00385
00386 if (GOOD_PTR(pWidget))
00387 {
00388 uint32 udx = findWidget(pWidget);
00389
00390 if (udx != Humble::BAD_INDEX)
00391 at(udx).uFlags = uFlags;
00392 else
00393 ec = HError::Set(ERR_NOT_FOUND, __FILE__, __LINE__);
00394 }
00395 else
00396 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00397
00398 return ec;
00399 }
00400
00401
00402
00403 protected:
00404 inline uint32 indexOf(InfoIter it)
00405 { return (uint32) distance(this->begin(), it); }
00406 };
00407
00408 #endif // HLAYOUT_H
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422