home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / gridedge.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  12.2 KB  |  425 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. // gridedge.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "gridedge.h"
  24.  
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static char BASED_CODE THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CGridEdge
  32.  
  33. // Returns the rectangle, in pixels, of where to position the edge,
  34. // The coordinates are relative to the owning context's view
  35. static void
  36. GetGridEdgeRect(LO_EdgeStruct* pEdge, CWinCX* pOwnerCX, CRect &rect)
  37. {
  38.     int32 lAlign = pEdge->x + pEdge->x_offset;
  39.     int32 lLeft = pOwnerCX->Twips2PixX(lAlign);
  40.  
  41.     lAlign = pEdge->y + pEdge->y_offset;
  42.     int32 lTop = pOwnerCX->Twips2PixY(lAlign);
  43.  
  44.     lAlign = pEdge->x + pEdge->x_offset + pEdge->width;
  45.     int32 lRight = pOwnerCX->Twips2PixX(lAlign);
  46.  
  47.     lAlign = pEdge->y + pEdge->y_offset + pEdge->height;
  48.     int32 lBottom = pOwnerCX->Twips2PixY(lAlign);
  49.     
  50.     rect.left = CASTINT(lLeft);
  51.     rect.top = CASTINT(lTop);
  52.     rect.right = CASTINT(lRight);
  53.     rect.bottom = CASTINT(lBottom);
  54. }
  55.  
  56. CGridEdge::CGridEdge(LO_EdgeStruct *pEdge, CWinCX *pOwnerCX)
  57. {
  58.     //    Set our members.
  59.     m_pEdge = pEdge;
  60.     m_pCX = pOwnerCX;
  61.  
  62.     //    Not currently tracking.
  63.     m_bTracking = FALSE;
  64.  
  65.     m_bParentClipChildren = FALSE;
  66.     
  67.     //    We need to create a window for ourselves.
  68.     CRect crRect;
  69.  
  70.     GetGridEdgeRect(m_pEdge, m_pCX, crRect);
  71.  
  72.     DWORD dwEdgeStyle = WS_CHILD | WS_CLIPSIBLINGS;
  73.     if(pEdge->visible)  {
  74.         //  Make it visible.
  75.         dwEdgeStyle |= WS_VISIBLE;
  76.     }
  77.  
  78.     CreateEx(0, NULL, "GridEdge", dwEdgeStyle, 
  79.              crRect.left, crRect.top, 
  80.              crRect.right - crRect.left,
  81.              crRect.bottom - crRect.top, 
  82.              m_pCX->GetPane(), (HMENU) 0, NULL);
  83. }
  84.  
  85. CGridEdge::~CGridEdge()
  86. {
  87.     //    If we were tracking, then let our clipped region go, etc.
  88.     if(m_bTracking == TRUE)    {
  89.         //    Release capture.
  90.         ReleaseCapture();
  91.  
  92.         //    Release the bounds established on the mouse.
  93.         ::ClipCursor(NULL);
  94.  
  95.         //    Invert the tracker (return screen to normal state).
  96.         InvertTracker();
  97.     }
  98.  
  99.     //    Destroy our window.
  100.     DestroyWindow();
  101.  
  102.     //    Clear our members.
  103.     m_pEdge = NULL;
  104.     m_pCX = NULL;
  105. }
  106.  
  107.  
  108. BEGIN_MESSAGE_MAP(CGridEdge, CWnd)
  109.     //{{AFX_MSG_MAP(CGridEdge)
  110.     ON_WM_LBUTTONDOWN()
  111.     ON_WM_LBUTTONUP()
  112.     ON_WM_MOUSEMOVE()
  113.     ON_WM_SETCURSOR()
  114.     ON_WM_PAINT()
  115.     ON_WM_LBUTTONDBLCLK()
  116.     //}}AFX_MSG_MAP
  117. END_MESSAGE_MAP()
  118.  
  119.  
  120. /////////////////////////////////////////////////////////////////////////////
  121. // CGridEdge message handlers
  122.  
  123. void CGridEdge::UpdateEdge(LO_EdgeStruct *pEdge)    {
  124.     //    Update what our edge is.
  125.     m_pEdge = pEdge;
  126.  
  127.     //  See if our visibility is a concern.
  128.     if(m_pEdge->visible && IsWindowVisible() == FALSE)  {
  129.         ShowWindow(SW_SHOW);
  130.     }
  131.     else if(!m_pEdge->visible && IsWindowVisible()) {
  132.         ShowWindow(SW_HIDE);
  133.     }
  134.  
  135.     // Position the window properly
  136.     CRect crRect;
  137.  
  138.     GetGridEdgeRect(m_pEdge, m_pCX, crRect);
  139.     MoveWindow(crRect);
  140. }
  141.  
  142. void CGridEdge::InvertTracker()    {
  143.     // Get our frame context's DC (need to draw over children). The tracker
  144.     // coordinates are already in the frame window's coordinate system
  145.     if(m_pCX->GetFrame()->GetFrameWnd() != NULL)    {
  146.         CDC *pDC = m_pCX->GetFrame()->GetFrameWnd()->GetDC();
  147.  
  148.         //    Invert a brush pattern.
  149. #ifdef XP_WIN16
  150.         pDC->PatBlt(m_crTracker.left, m_crTracker.top, m_crTracker.Width(),
  151.             m_crTracker.Height(), DSTINVERT);
  152. #else
  153.         CBrush *pBrush = CDC::GetHalftoneBrush();
  154.         HBRUSH hOldBrush = NULL;
  155.         if(pBrush != NULL)    {
  156.             hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
  157.         }
  158.  
  159.         pDC->PatBlt(m_crTracker.left, m_crTracker.top,
  160.             m_crTracker.Width(), m_crTracker.Height(), PATINVERT);
  161.  
  162.         if(hOldBrush != NULL)    {
  163.             SelectObject(pDC->m_hDC, hOldBrush);
  164.         }
  165. #endif
  166.  
  167.         m_pCX->GetFrame()->GetFrameWnd()->ReleaseDC(pDC);
  168.     }
  169. }
  170.  
  171. void CGridEdge::OnLButtonDown(UINT nFlags, CPoint point) 
  172. {
  173.     //    Only do something if we can resize.
  174.     if(CanResize() == FALSE)    {
  175.         return;
  176.     }
  177.  
  178.     //    Capture mouse events.
  179.     SetCapture();
  180.  
  181.     // Bound the mouse to a rectangle that is acceptable for use to perform a resize.
  182.     // Layout knows how big this should be, and it's stored in left_top_bound and
  183.     // right_bottom_bound (how these are interpreted depends on whether it's a vertical
  184.     // or horizontal edge)
  185.     CRect crRect;
  186.  
  187.     // Start with the grid edge rect, and then use the bounds that layout has
  188.     GetGridEdgeRect(m_pEdge, m_pCX, crRect);
  189.  
  190.     if(m_pEdge->is_vertical) {
  191.         crRect.left = CASTINT(m_pCX->Twips2PixX(m_pEdge->left_top_bound));
  192.         crRect.right = CASTINT(m_pCX->Twips2PixX(m_pEdge->right_bottom_bound));
  193.  
  194.     } else {
  195.         crRect.top = CASTINT(m_pCX->Twips2PixY(m_pEdge->left_top_bound));
  196.         crRect.bottom = CASTINT(m_pCX->Twips2PixY(m_pEdge->right_bottom_bound));
  197.     }
  198.  
  199.     ::ClientToScreen(m_pCX->GetPane(), &crRect.TopLeft());
  200.     ::ClientToScreen(m_pCX->GetPane(), &crRect.BottomRight());
  201.  
  202.     TRACE("Clipping cursor to (%d,%d)(%d,%d)\n", crRect.left, crRect.top,
  203.         crRect.right, crRect.bottom);
  204.     ::ClipCursor(crRect);
  205.  
  206.     //    Mark the point at which the mouse went down.
  207.     //    This can be used to calculate the relative distance of the movement of the tracker.
  208.     m_cpLBDown = point;
  209.  
  210.     //    Set tracking state.
  211.     m_bTracking = TRUE;
  212.  
  213.     // Update our tracker with our current coordinates. Tracker coordinates must be in the
  214.     // frame window's coordinate system
  215.     GetClientRect(m_crTracker);
  216.     MapWindowPoints(m_pCX->GetFrame()->GetFrameWnd(), m_crTracker);
  217.  
  218.     // Save the current tracker bounds for later
  219.     m_crOriginalTracker = m_crTracker;
  220.  
  221.     // Turn off clipping of children on the parent window before we 
  222.     // start dragging. This is so we can draw the tracker directly on
  223.     // the parent window (and probably over its child windows).
  224.     CWnd *pWnd = m_pCX->GetFrame()->GetFrameWnd();
  225.     if(pWnd)    {
  226.         DWORD dwStyle = ::GetWindowLong(pWnd->m_hWnd, GWL_STYLE);
  227.         m_bParentClipChildren = ((dwStyle & WS_CLIPCHILDREN) != 0);
  228.         ::SetWindowLong(pWnd->m_hWnd, GWL_STYLE, (dwStyle & ~WS_CLIPCHILDREN));
  229.     }
  230.  
  231.     //    Invert the tracker.
  232.     InvertTracker();
  233. }
  234.  
  235. void CGridEdge::OnLButtonUp(UINT nFlags, CPoint point) 
  236. {
  237.     //    Only do something if we can resize.
  238.     if(CanResize() == FALSE)    {
  239.         return;
  240.     }
  241.  
  242.     //    Release capture.
  243.     ReleaseCapture();
  244.  
  245.     //    Release the bounds established on the mouse.
  246.     ::ClipCursor(NULL);
  247.  
  248.     //    Invert the tracker (return screen to normal state).
  249.     InvertTracker();
  250.  
  251.     // Turn clipping children back on if our parent had it.
  252.     CWnd *pWnd = m_pCX->GetFrame()->GetFrameWnd();
  253.     if(pWnd && m_bParentClipChildren)    {
  254.         DWORD dwStyle = ::GetWindowLong(pWnd->m_hWnd, GWL_STYLE);
  255.         ::SetWindowLong(pWnd->m_hWnd, GWL_STYLE, (dwStyle|WS_CLIPCHILDREN));
  256.     }
  257.  
  258.     //    Set that we are no longer tracking.
  259.     m_bTracking = FALSE;
  260.  
  261.     // Convert tracker from the frame window's coordinate system to the
  262.     // owning context view's coordinate system
  263.     CPoint cpPoint;
  264.     m_pCX->GetViewOffsetInFrame(cpPoint);
  265.     m_crTracker.left -= cpPoint.x;
  266.     m_crTracker.top -= cpPoint.y;
  267.  
  268.     //    Report to layout the new position of the tracker.
  269.     //    Make sure we didn't pass any limits.
  270.     if(m_pEdge->is_vertical)    {
  271.         //    Check the left argument.
  272.         if(m_crTracker.left > m_pEdge->right_bottom_bound)    {
  273.             m_crTracker.left = CASTINT(m_pEdge->right_bottom_bound);
  274.         }
  275.         if(m_crTracker.left < m_pEdge->left_top_bound)    {
  276.             m_crTracker.left = CASTINT(m_pEdge->left_top_bound);
  277.         }
  278.     }
  279.     else    {
  280.         //    Check the top argument.
  281.         if(m_crTracker.top > m_pEdge->right_bottom_bound)    {
  282.             m_crTracker.top = CASTINT(m_pEdge->right_bottom_bound);
  283.         }
  284.         if(m_crTracker.top < m_pEdge->left_top_bound)    {
  285.             m_crTracker.top = CASTINT(m_pEdge->left_top_bound);
  286.         }
  287.     }
  288.  
  289.     //    Restore our tracker to its original value, in case layout does nothing.
  290.     CRect crTemp = m_crTracker;
  291.     m_crTracker = m_crOriginalTracker;
  292.  
  293.     LO_MoveGridEdge(m_pCX->GetContext(), m_pEdge, crTemp.left, crTemp.top);
  294. }
  295.  
  296. void CGridEdge::OnMouseMove(UINT nFlags, CPoint point) 
  297. {
  298.     //    Only do this if we can resize.
  299.     if(CanResize() == FALSE)    {
  300.         return;
  301.     }
  302.  
  303.     //    If we're currently tracking, simply update the coords.
  304.     if(m_bTracking == TRUE)    {
  305.         //    Turn off the tracker.
  306.         InvertTracker();
  307.  
  308.         //    Figure out which direction we're allowing this to be updated.
  309.         if(m_pEdge->is_vertical)    {
  310.             //    Can go left to right.
  311.             m_crTracker.left = CASTINT(m_crOriginalTracker.left + m_pCX->Pix2TwipsX(point.x - m_cpLBDown.x));
  312.             m_crTracker.right = m_crTracker.left + m_crOriginalTracker.Width();
  313.         }
  314.         else    {
  315.             //    Can go top to bottom.
  316.             m_crTracker.top = CASTINT(m_crOriginalTracker.top + m_pCX->Pix2TwipsY(point.y - m_cpLBDown.y));
  317.             m_crTracker.bottom = m_crTracker.top + m_crOriginalTracker.Height();
  318.         }
  319.  
  320.         //    Turn on the tracker.
  321.         InvertTracker();
  322.         return;
  323.     }
  324.  
  325.     static HCURSOR hcurLast = NULL;
  326.     static HCURSOR hcurDestroy = NULL;
  327.     static UINT uLastCursorID = 0;
  328.     UINT uCursorID;
  329.  
  330.     //    Decide which cursor we want to load.
  331.     if(m_pEdge->is_vertical == FALSE)    {
  332.         //    Horizontal.
  333.         uCursorID = AFX_IDC_VSPLITBAR;
  334.     }
  335.     else    {
  336.         //    Vertical.
  337.         uCursorID = AFX_IDC_HSPLITBAR;
  338.     }
  339.  
  340.     //    Only if not already loaded.
  341.     HCURSOR hcurToDestroy = NULL;
  342.     if(uCursorID != uLastCursorID)    {
  343.         HINSTANCE hInst =
  344. #ifdef _AFXDLL
  345.         AfxFindResourceHandle(MAKEINTRESOURCE(uCursorID), RT_GROUP_CURSOR);
  346. #else
  347.         AfxGetResourceHandle();
  348. #endif
  349.  
  350.         //    Load in another cursor.
  351.         hcurToDestroy = hcurDestroy;
  352.  
  353.         hcurDestroy = hcurLast = ::LoadCursor(hInst, MAKEINTRESOURCE(uCursorID));
  354.         uLastCursorID = uCursorID;
  355.     }
  356.  
  357.     //    Set the cursor.
  358.     ::SetCursor(hcurLast);
  359.  
  360.     //    Destroy the previous cursor if need be.
  361.     if(hcurToDestroy != NULL)    {
  362.         ::DestroyCursor(hcurToDestroy);
  363.     }
  364. }
  365.  
  366. BOOL CGridEdge::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  367. {
  368.     if (nHitTest == HTCLIENT && pWnd == this && !m_bTracking && CanResize())    {
  369.         return TRUE;    // we will handle it in the mouse move
  370.     }
  371.     
  372.     return CWnd::OnSetCursor(pWnd, nHitTest, message);
  373. }
  374.  
  375. void CGridEdge::OnPaint() 
  376. {
  377.     CPaintDC dc(this); // device context for painting
  378.     
  379.     //    The area we're drawing.
  380.     CRect crRect;
  381.     GetClientRect(crRect);
  382.  
  383.     //    Draw it as the button face if no other color available.
  384.     if(m_pEdge && m_pEdge->bg_color)    {
  385.         WFE_FillSolidRect((CDC *)&dc, crRect,
  386.             RGB(m_pEdge->bg_color->red, m_pEdge->bg_color->green, m_pEdge->bg_color->blue));
  387.     }
  388.     else    {
  389.         WFE_FillSolidRect((CDC *)&dc, crRect, sysInfo.m_clrBtnFace);
  390.     }
  391.  
  392.     // Draw the border edges if appropriate. We can't really do much unless the edge
  393.     // is at least 3 pixels wide/high
  394.     if (m_pEdge->visible) {
  395.         if (m_pEdge->is_vertical) {
  396.             if (m_pEdge->width >= 3) {
  397.                 int    nLeft = m_pEdge->width >= 6 ? crRect.left + 1 : crRect.left;
  398.  
  399.                 dc.PatBlt(nLeft, crRect.top, 1, crRect.Height(), WHITENESS);
  400.                 HBRUSH    hOldBrush = (HBRUSH)::SelectObject(dc.m_hDC, ::GetStockObject(GRAY_BRUSH));
  401.                 dc.PatBlt(crRect.right - 2, crRect.top, 1, crRect.Height(), PATCOPY);
  402.                 ::SelectObject(dc.m_hDC, hOldBrush);
  403.                 dc.PatBlt(crRect.right - 1, crRect.top, 1, crRect.Height(), BLACKNESS);
  404.             }
  405.     
  406.         } else {
  407.             if (m_pEdge->height >= 3) {
  408.                 int    nTop = m_pEdge->height >= 6 ? crRect.top + 1 : crRect.top;
  409.  
  410.                 dc.PatBlt(crRect.left, nTop, crRect.Width(), 1, WHITENESS);
  411.                 HBRUSH    hOldBrush = (HBRUSH)::SelectObject(dc.m_hDC, ::GetStockObject(GRAY_BRUSH));
  412.                 dc.PatBlt(crRect.left, crRect.bottom - 2, crRect.Width(), 1, PATCOPY);
  413.                 ::SelectObject(dc.m_hDC, hOldBrush);
  414.                 dc.PatBlt(crRect.left, crRect.bottom - 1, crRect.Width(), 1, BLACKNESS);
  415.             }
  416.         }
  417.     }
  418. }
  419.  
  420. void CGridEdge::OnLButtonDblClk(UINT nFlags, CPoint point) 
  421. {
  422.     //    Treat same as button down.
  423.     OnLButtonDown(nFlags, point);
  424. }
  425.