00001
00002
00003
00004
00005
00006
00007 #include "math.h"
00008 #include "stdinc.h"
00009 #include "icon.h"
00010 #include "eventhandler.h"
00011 #include "widgets.h"
00012 #include "menu.h"
00013 #include "widget.h"
00014 #include "window.h"
00015 #include "dockwindow.h"
00016 #include "exception.h"
00017 namespace MWidgets
00018 {
00019
00020
00021 DockWindow::DockWindow():Widget()
00022 {
00023 m_pParent=NULL;
00024 m_bDrawGripper=true;
00025 m_bDrag=false;
00026 m_ptPrevMousePos.x=m_ptPrevMousePos.y=0;
00027 m_wDotPatternBmp[0] = 0x00aa;
00028 m_wDotPatternBmp[1] = 0x0055;
00029 m_wDotPatternBmp[2] = 0x00aa;
00030 m_wDotPatternBmp[3] = 0x0055;
00031 m_wDotPatternBmp[4] = 0x00aa;
00032 m_wDotPatternBmp[5] = 0x0055;
00033 m_wDotPatternBmp[6] = 0x00aa;
00034 m_wDotPatternBmp[7] = 0x0055;
00035 m_dpDocked=NONE_DOCK;
00036 m_fLayout=1.0f;
00037 };
00038
00039 void DockWindow::Create(Widget* parent,int x,int y,int w,int h,string caption)
00040 {
00041 if(parent->GetType()==WINDOW)
00042 {
00043 DWORD styles=WS_POPUP | WS_THICKFRAME|WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
00044 if(caption.length()>0)
00045 {
00046 styles|=WS_CAPTION |WS_SYSMENU;
00047 m_bDrawGripper=false;
00048 }
00049 Widget::Create(x,y,w,h,caption,"MicroWidget",styles ,parent->GetHwnd(),WS_EX_TOOLWINDOW);
00050 m_pParent=(Window*)parent;
00051 SetParent(m_hWnd,NULL);
00052 m_dpDocked=NONE_DOCK;
00053 m_fLayout=1.0f;
00054 m_bDrag=false;
00055 m_bActive=true;
00056 }
00057
00058 else
00059 EXCEPT("DockWindow::Create - wrong parent type!");
00060 };
00061
00062 WIDGET_TYPE DockWindow::GetType()
00063 {
00064 return DOCKWINDOW;
00065 };
00066
00067 void DockWindow::DrawGripper()
00068 {
00069 if(m_bDrawGripper)
00070 {
00071 RECT rc;
00072 GetClientRect(m_hWnd, &rc);
00073 HDC hdc=GetWindowDC(m_hWnd);
00074 rc.left=3;
00075 rc.top=3;
00076 rc.bottom+=3;
00077 rc.right=8;
00078 HBRUSH b=CreateSolidBrush( GetSysColor(COLOR_BTNFACE));
00079 FillRect(hdc,&rc,b);
00080 DeleteObject(b);
00081 DrawEdge(hdc,&rc , BDR_RAISEDINNER, BF_RECT);
00082 ReleaseDC(m_hWnd,hdc);
00083 };
00084 };
00085
00086 LRESULT DockWindow::OnMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00087 {
00088 RECT rc;
00089 RECT rc2;
00090 POINT pt;
00091 LRESULT rez;
00092 switch(message)
00093 {
00094 case WM_ENABLE:
00095 if(IsWindowEnabled(m_pParent->GetHwnd())==FALSE)
00096 return 0;
00097 break;
00098 case WM_EXITSIZEMOVE:
00099 if(m_dpDocked!=NONE_DOCK)
00100 m_pParent->UpdateLayout(this);
00101 break;
00102 case WM_SIZE:
00103 if(m_dpDocked==NONE_DOCK)
00104 {
00105
00106 GetWindowRect(m_hWnd,&m_rPrevWndFloatSize);
00107 }
00108 break;
00109 case WM_NCHITTEST:
00110 GetClientRect(hWnd, &rc);
00111 pt.x = GET_X_LPARAM(lParam);
00112 pt.y = GET_Y_LPARAM(lParam);
00113 ScreenToClient(hWnd,&pt);
00114 if(m_bDrawGripper)
00115 {
00116 if(pt.x>-5&&pt.x<0&&pt.y>3&&pt.y<(rc.bottom+3))
00117 {
00118 return HTCAPTION;
00119 }
00120 }
00121
00122
00123 rez = Widget::OnMessage(hWnd, message, wParam, lParam);
00124 switch(m_dpDocked)
00125 {
00126 case LEFT_DOCK:
00127 if(rez==HTTOP||rez==HTTOPLEFT||rez==HTTOPRIGHT||rez==HTBOTTOMLEFT||rez==HTBOTTOMRIGHT||rez==HTLEFT||(rez==HTBOTTOM&&m_pParent->IsLast(this)))
00128 return HTBORDER;
00129 break;
00130 case TOP_DOCK:
00131 if(rez==HTTOP||rez==HTTOPLEFT||rez==HTTOPRIGHT||rez==HTBOTTOMLEFT||rez==HTBOTTOMRIGHT||rez==HTLEFT||(rez==HTRIGHT&&m_pParent->IsLast(this)))
00132 return HTBORDER;
00133 break;
00134 case RIGHT_DOCK:
00135 if(rez==HTTOP||rez==HTTOPLEFT||rez==HTTOPRIGHT||rez==HTBOTTOMLEFT||rez==HTBOTTOMRIGHT||rez==HTRIGHT||(rez==HTBOTTOM&&m_pParent->IsLast(this)))
00136 return HTBORDER;
00137 break;
00138 case BOTTOM_DOCK:
00139 if(rez==HTBOTTOM||rez==HTTOPLEFT||rez==HTTOPRIGHT||rez==HTBOTTOMLEFT||rez==HTBOTTOMRIGHT||rez==HTLEFT||(rez==HTRIGHT&&m_pParent->IsLast(this)))
00140 return HTBORDER;
00141 break;
00142 case NONE_DOCK:
00143 break;
00144 };
00145 break;
00146 case WM_NCPAINT:
00147 DrawGripper();
00148 break;
00149 case WM_NCCALCSIZE:
00150 if(m_bDrawGripper)
00151 {
00152
00153 RECT *pRect = (RECT*)lParam;
00154 pRect->left +=5;
00155 }
00156
00157 break;
00158 case WM_NCLBUTTONDOWN:
00159 if (wParam == HTCAPTION)
00160 {
00161
00162
00163 m_bDrag=true;
00164
00165
00166 GetCursorPos(&m_ptPrevMousePos);
00167
00168
00169 SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
00170
00171
00172 SetCapture(hWnd);
00173
00174
00175 rc.right=m_rPrevWndFloatSize.right-m_rPrevWndFloatSize.left;
00176 rc.bottom=m_rPrevWndFloatSize.bottom-m_rPrevWndFloatSize.top;
00177 rc.left=m_ptPrevMousePos.x;
00178 rc.top=m_ptPrevMousePos.y;
00179 DrawDragFrame(&rc);
00180 m_rPrevRect=rc;
00181
00182 return 0;
00183 }
00184 break;
00185 case WM_MOUSEMOVE:
00186 if(m_bDrag)
00187 {
00188 POINT pt;
00189
00190
00191 GetCursorPos(&pt);
00192
00193
00194 if (pt.x != m_ptPrevMousePos.x || pt.y != m_ptPrevMousePos.y)
00195 {
00196
00197 DrawDragFrame(&m_rPrevRect);
00198
00199
00200 m_ptPrevMousePos.x = pt.x;
00201 m_ptPrevMousePos.y = pt.y;
00202
00203
00204 if(CheckDockPos(&m_ptPrevMousePos,&rc2)!=NONE_DOCK)
00205 {
00206 DrawDragFrame(&rc2);
00207 m_rPrevRect=rc2;
00208 }
00209 else
00210 {
00211 rc.right=m_rPrevWndFloatSize.right-m_rPrevWndFloatSize.left;
00212 rc.bottom=m_rPrevWndFloatSize.bottom-m_rPrevWndFloatSize.top;
00213 rc.left=m_ptPrevMousePos.x;
00214 rc.top=m_ptPrevMousePos.y;
00215 DrawDragFrame(&rc);
00216 m_rPrevRect=rc;
00217 }
00218 }
00219 };
00220 return 0;
00221 case WM_CANCELMODE:
00222 case WM_LBUTTONUP:
00223 if(m_bDrag)
00224 {
00225 POINT pt;
00226 RECT rc;
00227
00228
00229 DrawDragFrame(&m_rPrevRect);
00230
00231
00232 GetCursorPos(&pt);
00233
00234 m_bDrag=false;
00235
00236 m_ptPrevMousePos.x = pt.x;
00237 m_ptPrevMousePos.y = pt.y;
00238
00239
00240 DOCKPOS dpos;
00241 dpos=CheckDockPos(&m_ptPrevMousePos,&rc);
00242 if((message!=WM_CANCELMODE)&&(dpos!=NONE_DOCK)&&(dpos!=m_dpDocked))
00243 {
00244 UnDock();
00245 m_dpDocked=dpos;
00246 SetWindowPos(hWnd, HWND_TOP, rc.left, rc.top, rc.right, rc.bottom,SWP_DRAWFRAME|SWP_SHOWWINDOW|SWP_FRAMECHANGED);
00247 Dock(dpos);
00248 }
00249
00250 else if((message!=WM_CANCELMODE)&&(dpos==NONE_DOCK))
00251 {
00252 UnDock();
00253 SetWindowPos(hWnd, HWND_TOP, pt.x, pt.y, m_rPrevWndFloatSize.right-m_rPrevWndFloatSize.left, m_rPrevWndFloatSize.bottom-m_rPrevWndFloatSize.top,SWP_DRAWFRAME|SWP_SHOWWINDOW|SWP_FRAMECHANGED);
00254 }
00255
00256
00257 InvalidateRect(hWnd,NULL,TRUE);
00258
00259 ReleaseCapture();
00260 }
00261 break;
00262 case WM_DESTROY:
00263 UnDock();
00264 break;
00265 }
00266 return Widget::OnMessage(hWnd, message, wParam, lParam);
00267 };
00268
00269 void DockWindow::DrawDragFrame(RECT* pRect)
00270 {
00271 HDC hdc;
00272 HBITMAP hbm;
00273 HBRUSH hbrush;
00274 HANDLE hbrushOrig;
00275 int border;
00276 RECT dragRecPlacement;
00277 memcpy(&dragRecPlacement,pRect,sizeof(RECT));
00278
00279 hdc = GetDC(0);
00280
00281 const WORD *bitmap;
00282
00283
00284 border = 3;
00285 bitmap = &m_wDotPatternBmp[0];
00286
00287
00288
00289 hbm = CreateBitmap(8, 8, 1, 1, bitmap);
00290 hbrush = CreatePatternBrush(hbm);
00291
00292
00293 SetBrushOrgEx(hdc, dragRecPlacement.left, dragRecPlacement.top, 0);
00294 hbrushOrig = SelectObject(hdc, hbrush);
00295
00296
00297
00298 int width, height;
00299
00300 width = dragRecPlacement.right;
00301 height = dragRecPlacement.bottom;
00302 PatBlt(hdc, dragRecPlacement.left + border, dragRecPlacement.top, width - border, border, PATINVERT);
00303 PatBlt(hdc, dragRecPlacement.left + width - border, dragRecPlacement.top + border, border, height - border, PATINVERT);
00304 PatBlt(hdc, dragRecPlacement.left, dragRecPlacement.top + height - border, width - border, border, PATINVERT);
00305 PatBlt(hdc, dragRecPlacement.left, dragRecPlacement.top, border, height - border, PATINVERT);
00306
00307
00308 SelectObject(hdc, hbrushOrig);
00309 DeleteObject(hbrush);
00310 DeleteObject(hbm);
00311 ReleaseDC(0, hdc);
00312
00313 };
00314
00315 DOCKPOS DockWindow::CheckDockPos(POINT* pPos,RECT* pRect)
00316 {
00317 RECT rc;
00318 POINT pt;
00319 RECT rc2={0,0,0,0};
00320 GetClientRect(m_pParent->GetHwnd(),&rc);
00321 pt.x=rc.left;
00322 pt.y=rc.top;
00323 ClientToScreen(m_pParent->GetHwnd(),&pt);
00324 rc.left=pt.x;
00325 rc.top=pt.y;
00326
00327 pt.x=rc.right;
00328 pt.y=rc.bottom;
00329 ClientToScreen(m_pParent->GetHwnd(),&pt);
00330 rc.right=pt.x;
00331 rc.bottom=pt.y;
00332
00333 HWND tempHwnd=FindWindowEx(m_pParent->GetHwnd(),NULL,STATUSCLASSNAME,NULL);
00334 if(tempHwnd)
00335 {
00336 GetWindowRect(tempHwnd,&rc2);
00337 rc.bottom=rc2.top;
00338 }
00339
00340
00341
00342 if(pPos->x>=rc.left&&pPos->x<=rc.left+10&&pPos->y>=rc.top&&pPos->y<=rc.bottom)
00343 {
00344 pRect->left=rc.left;
00345 pRect->top=rc.top+m_pParent->GetTopHeight();
00346 if(m_pParent->GetLeftWidth()>0)
00347 pRect->right=m_pParent->GetLeftWidth();
00348 else
00349 pRect->right=50;
00350
00351 if(m_pParent->GetLeftHeight()>0)
00352 pRect->bottom=m_pParent->GetLeftHeight()-m_pParent->GetBottomHeight()-m_pParent->GetTopHeight();
00353 else
00354 pRect->bottom=(rc.bottom-rc.top)-m_pParent->GetBottomHeight()-m_pParent->GetTopHeight();
00355 return LEFT_DOCK;
00356 }
00357 else if(pPos->x>=(rc.right-10)&&pPos->x<=rc.right&&pPos->y>=rc.top&&pPos->y<=rc.bottom)
00358 {
00359 if(m_pParent->GetRightWidth()>0)
00360 pRect->right=m_pParent->GetRightWidth();
00361 else
00362 pRect->right=50;
00363 pRect->left=rc.right-pRect->right;
00364 pRect->top=rc.top+m_pParent->GetTopHeight();
00365 if(m_pParent->GetRightHeight()>0)
00366 pRect->bottom=m_pParent->GetRightHeight()-m_pParent->GetBottomHeight()-m_pParent->GetTopHeight();
00367 else
00368 pRect->bottom=(rc.bottom-rc.top)-m_pParent->GetBottomHeight()-m_pParent->GetTopHeight();
00369 return RIGHT_DOCK;
00370 }
00371 else if(pPos->x>=rc.left&&pPos->x<=rc.right&&pPos->y>=rc.top&&pPos->y<=rc.top+10)
00372 {
00373 pRect->left=rc.left+m_pParent->GetLeftWidth();
00374 pRect->top=rc.top;
00375 if(m_pParent->GetTopWidth()>0)
00376 pRect->right=m_pParent->GetTopWidth()-m_pParent->GetRightWidth()-m_pParent->GetLeftWidth();
00377 else
00378 pRect->right=(rc.right-rc.left)-m_pParent->GetRightWidth()-m_pParent->GetLeftWidth();
00379 if(m_pParent->GetTopHeight()>0)
00380 pRect->bottom=m_pParent->GetTopHeight();
00381 else
00382 pRect->bottom=50;
00383 return TOP_DOCK;
00384 }
00385 else if(pPos->x>=rc.left&&pPos->x<=rc.right&&pPos->y>=rc.bottom-10&&pPos->y<=rc.bottom)
00386 {
00387 if(m_pParent->GetBottomHeight()>0)
00388 pRect->bottom=m_pParent->GetBottomHeight();
00389 else
00390 pRect->bottom=50;
00391 pRect->left=rc.left+m_pParent->GetLeftWidth();
00392 pRect->top=rc.bottom-pRect->bottom;
00393 if(m_pParent->GetBottomWidth()>0)
00394 pRect->right=m_pParent->GetBottomWidth()-m_pParent->GetRightWidth()-m_pParent->GetLeftWidth();
00395 else
00396 pRect->right=(rc.right-rc.left)-m_pParent->GetRightWidth()-m_pParent->GetLeftWidth();
00397 return BOTTOM_DOCK;
00398 }
00399 return NONE_DOCK;
00400 };
00401
00402 DOCKPOS DockWindow::GetDockPos()
00403 {
00404 return m_dpDocked;
00405 };
00406
00407 float DockWindow::GetLayout()
00408 {
00409 return m_fLayout;
00410 };
00411
00412 void DockWindow::SetLayout(float val)
00413 {
00414 m_fLayout=val;
00415 };
00416
00417 void DockWindow::UnDock()
00418 {
00419
00420 switch(m_dpDocked)
00421 {
00422 case LEFT_DOCK:
00423 m_pParent->UndockFromLeft(this);
00424 m_pParent->UpdateLayout();
00425 break;
00426 case TOP_DOCK:
00427 m_pParent->UndockFromTop(this);
00428 m_pParent->UpdateLayout();
00429 break;
00430 case RIGHT_DOCK:
00431 m_pParent->UndockFromRight(this);
00432 m_pParent->UpdateLayout();
00433 break;
00434 case BOTTOM_DOCK:
00435 m_pParent->UndockFromBottom(this);
00436 m_pParent->UpdateLayout();
00437 break;
00438 case NONE_DOCK:
00439 break;
00440 }
00441 m_dpDocked=NONE_DOCK;
00442 };
00443
00444 void DockWindow::Dock(DOCKPOS pos)
00445 {
00446 m_dpDocked=pos;
00447 switch(m_dpDocked)
00448 {
00449 case LEFT_DOCK:
00450 m_pParent->DockToLeft(this);
00451 m_pParent->UpdateLayout(this);
00452 break;
00453 case TOP_DOCK:
00454 m_pParent->DockToTop(this);
00455 m_pParent->UpdateLayout(this);
00456 break;
00457 case RIGHT_DOCK:
00458 m_pParent->DockToRight(this);
00459 m_pParent->UpdateLayout(this);
00460 break;
00461 case BOTTOM_DOCK:
00462 m_pParent->DockToBottom(this);
00463 m_pParent->UpdateLayout(this);
00464 break;
00465 case NONE_DOCK:
00466 break;
00467 };
00468 };
00469
00470 void DockWindow::DockToLeft()
00471 {
00472 UnDock();
00473 Dock(LEFT_DOCK);
00474 };
00475
00476 void DockWindow::DockToTop()
00477 {
00478 UnDock();
00479 Dock(TOP_DOCK);
00480 };
00481
00482 void DockWindow::DockToRight()
00483 {
00484 UnDock();
00485 Dock(RIGHT_DOCK);
00486 };
00487
00488 void DockWindow::DockToBottom()
00489 {
00490 UnDock();
00491 Dock(BOTTOM_DOCK);
00492 };
00493
00494 };