home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / fmfile.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  15.8 KB  |  526 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 "fmfile.h"
  22. #include "odctrl.h"
  23. #include "intl_csi.h"
  24.  
  25. //    This file is dedicated to form type select one elements
  26. //        otherwise known as list boxes on windows and
  27. //        their implementation as requried by the XP layout
  28. //        library.
  29.  
  30. //    Construction simply clears all members.
  31. CFormFile::CFormFile()
  32. {
  33.     //    No widgets yet.
  34.     m_pWidget = NULL;
  35.     m_pBrowse = NULL;
  36.     m_pWidgetOverride = NULL;
  37. }
  38.  
  39. //    Destruction cleans out all members.
  40. CFormFile::~CFormFile()
  41. {
  42. }
  43.  
  44. //    How to set the LO form element.
  45. //    This may change during the lifetime of an instance, so use this
  46. //        to update all referencing values.
  47. void CFormFile::SetElement(LO_FormElementStruct *pFormElement)
  48. {
  49.     //    Call the base.
  50.     CFormElement::SetElement(pFormElement);
  51.  
  52.     //    Let the widget know the element.
  53.     if(m_pWidget)    {
  54.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  55.     }
  56.  
  57.     //    Update the widget if present for correct callbacks.
  58.     if(m_pBrowse)    {
  59.         m_pBrowse->RegisterForm(GetElement());
  60.     }
  61. }
  62.  
  63. //    Set the owning context.
  64. //    Use this to determine what context we live in and how we should
  65. //        represent ourself (DC or window).
  66. void CFormFile::SetContext(CAbstractCX *pCX)
  67. {
  68.     //    Call the base.
  69.     CFormElement::SetContext(pCX);
  70.  
  71.     //    Let the widget know the context.
  72.     if(m_pWidget)    {
  73.         m_pWidget->SetContext(GetContext() ? GetContext()->GetContext() : NULL, GetElement());
  74.     }
  75.  
  76.     //    Update the widget if present for correct callbacks.
  77.     if(m_pBrowse)    {
  78.         m_pBrowse->RegisterContext(GetContext() ? GetContext()->GetContext() : NULL);
  79.     }
  80. }
  81.  
  82. //    Display the form element given the particular context we are in.
  83. //    Possibly only use a DC for representation, or have the
  84. //        window move.
  85. void CFormFile::DisplayFormElement(LTRB& Rect)
  86. {
  87.     //    Display only has meaning if our context is a device context.
  88.     if(GetContext() && GetContext()->IsDCContext())    {
  89.         //    Further, need to detect how we're going to be drawing ourselves.
  90.         if(GetContext()->IsPureDCContext())    {
  91.             //    Only works from a DC, needs a GDI drawing representation.
  92.             CDCCX *pDCCX = VOID2CX(GetContext(), CDCCX);
  93.         }
  94.         else if(GetContext()->IsWindowContext())    {
  95.             //    Is a window, needs a widget/window representation.
  96.             MoveWindow(m_pWidget->m_hWnd, Rect.left, Rect.top + EDIT_SPACE / 2);
  97.             CRect crWidget;
  98.             m_pWidget->GetWindowRect(crWidget);
  99.             MoveWindow(m_pBrowse->m_hWnd, Rect.left + 2 + (crWidget.right - crWidget.left), Rect.top + 1);
  100.         }
  101.         else    {
  102.             //    Is undefined....
  103.             ASSERT(0);
  104.         }
  105.     }
  106.  
  107.     //    CALL THE BASE, TWICE!
  108.     //    Fake out the base class by dynamically switching
  109.     //        what is reported with GetRaw().
  110.     CFormElement::DisplayFormElement(Rect);
  111.     if(m_pBrowse)    {
  112.         m_pWidgetOverride = m_pBrowse;
  113.         CFormElement::DisplayFormElement(Rect);
  114.         m_pWidgetOverride = NULL;
  115.     }
  116. }
  117.  
  118. //    Destroy the widget (window) implemenation of the form.
  119. void CFormFile::DestroyWidget()
  120. {
  121.     //    Destroy any widgets around.
  122.     if(m_pWidget)    {
  123.         m_pWidget->DestroyWindow();
  124.         delete m_pWidget;
  125.         m_pWidget = NULL;
  126.     }
  127.  
  128.     if(m_pBrowse)    {
  129.         m_pBrowse->DestroyWindow();
  130.         delete m_pBrowse;
  131.         m_pBrowse = NULL;
  132.     }
  133. }
  134.  
  135. //    Create the widget (window) implementation of the form
  136. //        but DO NOT DISPLAY.
  137. void CFormFile::CreateWidget()
  138. {
  139.     //    Detect context type.
  140.     if(GetContext() && GetElement())    {
  141.         if(GetContext()->IsWindowContext() && VOID2CX(GetContext(), CPaneCX)->GetPane())    {
  142.             //    Widget representation.
  143.             //    Text entry field first.
  144.             ASSERT(m_pWidget == NULL);
  145.             m_pWidget = new CODNetscapeEdit;
  146.             if(m_pWidget == NULL)    {
  147.                 return;
  148.             }
  149.  
  150.             //    Inform widget of context and element.
  151.             m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  152.  
  153. #ifdef XP_WIN16
  154.             //    On 16 bits, we need to set the segment of the widget before creation.
  155.             HINSTANCE hSegment = GetSegment();
  156.             if(hSegment)    {
  157.                 m_pWidget->SetInstance(hSegment);
  158.             }
  159.             else    {
  160.                 delete m_pWidget;
  161.                 m_pWidget = NULL;
  162.                 return;
  163.             }
  164. #endif
  165.  
  166.             //    Decide the style of the widget.
  167.             DWORD dwStyle = WS_CHILD | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL;
  168.  
  169.             //    Create the widget, hidden, and with a bad size.
  170.             BOOL bCreate =
  171. #ifdef XP_WIN32
  172.                 m_pWidget->CreateEx(WS_EX_CLIENTEDGE,
  173.                     _T("EDIT"),
  174.                     NULL,
  175.                     dwStyle,
  176.                     1, 1, 0, 0,
  177.                     VOID2CX(GetContext(), CPaneCX)->GetPane(),
  178.                     (HMENU)GetDynamicControlID(),
  179.                     NULL);
  180. #else
  181.                 m_pWidget->Create(dwStyle, CRect(1, 1, 0, 0), 
  182.                     CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()), 
  183.                     GetDynamicControlID());
  184. #endif
  185.             if(!bCreate)    {
  186.                 delete m_pWidget;
  187.                 m_pWidget = NULL;
  188.                 return;
  189.             }
  190.  
  191.             //    Next, size the widget.
  192.             CDC *pDC = m_pWidget->GetDC();
  193.             if(pDC)    {
  194.                 CyaFont    *pMyFont;
  195.                 LO_TextAttr *text_attr = GetElement()->text_attr;
  196.                 VOID2CX(GetContext(), CWinCX)->SelectNetscapeFont( pDC->GetSafeHdc(), GetTextAttr(), pMyFont );
  197.                 //    Text metrics won't work unless we select the font.
  198.                 if(pMyFont == NULL)    {
  199.                     m_pWidget->ReleaseDC(pDC);
  200.                     DestroyWidget();
  201.                     return;
  202.                 }
  203.                 else {
  204.                     //    Default length is 20
  205.                     int32 lLength = 20;
  206.                     SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd);
  207.                     text_attr->FE_Data = pMyFont;
  208.  
  209.                     //    Figure up width and height we would like.
  210. //                    int32 lWidgetWidth = tm.tmMaxCharWidth;
  211. //                    int32 lWidgetHeight = tm.tmHeight + tm.tmHeight / 2;
  212.                     int32 lWidgetWidth = pMyFont->GetMaxWidth();
  213.                     int32 lWidgetHeight = pMyFont->GetHeight() + pMyFont->GetHeight() / 2;
  214.  
  215.                     //    See if we can measure the default text, and/or
  216.                     //        set up the size and size limits.
  217.                     if(GetElementTextData())    {
  218.                         if(GetElementTextData()->size > 0)    {
  219.                             //    Use provided size.
  220.                             lLength = GetElementTextData()->size;
  221.  
  222.                             //    Use average width.
  223.                             lWidgetWidth += lLength * pMyFont->GetMeanWidth();
  224.                         }
  225.                         else if(GetElementTextData()->default_text)    {
  226.                             //    Use length of text, exactly.
  227.                             char *pDefault = (char *)GetElementTextData()->default_text;
  228.  
  229.                             lLength = XP_STRLEN(pDefault);
  230.     //                        CSize csz = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), pDefault, CASTINT(lLength));
  231.  
  232.                             SIZE csz;
  233.                             CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  234.                                 INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  235.                                  pDC->GetSafeHdc(), pDefault, CASTINT(lLength), &csz);
  236.  
  237.                             //    Use this width.
  238.                             lWidgetWidth += csz.cx;
  239.                         }
  240.  
  241.                         //    Hold to the maximum size limit, and set it.
  242.                         if(GetElementTextData()->max_size >= 0)    {
  243.                             m_pWidget->LimitText(CASTINT(GetElementTextData()->max_size));
  244.                         }
  245.                     }
  246.  
  247.                     //    Restore old font selection.
  248.                     VOID2CX(GetContext(), CWinCX)->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
  249.                     m_pWidget->MoveWindow(1, 1, CASTINT(lWidgetWidth), CASTINT(lWidgetHeight), FALSE);
  250.                 }
  251.                 m_pWidget->ReleaseDC(pDC);
  252.             }
  253.             else    {
  254.                 DestroyWidget();
  255.                 return;
  256.             }
  257.  
  258.             //    2nd widget coming up, the browse button.
  259.             m_pBrowse = new CODNetscapeButton(GetContext()->GetContext(), GetElement());
  260.             if(m_pBrowse == NULL)    {
  261.                 DestroyWidget();
  262.                 return;
  263.             }
  264.  
  265.             //    Create with a bad size and hidden.
  266.             dwStyle = WS_CHILD | BS_PUSHBUTTON;
  267.             bCreate = m_pBrowse->Create("",
  268.                 dwStyle,
  269.                 CRect(1, 1, 0, 0),
  270.                 CWnd::FromHandle(VOID2CX(GetContext(), CPaneCX)->GetPane()),
  271.                 GetDynamicControlID());
  272.             if(!bCreate)    {
  273.                 delete m_pBrowse;
  274.                 m_pBrowse = NULL;
  275.                 DestroyWidget();
  276.                 return;
  277.             }
  278.  
  279.             //    Font in the button.
  280.             //    Measure what the size of the button should be.
  281.             pDC = m_pBrowse->GetDC();
  282.             if(pDC)    {
  283.                 CyaFont    *pMyFont;
  284.                 VOID2CX(GetContext(), CWinCX)->SelectNetscapeFont( pDC->GetSafeHdc(), GetTextAttr(), pMyFont );
  285.  
  286.                 if (pMyFont) {
  287.                     int32 lWidgetWidth = 0;
  288.                     int32 lWidgetHeight = 0;
  289.  
  290.  
  291.                     SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd);
  292.                     //    Determine caption text.
  293.                     char *pCaption = szLoadString(IDS_BROWSE_BUTTON);
  294.                     if(GetElementMinimalData() && GetElementMinimalData()->value)    {
  295.                         pCaption = (char *)GetElementMinimalData()->value;
  296.                     }
  297.  
  298.                     SIZE csz;
  299.                     CIntlWin::GetTextExtentPointWithCyaFont(pMyFont, 
  300.                         INTL_GetCSIWinCSID(LO_GetDocumentCharacterSetInfo(GetContext()->GetContext())),
  301.                          pDC->GetSafeHdc(), pCaption, XP_STRLEN(pCaption), &csz);
  302.     //                csz = CIntlWin::GetTextExtent(0, pDC->GetSafeHdc(), pCaption, XP_STRLEN(pCaption));
  303.  
  304.                     lWidgetWidth = 3 * csz.cx / 2;
  305.                     lWidgetHeight = 3 * csz.cy / 2;
  306.  
  307.                     //    Done measureing.
  308.                     VOID2CX(GetContext(), CWinCX)->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
  309.                     m_pBrowse->MoveWindow(1, 1, CASTINT(lWidgetWidth), CASTINT(lWidgetHeight), FALSE);
  310.                     m_pBrowse->ReleaseDC(pDC);
  311.                 }
  312.                 else {
  313.                     m_pBrowse->ReleaseDC(pDC);
  314.                     DestroyWidget();
  315.                     return;
  316.                 }
  317.  
  318.                 //    Move it.
  319.  
  320.                 //    Tell it what edit control is associated.
  321.                 m_pBrowse->RegisterEdit(m_pWidget);
  322.             }
  323.             else    {
  324.                 DestroyWidget();
  325.                 return;
  326.             }
  327.         }
  328.         else if(GetContext()->IsPureDCContext())    {
  329.             //    DC representation.
  330.         }
  331.     }
  332. }
  333.  
  334. //    Copy the current data out of the layout struct into the form
  335. //        widget, or mark that you should represent using the current data.
  336. void CFormFile::UseCurrentData()
  337. {
  338.     //    Detect context type and do the right thing.
  339.     if(GetContext())    {
  340.         if(GetContext()->IsWindowContext())    {
  341.             if(m_pWidget)    {
  342.                 //    Determine the current text to set.
  343.                 char *pCurrent = "";
  344.                 if(GetElementTextData() && GetElementTextData()->current_text)    {
  345.                     pCurrent = (char *)GetElementTextData()->current_text;
  346.                 }
  347.                 // We have to SetContext to the widget before we SetWindowText
  348.                 // Otherwise, the widget don't know what csid the text is.
  349.                 m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  350.  
  351.                 m_pWidget->SetWindowText(pCurrent);
  352.             }
  353.  
  354.             if(m_pBrowse)    {
  355.                 //    Set the button caption.
  356.                 char *pCaption = szLoadString(IDS_BROWSE_BUTTON);
  357.                 if(GetElementMinimalData() && GetElementMinimalData()->value)    {
  358.                     pCaption = (char *)GetElementMinimalData()->value;
  359.                 }
  360.                 m_pBrowse->SetWindowText(pCaption);
  361.             }
  362.         }
  363.         else if(GetContext()->IsPureDCContext())    {
  364.         }
  365.     }
  366. }
  367.  
  368. //    Copy the default data out of the layout struct into the form
  369. //        widget, or mark that you should represent using the default data.
  370. void CFormFile::UseDefaultData()
  371. {
  372.     //    Detect context type and do the right thing.
  373.     if(GetContext())    {
  374.         if(GetContext()->IsWindowContext())    {
  375.             if(m_pWidget)    {
  376.                 //    Determine the default text to set.
  377.                 char *pDefault = "";
  378.                 if(GetElementTextData() && GetElementTextData()->default_text)    {
  379.                     pDefault = (char *)GetElementTextData()->default_text;
  380.                 }
  381.                 // We have to SetContext to the widget before we SetWindowText
  382.                 // Otherwise, the widget don't know what csid the text is.
  383.                 m_pWidget->SetContext(GetContext()->GetContext(), GetElement());
  384.  
  385.                 m_pWidget->SetWindowText(pDefault);
  386.             }
  387.  
  388.             if(m_pBrowse)    {
  389.                 //    Set the button caption.
  390.                 char *pCaption = szLoadString(IDS_BROWSE_BUTTON);
  391.                 if(GetElementMinimalData() && GetElementMinimalData()->value)    {
  392.                     pCaption = (char *)GetElementMinimalData()->value;
  393.                 }
  394.                 m_pBrowse->SetWindowText(pCaption);
  395.             }
  396.         }
  397.         else if(GetContext()->IsPureDCContext())    {
  398.         }
  399.     }
  400. }
  401.  
  402. //    Fill in the layout size information in the layout struct regarding
  403. //        the dimensions of the widget.
  404. void CFormFile::FillSizeInfo()
  405. {
  406.     //    Detect context type and do the right thing.
  407.     if(GetContext() && GetElement())    {
  408.         if(GetContext()->IsWindowContext())    {
  409.             if(m_pWidget)    {
  410.                 //    Calculate the size we need.
  411.                 CRect crRect;
  412.                 m_pWidget->GetWindowRect(crRect);
  413.  
  414.                 //    Munge the coordinate a little for layout.
  415.                 //    We'll have to know how to decode this information
  416.                 //        in the display routine (by half).
  417.                 GetElement()->width = crRect.Width();
  418.                 GetElement()->height = crRect.Height() + EDIT_SPACE;
  419.                 GetElement()->border_vert_space = EDIT_SPACE/2;
  420.  
  421.                 //    Baseline needs text metric information.
  422.                 GetElement()->baseline = GetElement()->height;    //    ugly default in case of failure below.
  423.                 CDC *pDC = m_pWidget->GetDC();
  424.                 if(pDC)    {
  425.                     //    Need to specifically select the font before calling GetTextMetrics.
  426.                     CyaFont    *pMyFont;
  427.                     VOID2CX(GetContext(), CPaneCX)->SelectNetscapeFont( pDC->GetSafeHdc(), GetTextAttr(), pMyFont );
  428.                     if (pMyFont) {
  429.                         SetWidgetFont(pDC->GetSafeHdc(), m_pWidget->m_hWnd);
  430.                         GetElement()->baseline -= (pMyFont->GetHeight() / 2 + pMyFont->GetDescent()) / 2;
  431.  
  432.                         VOID2CX(GetContext(), CPaneCX)->ReleaseNetscapeFont( pDC->GetSafeHdc(), pMyFont );
  433.                         m_pWidget->ReleaseDC(pDC);
  434.                     }
  435.                     else {
  436.                         m_pWidget->ReleaseDC(pDC);
  437.                         DestroyWidget();
  438.                         return;
  439.                     }
  440.                 }
  441.  
  442.                 //    Now for the second part.
  443.                 //    Add the width of browse button and take the max height.
  444.                 //    Whichever height we take, controls the baseline.
  445.                 CRect crBrowse;
  446.                 m_pBrowse->GetWindowRect(crBrowse);
  447.  
  448.                 //    This is a recreation of csz.cy in CreateWidget.
  449.                 int32 csz_cy = 2 * crBrowse.Height() / 3;
  450.  
  451.                 //    Munge return coordinates a little for
  452.                 //        layout.  We have to know how to reverse
  453.                 //        these in Display.
  454.                 GetElement()->width += crBrowse.Width() + 2;
  455.                 GetElement()->border_horiz_space = 1;
  456.                 if(crBrowse.Height() >= GetElement()->height)    {
  457.                     GetElement()->height = crBrowse.Height();
  458.                     GetElement()->baseline = crBrowse.Height() - csz_cy / 4 - 1;
  459.                 }
  460.             }
  461.             else    {
  462.                 //    Nope.
  463.                 GetElement()->width = 0;
  464.                 GetElement()->height = 0;
  465.                 GetElement()->baseline = 0;
  466.             }
  467.         }
  468.         else if(GetContext()->IsPureDCContext())    {
  469.             //    Do some printing specific stuff here...
  470.             GetElement()->width = 0;
  471.             GetElement()->height = 0;
  472.             GetElement()->baseline = 0;
  473.         }
  474.     }
  475. }
  476.  
  477. //    Copy the current data out of the form element back into the
  478. //        layout struct.
  479. void CFormFile::UpdateCurrentData()
  480. {
  481.     //    Detect context type and do the right thing.
  482.     if(GetContext())    {
  483.         if(GetContext()->IsWindowContext())    {
  484.             if(m_pWidget && ::IsWindow(m_pWidget->GetSafeHwnd()) && GetElementTextData())    {
  485.                 //    Free off any current text.
  486.                 if(GetElementTextData()->current_text)    {
  487.                     XP_FREE(GetElementTextData()->current_text);
  488.                     GetElementTextData()->current_text = NULL;
  489.                 }
  490.  
  491.                 //    See if we've got anything.
  492.                 int32 lLength = m_pWidget->GetWindowTextLength();
  493.                 if(lLength > 0)    {
  494.                     GetElementTextData()->current_text = (XP_Block)XP_ALLOC(lLength + 1);
  495.                     if(GetElementTextData()->current_text)    {
  496.                         m_pWidget->GetWindowText((char *)GetElementTextData()->current_text, CASTINT(lLength + 1));
  497.                     }
  498.                 }
  499.             }
  500.         }
  501.         else if(GetContext()->IsPureDCContext())    {
  502.         }
  503.     }
  504. }
  505.  
  506. HWND CFormFile::GetRaw()
  507. {
  508.     //    We may be returning an overriding value instead of our main
  509.     //        widget.
  510.     if(m_pWidgetOverride)    {
  511.         return(m_pWidgetOverride->m_hWnd);
  512.     }
  513.  
  514.     //    Return only our main widget here (the interesting one).
  515.     //    The edit field, not the button.
  516.     return(m_pWidget ? m_pWidget->m_hWnd : NULL);
  517. }
  518.  
  519. CWnd *CFormFile::GetSecondaryWidget()
  520. {
  521.     //    Return the button widget so that click events can be 
  522.     //    processed correctly.
  523.     return(m_pBrowse);
  524. }
  525.  
  526.