home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Dita / source / w32splitter.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  12.0 KB  |  490 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2004 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <stdafx.h>
  19. #include <vd2/Dita/w32control.h>
  20.  
  21. class VDUISplitterW32 : public VDUICustomControlW32 {
  22. public:
  23.     VDUISplitterW32();
  24.  
  25.     bool Create(IVDUIParameters *pParams);
  26.  
  27.     void PreLayoutBase(const VDUILayoutSpecs& constraints);
  28.     void PostLayoutBase(const vduirect& r);
  29.  
  30. protected:
  31.     LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
  32.     void OnPaint();
  33.     void OnLButtonDown(WPARAM wParam, int x, int y);
  34.     void OnLButtonUp(WPARAM wParam, int x, int y);
  35.     void OnMouseMove(WPARAM wParam, int x, int y);
  36.     void OnCaptureChanged(HWND hwndNewCapture);
  37.  
  38.     void DrawMovingSplitter();
  39.     void ConvertLocationToFraction();
  40.     void ConvertFractionToLocation();
  41.  
  42.     float    mFraction;
  43.     RECT    mSplitter;
  44.     int        mDragOffset;
  45.     bool    mbIsVertical;
  46. };
  47.  
  48. extern IVDUIWindow *VDCreateUISplitter() { return new VDUISplitterW32; }
  49.  
  50. VDUISplitterW32::VDUISplitterW32()
  51.     : mFraction(0.5f)
  52.     , mbIsVertical(true)
  53. {
  54. }
  55.  
  56. bool VDUISplitterW32::Create(IVDUIParameters *pParams) {
  57.     mbIsVertical = pParams->GetB(nsVDUI::kUIParam_IsVertical, false);
  58.     return VDUICustomControlW32::Create(pParams);
  59. }
  60.  
  61. void VDUISplitterW32::PreLayoutBase(const VDUILayoutSpecs& constraints) {
  62.     tChildren::iterator it(mChildren.begin()), itEnd(mChildren.end());
  63.  
  64.     for(; it != itEnd; ++it) {
  65.         IVDUIWindow *pWin = *it;
  66.  
  67.         pWin->PreLayout(constraints);
  68.  
  69.         mLayoutSpecs.minsize.include(pWin->GetLayoutSpecs().minsize);
  70.     }
  71. }
  72.  
  73. void VDUISplitterW32::PostLayoutBase(const vduirect& r) {
  74.     SetArea(r);
  75.     ConvertFractionToLocation();
  76.     InvalidateRect(mhwnd, NULL, TRUE);
  77.  
  78.     const vduirect rClient(GetClientArea());
  79.     tChildren::iterator it(mChildren.begin()), itEnd(mChildren.end());
  80.     IVDUIWindow *pWin;
  81.  
  82.     if (mbIsVertical) {
  83.         if (it != itEnd) {
  84.             pWin = *it;
  85.             ++it;
  86.  
  87.             pWin->Layout(vduirect(0, 0, mSplitter.left, rClient.bottom));
  88.         }
  89.         if (it != itEnd) {
  90.             pWin = *it;
  91.             ++it;
  92.  
  93.             pWin->Layout(vduirect(mSplitter.right, 0, rClient.right, rClient.bottom));
  94.         }
  95.     } else {
  96.         if (it != itEnd) {
  97.             pWin = *it;
  98.             ++it;
  99.  
  100.             pWin->Layout(vduirect(0, 0, rClient.right, mSplitter.top));
  101.         }
  102.         if (it != itEnd) {
  103.             pWin = *it;
  104.             ++it;
  105.  
  106.             pWin->Layout(vduirect(0, mSplitter.bottom, rClient.right, rClient.bottom));
  107.         }
  108.     }
  109. }
  110.  
  111. LRESULT VDUISplitterW32::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) {
  112.     switch(msg) {
  113.     case WM_PAINT:
  114.         OnPaint();
  115.         break;
  116.  
  117.     case WM_LBUTTONDOWN:
  118.         OnLButtonDown(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  119.         return 0;
  120.  
  121.     case WM_LBUTTONUP:
  122.         OnLButtonUp(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  123.         return 0;
  124.  
  125.     case WM_MOUSEMOVE:
  126.         OnMouseMove(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  127.         return 0;
  128.  
  129.     case WM_CAPTURECHANGED:
  130.         OnCaptureChanged((HWND)lParam);
  131.         return 0;
  132.  
  133.     case WM_SETCURSOR:
  134.         if ((HWND)wParam == mhwnd && LOWORD(lParam) == HTCLIENT) {
  135.             POINT pt;
  136.             GetCursorPos(&pt);
  137.             ScreenToClient(mhwnd, &pt);
  138.             SetCursor(LoadCursor(NULL, PtInRect(&mSplitter, pt) ? mbIsVertical ? IDC_SIZEWE : IDC_SIZENS : IDC_ARROW));
  139.             return TRUE;
  140.         }
  141.         break;
  142.     }
  143.     return VDUICustomControlW32::WndProc(msg, wParam, lParam);
  144. }
  145.  
  146. void VDUISplitterW32::OnPaint() {
  147.     PAINTSTRUCT ps;
  148.  
  149.     if (HDC hdc = BeginPaint(mhwnd, &ps)) {
  150.         if (mbIsVertical)
  151.             DrawEdge(hdc, &mSplitter, EDGE_RAISED, BF_LEFT|BF_RIGHT);
  152.         else
  153.             DrawEdge(hdc, &mSplitter, EDGE_RAISED, BF_TOP|BF_BOTTOM);
  154.  
  155.         EndPaint(mhwnd, &ps);
  156.     }
  157. }
  158.  
  159. void VDUISplitterW32::OnLButtonDown(WPARAM wParam, int x, int y) {
  160.     POINT pt={x,y};
  161.  
  162.     if (PtInRect(&mSplitter, pt)) {
  163.         if (mbIsVertical)
  164.             mDragOffset = mSplitter.left - x;
  165.         else
  166.             mDragOffset = mSplitter.top - y;
  167.         SetCapture(mhwnd);
  168.         LockWindowUpdate(mhwnd);
  169.         DrawMovingSplitter();        
  170.     }
  171. }
  172.  
  173. void VDUISplitterW32::OnLButtonUp(WPARAM wParam, int x, int y) {
  174.     if (GetCapture() == mhwnd)
  175.         ReleaseCapture();
  176. }
  177.  
  178. void VDUISplitterW32::OnMouseMove(WPARAM wParam, int x, int y) {
  179.     if (GetCapture() == mhwnd) {
  180.         RECT rClient;
  181.  
  182.         DrawMovingSplitter();
  183.         GetClientRect(mhwnd, &rClient);
  184.         if (mbIsVertical)
  185.             OffsetRect(&mSplitter, std::min<int>(rClient.right - GetSystemMetrics(SM_CXEDGE)*3, std::max<int>(0, mDragOffset + x)) - mSplitter.left, 0);
  186.         else
  187.             OffsetRect(&mSplitter, 0, std::min<int>(rClient.bottom - GetSystemMetrics(SM_CYEDGE)*3, std::max<int>(0, mDragOffset + y)) - mSplitter.top);
  188.         DrawMovingSplitter();
  189.     }
  190. }
  191.  
  192. void VDUISplitterW32::OnCaptureChanged(HWND hwndNewCapture) {
  193.     DrawMovingSplitter();
  194.     LockWindowUpdate(NULL);
  195.     ConvertLocationToFraction();
  196.     PostLayoutBase(mArea);
  197. }
  198.  
  199. void VDUISplitterW32::DrawMovingSplitter() {
  200.     if (HDC hdc = GetDCEx(mhwnd, NULL, DCX_LOCKWINDOWUPDATE|DCX_CACHE)) {
  201.         InvertRect(hdc, &mSplitter);
  202.         ReleaseDC(mhwnd, hdc);
  203.     }
  204. }
  205.  
  206. void VDUISplitterW32::ConvertLocationToFraction() {
  207.     const vduirect rClient(GetClientArea());
  208.  
  209.     if (mbIsVertical) {
  210.         const int w = rClient.width();
  211.         int sw = GetSystemMetrics(SM_CXEDGE) * 3;
  212.  
  213.         if (sw > w)
  214.             sw = w;
  215.  
  216.         if (sw >= w)
  217.             mFraction = 0;
  218.         else
  219.             mFraction = (float)mSplitter.left / (float)(w-sw);
  220.     } else {
  221.         const int h = rClient.height();
  222.         int sh = GetSystemMetrics(SM_CYEDGE) * 3;
  223.  
  224.         if (sh > h)
  225.             sh = h;
  226.  
  227.         if (sh >= h)
  228.             mFraction = 0;
  229.         else
  230.             mFraction = (float)mSplitter.top / (float)(h-sh);
  231.     }
  232.  
  233.     if (mFraction < 0)
  234.         mFraction = 0;
  235.     else if (mFraction > 1)
  236.         mFraction = 1;
  237. }
  238.  
  239. void VDUISplitterW32::ConvertFractionToLocation() {
  240.     const vduirect rClient(GetClientArea());
  241.  
  242.     if (mbIsVertical) {
  243.         const int w = rClient.width();
  244.         int sw = GetSystemMetrics(SM_CXEDGE) * 3;
  245.  
  246.         if (sw > w)
  247.             sw = w;
  248.  
  249.         const int x = (int)(0.5 + (w-sw)*mFraction);
  250.  
  251.         mSplitter.left = x;
  252.         mSplitter.right = x + sw;
  253.         mSplitter.top = rClient.top;
  254.         mSplitter.bottom = rClient.bottom;
  255.     } else {
  256.         const int h = rClient.height();
  257.         int sh = GetSystemMetrics(SM_CYEDGE) * 3;
  258.  
  259.         if (sh > h)
  260.             sh = h;
  261.  
  262.         const int y = (int)(0.5 + (h-sh)*mFraction);
  263.  
  264.         mSplitter.top = y;
  265.         mSplitter.bottom = y + sh;
  266.         mSplitter.left = rClient.left;
  267.         mSplitter.right = rClient.right;
  268.     }
  269. }
  270.  
  271. ///////////////////////////////////////////////////////////////////////////
  272.  
  273. class VDUISplitSetW32 : public VDUIWindow {
  274. public:
  275.     VDUISplitSetW32();
  276.  
  277.     bool Create(IVDUIParameters *pParams);
  278.  
  279.     void PreLayoutBase(const VDUILayoutSpecs& constraints);
  280.     void PostLayoutBase(const vduirect& r);
  281.  
  282. protected:
  283.     bool    mbIsVertical;
  284. };
  285.  
  286. extern IVDUIWindow *VDCreateUISplitSet() { return new VDUISplitSetW32; }
  287.  
  288. VDUISplitSetW32::VDUISplitSetW32()
  289.     : mbIsVertical(true)
  290. {
  291. }
  292.  
  293. bool VDUISplitSetW32::Create(IVDUIParameters *pParams) {
  294.     mbIsVertical = pParams->GetB(nsVDUI::kUIParam_IsVertical, false);
  295.     return VDUIWindow::Create(pParams);
  296. }
  297.  
  298. void VDUISplitSetW32::PreLayoutBase(const VDUILayoutSpecs& constraints) {
  299.     tChildren::iterator it(mChildren.begin()), itEnd(mChildren.end());
  300.  
  301.     for(; it != itEnd; ++it) {
  302.         IVDUIWindow *pWin = *it;
  303.  
  304.         pWin->PreLayout(constraints);
  305.  
  306.         mLayoutSpecs.minsize.include(pWin->GetLayoutSpecs().minsize);
  307.     }
  308. }
  309.  
  310. void VDUISplitSetW32::PostLayoutBase(const vduirect& r) {
  311.     SetArea(r);
  312.  
  313.     vduirect rClient(GetClientArea());
  314.     tChildren::iterator itBegin(mChildren.begin()), itEnd(mChildren.end());
  315.     IVDUIWindow *pWin;
  316.  
  317.     if (!mbIsVertical) {
  318.         if (itEnd != itBegin) {
  319.             while(--itEnd != itBegin) {
  320.                 pWin = *itEnd;
  321.  
  322.                 const vduirect rChild(pWin->GetArea());
  323.                 int w = rChild.width();
  324.                 int h = rChild.height();
  325.  
  326.                 rClient.right -= w;
  327.  
  328.                 pWin->SetArea(vduirect(rClient.right, rClient.top, rClient.right + w, rClient.bottom));
  329.             }
  330.  
  331.             if (rClient.right < rClient.left)
  332.                 rClient.right = rClient.left;
  333.  
  334.             pWin = *itEnd;
  335.             pWin->SetArea(rClient);
  336.         }
  337.     } else {
  338.         if (itEnd != itBegin) {
  339.             while(--itEnd != itBegin) {
  340.                 pWin = *itEnd;
  341.  
  342.                 const vduirect rChild(pWin->GetArea());
  343.                 int w = rChild.width();
  344.                 int h = rChild.height();
  345.  
  346.                 int minh = pWin->GetLayoutSpecs().minsize.h;
  347.                 if (h < minh)
  348.                     h = minh;
  349.  
  350.                 rClient.bottom -= h;
  351.  
  352.                 pWin->PostLayout(vduirect(rClient.left, rClient.bottom, rClient.right, rClient.bottom + h));
  353.             }
  354.  
  355.             if (rClient.bottom < rClient.top)
  356.                 rClient.bottom = rClient.top;
  357.  
  358.             pWin = *itEnd;
  359.             pWin->SetArea(rClient);
  360.         }
  361.     }
  362. }
  363.  
  364. ///////////////////////////////////////////////////////////////////////////
  365.  
  366. class VDUISplitBarW32 : public VDUICustomControlW32 {
  367. public:
  368.     VDUISplitBarW32();
  369.  
  370.     bool Create(IVDUIParameters *pParams);
  371.  
  372.     void PreLayoutBase(const VDUILayoutSpecs& constraints);
  373.  
  374. protected:
  375.     LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
  376.     void OnPaint();
  377.     void OnLButtonDown(WPARAM wParam, int x, int y);
  378.     void OnLButtonUp(WPARAM wParam, int x, int y);
  379.     void OnMouseMove(WPARAM wParam, int x, int y);
  380.  
  381.     int        mDragOffset;
  382.     int        mSplitterSize;
  383.     bool    mbIsVertical;
  384. };
  385.  
  386. extern IVDUIWindow *VDCreateUISplitBar() { return new VDUISplitBarW32; }
  387.  
  388. VDUISplitBarW32::VDUISplitBarW32()
  389.     : mbIsVertical(true)
  390. {
  391. }
  392.  
  393. bool VDUISplitBarW32::Create(IVDUIParameters *pParams) {
  394.     mbIsVertical = pParams->GetB(nsVDUI::kUIParam_IsVertical, false);
  395.     mSplitterSize = GetSystemMetrics(mbIsVertical ? SM_CXEDGE : SM_CYEDGE)*3;
  396.     return VDUICustomControlW32::Create(pParams);
  397. }
  398.  
  399. void VDUISplitBarW32::PreLayoutBase(const VDUILayoutSpecs& constraints) {
  400.     if (mbIsVertical)
  401.         mLayoutSpecs.minsize.include(vduisize(mSplitterSize, 0));
  402.     else
  403.         mLayoutSpecs.minsize.include(vduisize(0, mSplitterSize));
  404. }
  405.  
  406. LRESULT VDUISplitBarW32::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) {
  407.     switch(msg) {
  408.     case WM_PAINT:
  409.         OnPaint();
  410.         break;
  411.  
  412.     case WM_LBUTTONDOWN:
  413.         OnLButtonDown(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  414.         return 0;
  415.  
  416.     case WM_LBUTTONUP:
  417.         OnLButtonUp(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  418.         return 0;
  419.  
  420.     case WM_MOUSEMOVE:
  421.         OnMouseMove(wParam, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
  422.         return 0;
  423.  
  424.     case WM_SETCURSOR:
  425.         if ((HWND)wParam == mhwnd && LOWORD(lParam) == HTCLIENT) {
  426.             SetCursor(LoadCursor(NULL, mbIsVertical ? IDC_SIZEWE : IDC_SIZENS));
  427.             return TRUE;
  428.         }
  429.         break;
  430.     }
  431.     return VDUICustomControlW32::WndProc(msg, wParam, lParam);
  432. }
  433.  
  434. void VDUISplitBarW32::OnPaint() {
  435.     PAINTSTRUCT ps;
  436.  
  437.     if (HDC hdc = BeginPaint(mhwnd, &ps)) {
  438.         RECT r;
  439.         GetClientRect(mhwnd, &r);
  440.         if (mbIsVertical)
  441.             DrawEdge(hdc, &r, EDGE_RAISED, BF_LEFT|BF_RIGHT);
  442.         else
  443.             DrawEdge(hdc, &r, EDGE_RAISED, BF_TOP|BF_BOTTOM);
  444.  
  445.         EndPaint(mhwnd, &ps);
  446.     }
  447. }
  448.  
  449. void VDUISplitBarW32::OnLButtonDown(WPARAM wParam, int x, int y) {
  450.     POINT pt={x,y};
  451.  
  452.     if (mbIsVertical)
  453.         mDragOffset = x;
  454.     else
  455.         mDragOffset = y;
  456.     SetCapture(mhwnd);
  457. }
  458.  
  459. void VDUISplitBarW32::OnLButtonUp(WPARAM wParam, int x, int y) {
  460.     if (GetCapture() == mhwnd)
  461.         ReleaseCapture();
  462. }
  463.  
  464. void VDUISplitBarW32::OnMouseMove(WPARAM wParam, int x, int y) {
  465.     if (GetCapture() == mhwnd) {
  466.         RECT rClient;
  467.  
  468.         GetClientRect(mhwnd, &rClient);
  469.  
  470.         IVDUIWindow *pParent = GetParent();
  471.         if (pParent) {
  472.             IVDUIWindow *pSibling = pParent->GetNextChild(this);
  473.             vduirect r(pSibling->GetArea());
  474.             if (mbIsVertical) {
  475.                 int delta = x - mDragOffset;
  476.                 if (!delta)
  477.                     return;
  478.                 r.right += delta;
  479.             } else {
  480.                 int delta = y - mDragOffset;
  481.                 if (!delta)
  482.                     return;
  483.                 r.top += delta;
  484.             }
  485.             pSibling->SetArea(r);
  486.             pParent->PostLayout(pParent->GetArea());
  487.         }
  488.     }
  489. }
  490.