src/dockwindow.cpp

Go to the documentation of this file.
00001 /*
00002 * Copyright (c) 2006 by Kirill Kolodyazhniy.
00003 * See the file "license.terms" for information on usage and redistribution
00004 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
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                                         //store prev floating size
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                                 // disable sizing.
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                                         //create non client part
00153                                         RECT *pRect = (RECT*)lParam;
00154                                         pRect->left +=5;
00155                                 }
00156 
00157                                 break;
00158                         case WM_NCLBUTTONDOWN:
00159                                 if (wParam == HTCAPTION)
00160                                 {
00161 
00162                                         //enable drag mode
00163                                         m_bDrag=true;
00164 
00165                                         // Get mouse pointer position in screen coords
00166                                         GetCursorPos(&m_ptPrevMousePos);
00167 
00168                                         // Bring Docking Frame to the top
00169                                         SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
00170 
00171                                         // Capture the mouse
00172                                         SetCapture(hWnd);
00173 
00174                                         // Draw the drag rectangle around the current frame
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                                         // Get mouse pointer position in screen coords
00191                                         GetCursorPos(&pt);
00192 
00193                                         // Did the mouse move?
00194                                         if (pt.x != m_ptPrevMousePos.x || pt.y != m_ptPrevMousePos.y)
00195                                         {
00196                                                 // Erase the drag rectangle by XOR drawing it at the same position
00197                                                 DrawDragFrame(&m_rPrevRect);
00198 
00199                                                 // Save new mouse pointer position
00200                                                 m_ptPrevMousePos.x = pt.x;
00201                                                 m_ptPrevMousePos.y = pt.y;
00202 
00203                                                 // Draw the drag rectangle around the current frame
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                                         // Erase the drag rectangle by XOR drawing it at the same position
00229                                         DrawDragFrame(&m_rPrevRect);
00230 
00231                                         // Get mouse pointer position in screen coords
00232                                         GetCursorPos(&pt);
00233 
00234                                         m_bDrag=false;
00235                                         // Save new mouse pointer position
00236                                         m_ptPrevMousePos.x = pt.x;
00237                                         m_ptPrevMousePos.y = pt.y;
00238 
00239                                         // Dock window
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;// for saving undocked size
00246                                                 SetWindowPos(hWnd, HWND_TOP, rc.left, rc.top, rc.right, rc.bottom,SWP_DRAWFRAME|SWP_SHOWWINDOW|SWP_FRAMECHANGED);
00247                                                 Dock(dpos);
00248                                         }
00249                                         // Bring Docking Frame to the top and move
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                                         // Redraw window
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                 // Determine whether to draw a solid drag rectangle or checkered
00284                 border = 3;
00285                 bitmap = &m_wDotPatternBmp[0];
00286 
00287 
00288                 // Create a brush with the appropriate bitmap pattern to draw our drag rectangle
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                 // Draw the drag rectangle
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                 //remove prev docking
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 };

Generated on Thu Oct 26 13:47:45 2006 for MWidgets by  doxygen 1.4.7