home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fmradio.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  14.0 KB  |  411 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. #include "stdafx.h"
  20.  
  21. #include "fmradio.h"
  22.  
  23. //    This file is dedicated to form type radio elements
  24. //        otherwise known as list boxes on windows and
  25. //        their implementation as requried by the XP layout
  26. //        library.
  27.  
  28. //    Construction simply clears all members.
  29. CFormRadio::CFormRadio()
  30. {
  31.     //    No widget.
  32.     m_pWidget = NULL;
  33. }
  34.  
  35. //    Destruction cleans out all members.
  36. CFormRadio::~CFormRadio()
  37. {
  38. }
  39.  
  40. //    How to set the LO form element.
  41. //    This may change during the lifetime of an instance, so use this
  42. //        to update all referencing values.
  43. void CFormRadio::SetElement(LO_FormElementStruct *pFormElement)
  44. {
  45.     //    Call the base.
  46.     CFormElement::SetElement(pFormElement);
  47.  
  48.     //    Update the widget if present for correct callbacks.
  49.     if(m_pWidget)    {
  50.         m_pWidget->RegisterForm(GetElement());
  51.     }
  52. }
  53.  
  54. //    Set the owning context.
  55. //    Use this to determine what context we live in and how we should
  56. //        represent ourself (DC or window).
  57. void CFormRadio::SetContext(CAbstractCX *pCX)
  58. {
  59.     //    Call the base.
  60.     CFormElement::SetContext(pCX);
  61.  
  62.     //    Update the widget if present for correct callbacks.
  63.     if(m_pWidget)    {
  64.         m_pWidget->RegisterContext(GetContext() ? GetContext()->GetContext() : NULL);
  65.     }
  66. }
  67.  
  68. //    Display the form element given the particular context we are in.
  69. //    Possibly only use a DC for representation, or have the
  70. //        window move.
  71. void CFormRadio::DisplayFormElement(LTRB& Rect)
  72. {
  73.     //    Display only has meaning if our context is a device context.
  74.     if(GetContext() && GetContext()->IsDCContext())    {
  75.         //    Further, need to detect how we're going to be drawing ourselves.
  76.         if(GetContext()->IsPureDCContext())    {
  77.             //    Only works from a DC, needs a GDI drawing representation.
  78.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  79.             HDC pDC = pDCCX->GetContextDC();
  80.             if(pDC && Rect.Width() && Rect.Height()) {
  81.                 //  Adjust the rect some (reverse what we did earlier for layout).
  82.                 RECT crRect;
  83.                 ::SetRect(&crRect, CASTINT(Rect.left), CASTINT(Rect.top),
  84.                     CASTINT(Rect.right), CASTINT(Rect.bottom));
  85.                 ::InflateRect(&crRect, CASTINT(-1 * pDCCX->Pix2TwipsX(BUTTON_FUDGE) / 2),
  86.                     CASTINT(-1 * pDCCX->Pix2TwipsY(BUTTON_FUDGE) / 2));
  87.  
  88.                 //  Figure out what type we're about to draw, and its current state.
  89.                 BOOL bRadio = FALSE;    //  Radio or checkbox.
  90.                 BOOL bChecked = FALSE;  //  State, checked or not.
  91.  
  92.                 if(GetElementMinimalData())    {
  93.                     switch(GetElementMinimalData()->type)    {
  94.                     case FORM_TYPE_RADIO:
  95.                         bRadio = TRUE;
  96.                         break;
  97.                     case FORM_TYPE_CHECKBOX:
  98.                         bRadio = FALSE;
  99.                         break;
  100.                     default:    //    Unknown!
  101.                         ASSERT(0);
  102.                         return;
  103.                     }
  104.                 }
  105.  
  106.                 if(GetElementToggleData())  {
  107.                     bChecked = GetElementToggleData()->toggled ? TRUE : FALSE;
  108.                 }
  109.  
  110.                 //  Are we drawing a circle or a square?
  111.                 if(bRadio)  {
  112.                     TRY {
  113.                         //  Circle.
  114.                         //  Select the outer pen.
  115.                         HPEN hpOuter = ::CreatePen(PS_SOLID, CASTINT(pDCCX->Pix2TwipsY(1)), pDCCX->ResolveLightLineColor());
  116.                         HPEN hOldPen = (HPEN)::SelectObject(pDC, hpOuter);
  117.                         if(hOldPen) {
  118.                             //  Draw an ellipse.
  119.                             ::Ellipse(pDC, crRect.left, crRect.top, crRect.right, crRect.bottom);
  120.  
  121.                             //  Select the inner pen.
  122.                             HPEN hpInner = ::CreatePen(PS_SOLID, CASTINT(pDCCX->Pix2TwipsY(1)), pDCCX->ResolveDarkLineColor());
  123.                             ::SelectObject(pDC, hpInner);
  124.                             ::InflateRect(&crRect, CASTINT(-1 * pDCCX->Pix2TwipsX(1)), CASTINT(-1 * pDCCX->Pix2TwipsY(1)));
  125.                             ::Ellipse(pDC, crRect.left, crRect.top, crRect.right, crRect.bottom);
  126.  
  127.                             //  Are we drawing a circle in the radio button (checked?)
  128.                             if(bChecked)    {
  129.                                 HPEN hpBlack = CreatePen(PS_SOLID, CASTINT(pDCCX->Pix2TwipsY(1)), RGB(0, 0, 0));
  130.                                 ::SelectObject(pDC, hpBlack);
  131.  
  132.                                 //  Get the brush with which to fill the ellipse this time around.
  133.                                 HBRUSH hbBlack = ::CreateSolidBrush(RGB(0, 0, 0));
  134.                                 HBRUSH hOldBrush = (HBRUSH)::SelectObject(pDC, hbBlack);
  135.                                 ::InflateRect(&crRect, CASTINT(-1 * pDCCX->Pix2TwipsX(3)), CASTINT(-1 * pDCCX->Pix2TwipsY(3)));
  136.                                 ::Ellipse(pDC, crRect.left, crRect.top, crRect.right, crRect.bottom);
  137.  
  138.                                 //  Restore the brush.
  139.                                 if(hOldBrush)   {
  140.                                     ::SelectObject(pDC, hOldBrush);
  141.                                 }
  142.                                 VERIFY(::DeleteObject( hbBlack ));
  143.                                 VERIFY(::DeleteObject( hpBlack ));
  144.                             }
  145.  
  146.                             //  Restore original pen.
  147.                             ::SelectObject(pDC, hOldPen);
  148.                             VERIFY(::DeleteObject( hpOuter ));
  149.                             VERIFY(::DeleteObject( hpInner ));
  150.  
  151.                         }
  152.                     }
  153.                     CATCH(CException, e)    {
  154.                         //  Caught some pen/brush exception, do nothing special.
  155.                     }
  156.                     END_CATCH
  157.                 }
  158.                 else    {
  159.                     //  Square.
  160.                     pDCCX->Display3DBox(LTRB(crRect.left, crRect.top, crRect.right, crRect.bottom),
  161.                         pDCCX->ResolveLightLineColor(), pDCCX->ResolveDarkLineColor(), pDCCX->Pix2TwipsY(2));
  162.  
  163.                     //  Are we checking it?
  164.                     if(bChecked)    {
  165.                         ::InflateRect(&crRect, CASTINT(-1 * pDCCX->Pix2TwipsX(2)), CASTINT(-1 * pDCCX->Pix2TwipsY(2)));
  166.  
  167.                         TRY {
  168.                             HPEN hpBlack = ::CreatePen(PS_SOLID, CASTINT(pDCCX->Pix2TwipsY(2)), RGB(0, 0, 0));
  169.                             HPEN hOldPen = (HPEN)::SelectObject(pDC, hpBlack);
  170.                             if(hOldPen) {
  171.                                 //  Draw a check.
  172.                                 int width = crRect.right - crRect.left;
  173.                                 int height = crRect.bottom - crRect.top;
  174.  
  175.                                 ::MoveToEx(pDC, crRect.left + width / 4, crRect.top + height / 2, NULL);
  176.                                 ::LineTo(pDC, crRect.left + width / 3, crRect.top + 3 * height / 4);
  177.                                 ::LineTo(pDC, crRect.left + 3 * width / 4, crRect.top + height / 4);
  178.  
  179.                                 //  Restore old pen.
  180.                                 ::SelectObject(pDC, hOldPen);
  181.                                 VERIFY(::DeleteObject(hpBlack));
  182.                             }
  183.                         }
  184.                         CATCH(CException, e)    {
  185.                             //  Caught some pen exeption, do nothing special here.
  186.                         }
  187.                         END_CATCH
  188.                     }
  189.                 }
  190.  
  191.                 pDCCX->ReleaseContextDC(pDC);
  192.             }
  193.         }
  194.         else if(GetContext()->IsWindowContext())    {
  195.             //    Is a window, needs a widget/window representation.
  196.             MoveWindow(m_pWidget->m_hWnd, Rect.left + BUTTON_FUDGE / 2, 
  197.                                 Rect.top + BUTTON_FUDGE / 2);
  198.         }
  199.         else    {
  200.             //    Is undefined....
  201.             ASSERT(0);
  202.         }
  203.     }
  204.  
  205.     //    Call the base.
  206.     CFormElement::DisplayFormElement(Rect);
  207. }
  208.  
  209. //    Destroy the widget (window) implemenation of the form.
  210. void CFormRadio::DestroyWidget()
  211. {
  212.     if(m_pWidget)    {
  213.         m_pWidget->DestroyWindow();
  214.         delete m_pWidget;
  215.         m_pWidget = NULL;
  216.     }
  217. }
  218.  
  219. //    Create the widget (window) implementation of the form
  220. //        but DO NOT DISPLAY.
  221. void CFormRadio::CreateWidget()
  222. {
  223.     if(GetContext() && GetElement())    {
  224.         if(GetContext()->IsWindowContext() && VOID2CX(GetContext(), CPaneCX)->GetPane())    {
  225.             //    For a window context, allocate a widget.
  226.             ASSERT(m_pWidget == NULL);
  227.             m_pWidget = new CNetscapeButton(GetContext()->GetContext(), GetElement());
  228.             if(m_pWidget == NULL)    {
  229.                 return;
  230.             }
  231.  
  232.             //    Figure the window style.
  233.             DWORD dwStyle = WS_CHILD;
  234.             if(GetElementMinimalData())    {
  235.                 switch(GetElementMinimalData()->type)    {
  236.                 case FORM_TYPE_RADIO:
  237.                     dwStyle |= BS_RADIOBUTTON;  
  238.                     break;
  239.                 case FORM_TYPE_CHECKBOX:
  240.                     dwStyle |= BS_CHECKBOX;        // bug 49682 removed AUTO, see button.cpp click()
  241.                     break;
  242.                 default:    //    Unknown!
  243.                     ASSERT(0);
  244.                     delete m_pWidget;
  245.                     m_pWidget = NULL;
  246.                     return;
  247.                 }
  248.             }
  249.             else    {
  250.                 //    Must know the type.
  251.                 delete m_pWidget;
  252.                 m_pWidget = NULL;
  253.                 return;
  254.             }
  255.  
  256.             BOOL bCreate = m_pWidget->Create(NULL,
  257.                 dwStyle,
  258.                 CRect(0, 0, 1, 1),
  259.                 CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()),
  260.                 GetDynamicControlID());
  261.             if(!bCreate)    {
  262.                 delete m_pWidget;
  263.                 m_pWidget = NULL;
  264.                 return;
  265.             }
  266.  
  267.             //    Size the thing.
  268.             //    Buttons are 7 x 7 in dialog units.
  269.             //    Perform a conversion to pixels.
  270.             LONG lUnits = GetDialogBaseUnits();
  271.             int32 lWidth = 7 * LOWORD(lUnits) / 4;
  272.             int32 lHeight = 7 * HIWORD(lUnits) / 8;
  273.  
  274.             //    Move it.
  275.             m_pWidget->MoveWindow(1, 1, CASTINT(lWidth), CASTINT(lHeight), FALSE);
  276.         }
  277.         else if(GetContext()->IsPureDCContext())    {
  278.         }
  279.     }
  280. }
  281.  
  282. //    Copy the current data out of the layout struct into the form
  283. //        widget, or mark that you should represent using the current data.
  284. void CFormRadio::UseCurrentData()
  285. {
  286.     //    Detect context type.
  287.     if(GetContext())    {
  288.         if(GetContext()->IsWindowContext())    {
  289.             //    Only continue if there's a widget at all.
  290.             if(m_pWidget)    {
  291.                 int iChecked = 0;    //    Sad default.
  292.                 if(GetElementToggleData())    {
  293.                     iChecked = GetElementToggleData()->toggled ? 1 : 0;
  294.                 }
  295.  
  296.                 //    Update the widget.
  297.                 if(m_pWidget->GetCheck() != iChecked)   {
  298.                     m_pWidget->SetCheck(iChecked);
  299.                 }
  300.             }
  301.         }
  302.         else if(GetContext()->IsPureDCContext())    {
  303.             //  Current data already reflected in toggle data.
  304.         }
  305.     }
  306. }
  307.  
  308. //    Copy the default data out of the layout struct into the form
  309. //        widget, or mark that you should represent using the default data.
  310. void CFormRadio::UseDefaultData()
  311. {
  312.     //    Detect context type.
  313.     if(GetContext())    {
  314.         if(GetContext()->IsWindowContext())    {
  315.             //    Only continue if there's a widget at all.
  316.             if(m_pWidget)    {
  317.                 int iChecked = 0;    //    Sad default.
  318.                 if(GetElementToggleData())    {
  319.                     iChecked = GetElementToggleData()->default_toggle ? 1 : 0;
  320.                 }
  321.  
  322.                 //    Update the widget.
  323.                 m_pWidget->SetCheck(iChecked);
  324.             }
  325.         }
  326.         else if(GetContext()->IsPureDCContext())    {
  327.             //  Set current to default.
  328.             if(GetElementToggleData())  {
  329.                 GetElementToggleData()->toggled = GetElementToggleData()->default_toggle;
  330.             }
  331.         }
  332.     }
  333. }
  334.  
  335. //    Fill in the layout size information in the layout struct regarding
  336. //        the dimensions of the widget.
  337. void CFormRadio::FillSizeInfo()
  338. {
  339.     //    Detect context type.
  340.     if(GetContext() && GetElement())    {
  341.         if(GetContext()->IsWindowContext())    {
  342.             //    Only continue if there's a widget at all.
  343.             if(m_pWidget)    {
  344.                 //    Determine out window position.
  345.                 CRect crWidget;
  346.                 m_pWidget->GetWindowRect(crWidget);
  347.  
  348.                 //    Munge it for layout.
  349.                 //    We'll need to know how to undo this
  350.                 //        in the display routine.
  351.                 GetElement()->width = crWidget.Width() + BUTTON_FUDGE;
  352.                 GetElement()->height = crWidget.Height() + BUTTON_FUDGE;
  353.                 GetElement()->baseline = GetElement()->height - (BUTTON_FUDGE - 1);
  354.                 GetElement()->border_vert_space = BUTTON_FUDGE/2;
  355.                 GetElement()->border_horiz_space = BUTTON_FUDGE/2;
  356.             }
  357.             else    {
  358.                 GetElement()->width = 0;
  359.                 GetElement()->height = 0;
  360.                 GetElement()->baseline = 0;
  361.             }
  362.         }
  363.         else if(GetContext()->IsPureDCContext())    {
  364.             //    Do some printing specific stuff here...
  365.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  366.  
  367.             //    Size the thing.
  368.             //    Buttons are 7 x 7 in dialog units.
  369.             //    Perform a conversion to twips/whatever.
  370.             LONG lUnits = GetDialogBaseUnits();
  371.             int32 lWidth = 7 * LOWORD(lUnits) / 4;
  372.             int32 lHeight = 7 * HIWORD(lUnits) / 8;
  373.             int32 lButtonFudge = pDCCX->Pix2TwipsY(BUTTON_FUDGE);
  374.  
  375.             lWidth = pDCCX->Pix2TwipsX(lWidth);
  376.             lHeight = pDCCX->Pix2TwipsX(lHeight);
  377.  
  378.             GetElement()->width = lWidth + lButtonFudge;
  379.             GetElement()->height = lHeight + lButtonFudge;
  380.             GetElement()->baseline = GetElement()->height - (lButtonFudge - pDCCX->Pix2TwipsY(1));
  381.         }
  382.     }
  383. }
  384.  
  385. //    Copy the current data out of the form element back into the
  386. //        layout struct.
  387. void CFormRadio::UpdateCurrentData()
  388. {
  389.     //    Detect context type.
  390.     if(GetContext())    {
  391.         if(GetContext()->IsWindowContext())    {
  392.             //    Only continue if there's a widget at all.
  393.             if(m_pWidget && ::IsWindow(m_pWidget->GetSafeHwnd()))    {
  394.                 if(GetElementToggleData())    {
  395.                     //    Update layout data as BOOL.
  396.                     GetElementToggleData()->toggled = m_pWidget->GetCheck() ? TRUE : FALSE;
  397.                 }
  398.             }
  399.         }
  400.         else if(GetContext()->IsPureDCContext())    {
  401.             //  Nothing to update.
  402.         }
  403.     }
  404. }
  405.  
  406. HWND CFormRadio::GetRaw()
  407. {
  408.     return(m_pWidget ? m_pWidget->m_hWnd : NULL);
  409. }
  410.  
  411.