dlgmgr.cpp

Go to the documentation of this file.
00001 // $Id: dlgmgr.cpp 1770 2007-06-17 19:42:21Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 // Implementation of the DialogManager class (bodge central)
00100 
00101 // Include files
00102 #include "camtypes.h"
00103 
00104 #include "dlgmgr.h"
00105 //#include "dialogop.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "simon.h"
00107 //#include "fixst256.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "fixstr8.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "list.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "infobar.h"
00113 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 //#include "msg.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00115 //#include "bars.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "dlgbar.h"
00117 //#include "cheklist.h"
00118 //#include "custmsg.h"
00119 //#include "sgallery.h"
00120 //#include "galbar.h"
00121 //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00122 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00123 #include "ccdc.h"
00124 //#include "bitbutn.h"
00125 //#include "bitc1ded.h"
00126 //#include "fonts.h"
00127 //#include "oilprog.h"  // beep()
00128 //#include "ctrlhelp.h"
00129 #include "camelot.h"
00130 #include "camframe.h"
00131 //#include "palman.h"
00132 #include "stack.h"
00133 #include "dropdown.h"   // Colour/Font dropdown combo box support
00134 #include "griddropdown.h"
00135 #include "unicdman.h"
00136 #include "appprefs.h"
00137 #include "helpuser.h"
00138 //#include "textres.h"  // required so we know what an _R(IDC_FONT_COMBO) is.
00139 //#include "fontdrop.h" // required so we know what a FontDropItem is.
00140 //#include "brdlgres.h"
00141 //#include "dlgcthlp.h"
00142 //#include "customlist.h"
00143 //#include "customedit.h"
00144 #include "dlgevt.h"
00145 #include "cartprov.h"
00146 #include "cartctl.h"
00147 #include "osrndrgn.h"
00148 //#include "dlgtypes.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00149 #include "statline.h"
00150 #include <wx/imaglist.h>
00151 
00152 DECLARE_SOURCE("$Revision: 1770 $");
00153 
00154 CC_IMPLEMENT_DYNAMIC(CGadgetImageList, CCObject);
00155 
00156 // Declare smart memory handling in Debug builds
00157 #define new CAM_DEBUG_NEW
00158 
00159 // Place all statics here please, ordered by class
00160 // Statics
00161 
00162 // DialogManager statics
00163 List DialogManager::DiscardStrList;
00164 List DialogManager::ScrollPageIncList;
00165 List DialogManager::DialogPositionList;
00166 
00167 IdToSerializedPaneInfo * DialogManager::s_pPaneInfoHash = NULL;
00168 
00169 wxWindow   *DialogManager::pDlgCurrent = NULL;   // Required for IsDialogMessage handling
00170 
00171 // The ActiveDialogStack is used to restore previously active dialogs after a Modal dialog
00172 // is closed.
00173 ActiveDlgStateStack DialogManager::ActiveDlgStack;
00174 
00175 // When the user clicks with the right mouse button on a dual function button BN_RGT_CLICKED
00176 // is returned as the notification code.
00177 #define BN_RGT_CLICKED 6
00178 
00179 
00180 class Node;
00181 
00182 /********************************************************************************************
00183 
00184 >   DialogManager::DialogManager()
00185 
00186     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00187     Created:    17/12/93
00188     Purpose:    DialogManager constructor. It allocates our special Property atom.
00189 
00190 ********************************************************************************************/
00191 
00192 DialogManager::DialogManager()
00193 {
00194     // we must use a unique string so we don't clash with anyone else
00195 }
00196 
00197 /********************************************************************************************
00198 
00199 >   BOOL        DialogManager::Create(DialogOp* DlgOp,
00200                                     HINSTANCE MainInstance, CDlgResID MainDlgID,
00201                                     HINSTANCE SubInstance,  CDlgResID SubDlgID,
00202                                     CDlgMode Mode, INT32 OpeningPage, CWindowID ParentWnd)
00203 
00204     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00205     Created:    17/8/93
00206 
00207     Inputs:     DlgOp:          The DialogOp we are creating a window for
00208 
00209                 The following inputs may soon become defunct
00210 
00211                 MainInstance:   Instance handle of the module that contains the dialog
00212                                 defined by MainDlgID.
00213                 MainDlgID:      Resource identifier of the main dialog box
00214                 SubInstance:    Instance handle of the module that contains the dialog
00215                                 defined by SubDlgID.
00216                 SubDlgID:       Resource identifier of the secondary dialog box to merge
00217                                 with the main one (0 if none).
00218                 Mode:           Dialog mode (Modal, Modeless)
00219                 OpeningPage:    Index of the tabbed page which we need to open (0 if none).
00220 
00221     Returns:    TRUE if the Dialog/Bar could be created, else FALSE
00222 
00223     Purpose:    The create method creates a Dialog box and positions it
00224 
00225                 If the Dialog is Modal then the dialog is displayed, to initialise the dialog
00226                 you must respond to the DIM_CREATE message.
00227 
00228                 If the Dialog is Modeless then the Open method needs to be called to make the
00229                 dialog visible.
00230 
00231                 If the dialog has not been created before then it is positioned centrally on
00232                 the screen. Otherwise the dialog's position is restored to the position it
00233                 was at the last time it was deleted.
00234 
00235                 If SubDlgID is non-0, then this dialog is merged with the main one during
00236                 the creation of the dialog.  If it is 0, then no merging is done (the
00237                 DialogOp() function should take care of all this), and SubInstance
00238                 is ignored.
00239 
00240                 If it is a tabbed dialog that is being created then we can now specify the
00241                 opening tab. Usually, this will be the first one if this box has not been
00242                 opened before or the one selected when it was closed. This parameter allows
00243                 this to be overriden.
00244 
00245                 Note that this function sets the DialogOps window ID
00246 
00247 
00248                 Note: It is important that all dialogs do not have the Visible property set.
00249 
00250     Errors:     An Error will be set if this function fails
00251 
00252     SeeAlso:    DialogOp::Create
00253 
00254 ********************************************************************************************/
00255 
00256 // First a private class definition
00257 // as this is missing two-stage create we have to use a static variable. Yuck.
00258 class wxDynamicPropertySheetDialog : public wxPropertySheetDialog
00259 {
00260 public:
00261     wxDynamicPropertySheetDialog() {m_TabType=TABTYPE_TABS;}
00262     ~wxDynamicPropertySheetDialog() {}
00263     void SetTabType(TabType t) {m_TabType=t;}
00264 protected:
00265     TabType m_TabType;
00266     virtual wxBookCtrlBase* CreateBookCtrl()
00267     {
00268         INT32 style = wxCLIP_CHILDREN | wxBC_DEFAULT;
00269         wxBookCtrlBase* pBook = NULL;
00270 
00271         switch (m_TabType)
00272         {
00273 #if wxUSE_LISTBOOK
00274             case TABTYPE_LIST:
00275                 return new wxListbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00276                 break;
00277 #endif
00278 #if wxUSE_CHOICEBOOK
00279             case TABTYPE_CHOICE:
00280                 return new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00281                 break;
00282 #endif
00283 #if wxUSE_TREEBOOK || wxXTRA_TREEBOOK
00284             case TABTYPE_TREE:
00285                 {
00286                     wxTreebook * t = new wxTreebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00287                     if (t)
00288                         t->GetTreeCtrl()->SetIndent(0);
00289                     return t;
00290                 }
00291                 break;
00292 #else
00293             // Default to a ListBook if there is no treebook availables
00294             case TABTYPE_TREE:
00295                 return new wxListbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00296                 break;
00297 #endif
00298 #if wxUSE_TOOLBOOK
00299             case TABTYPE_TOOLBAR:
00300                 return new wxToolbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00301                 break;
00302 #endif
00303             case TABTYPE_TABS:
00304             default:
00305                 pBook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style );
00306                     
00307 PORTNOTE("dialog", "This should probably be applied to all controls eventually")
00308                 // Fabricate a Xara standard font and associate it with notebook control
00309                 wxFont  fontDefault = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
00310                 fontDefault.SetPointSize( 8 );
00311                 pBook->SetFont( fontDefault );
00312                 
00313                 break;
00314         }
00315 
00316         return pBook;
00317     }
00318 };
00319 
00320 BOOL DialogManager::Create(DialogOp* DlgOp,
00321                         /* HINSTANCE MainInstance, */ CDlgResID MainDlgID,
00322                         /* HINSTANCE SubInstance, */  CDlgResID SubDlgID,
00323                         CDlgMode Mode, INT32 OpeningPage, CWindowID ParentWnd)
00324 {
00325     ERROR2IF(!DlgOp, FALSE, _T("Create Passed Null DialogOp"));
00326     ERROR2IF(DlgOp->pEvtHandler, FALSE, _T("Window has already been created. Having two is greedy"));
00327 
00328     DlgOp->pEvtHandler = new DialogEventHandler(DlgOp);
00329     ERRORIF(!DlgOp->pEvtHandler || !DlgOp->pEvtHandler->pDialogOp, FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
00330 
00331     BOOL wxAUImanaged = FALSE;
00332     if ( DlgOp->IsABar() || DlgOp->IsAGallery() )
00333     {
00334         BOOL modal = DlgOp->IsModal();
00335         ERROR2IF(modal, FALSE, "Attempting to create a wxAUImanaged Dialog that is modal");
00336         // They wanted a bar. Well, the main difference to us is we let wxAUI manage it.
00337         wxAUImanaged = TRUE;
00338     }
00339 
00340 //  ERROR2IF( DlgOp->IS_KIND_OF(DialogBarOp), FALSE, _T("Bar creation not yet supported"));
00341 //  ERROR2IF( DlgOp->IS_KIND_OF(DialogTabOp), FALSE, _T("Tabbed dialogs not yet supported"));
00342     ERROR2IF( SubDlgID !=0, FALSE, _T("Merging of dialogs not yet supported"));
00343 
00344     // if no parent dialog window specified use the main frame window
00345     if ((ParentWnd == NULL) || wxAUImanaged)
00346         ParentWnd = GetMainFrame();
00347 
00348     const TCHAR*    pDialogName = NULL;
00349     wxWindow*       pDialogWnd = NULL;
00350 
00351     if( DlgOp->IS_KIND_OF(DialogTabOp) && !(((DialogTabOp*)DlgOp)->LoadFrameFromResources()))
00352     {
00353         // ok first try and create the property sheet
00354         wxDynamicPropertySheetDialog* pPropertySheet;
00355 
00356         // error handling done later
00357         pPropertySheet = new wxDynamicPropertySheetDialog();
00358         if (pPropertySheet)
00359         {
00360             pPropertySheet->SetTabType(((DialogTabOp*)DlgOp)->GetTabType());
00361             if (!pPropertySheet->Create((wxWindow *)ParentWnd, wxID_ANY, (TCHAR*) (*((DialogTabOp*)DlgOp)->GetName()) ))
00362             {
00363                 delete pPropertySheet;
00364                 pPropertySheet=NULL; // error handling done below
00365             }
00366             else
00367             {
00368                 wxStdDialogButtonSizer *sizer = new wxStdDialogButtonSizer();
00369                 wxButton * ok=new wxButton(pPropertySheet, wxID_OK);
00370                 sizer->AddButton(ok); // Add an OK button
00371                 sizer->AddButton(new wxButton(pPropertySheet, wxID_CANCEL)); // Add a Cancel button
00372                 sizer->AddButton(new wxButton(pPropertySheet, wxID_APPLY)); // Add an Apply button
00373                 sizer->AddButton(new wxButton(pPropertySheet, wxID_HELP)); // Add a Help button
00374                 ok->SetDefault();
00375                 ok->SetFocus();
00376                 pPropertySheet->SetAffirmativeId(wxID_OK);
00377                 sizer->Realize();
00378                 pPropertySheet->GetInnerSizer()->Add( sizer, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxLEFT|wxRIGHT, 2);
00379                 pPropertySheet->GetInnerSizer()->AddSpacer(2);
00380             }
00381         }
00382         pDialogWnd=pPropertySheet;
00383     }
00384     else
00385     {
00386         pDialogName=CamResource::GetObjectNameFail(MainDlgID);
00387         ERROR1IF(pDialogName == NULL, FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
00388 
00389 PORTNOTE("dialog","A more general scheme is needed to allow creation of a panel for non-toolbar type dialog")
00390         if (wxAUImanaged || _R(IDD_BITMAPPREVIEWDIALOG) == MainDlgID )
00391             pDialogWnd = wxXmlResource::Get()->LoadPanel((wxWindow *)ParentWnd, pDialogName);
00392         else
00393             pDialogWnd = wxXmlResource::Get()->LoadDialog((wxWindow *)ParentWnd, pDialogName);
00394     }
00395 
00396     ERROR1IF(pDialogWnd == NULL, FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
00397 
00398     pDialogWnd->Hide();
00399     CamArtProvider::Get()->EnsureChildBitmapsLoaded(pDialogWnd);
00400 
00401     // On the Mac, panels etc. are by default transparent; fix them up
00402 #ifdef __WXMAC__
00403     pDialogWnd->SetBackgroundStyle(wxBG_STYLE_COLOUR);
00404     pDialogWnd->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
00405 #endif
00406 
00407     // Note that we might one day want to create (say) wxPanels, or wxToolbars instead above
00408     // It deosn't matter to us, we just want a wxWindow
00409 
00410     DlgOp->pEvtHandler->pwxWindow = pDialogWnd;
00411     DlgOp->pEvtHandler->wxAUImanaged = wxAUImanaged;
00412     DlgOp->pEvtHandler->ID =MainDlgID;
00413     // Set the DialogOp's WindowID
00414     DlgOp->WindowID = (CWindowID)pDialogWnd;
00415     pDialogWnd->PushEventHandler(DlgOp->pEvtHandler);
00416 
00417     if (DlgOp->IS_KIND_OF(DialogTabOp))
00418     {
00419         // on balance we might be best ignoring errors here - we are really now past
00420         // the point of no return, and the dialog can be closed cleanly by the user
00421         // but let's try anyway
00422         if (!CreateTabbedDialog( (DialogTabOp*)DlgOp, Mode, OpeningPage, MainDlgID ))
00423         {
00424             // try using our own tolerant delete mechanism
00425             Delete(pDialogWnd, DlgOp);
00426             ERROR1(FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
00427         }
00428     }
00429 
00430     CreateRecursor(pDialogWnd);
00431 
00432     // Register all the child controls
00433     ControlList::Get()->RegisterWindowAndChildren(pDialogWnd, DlgOp);
00434 
00435     ControlList::Get()->ReflectAllStates(); // might as well do the processing before the bar / dialog appears
00436 
00437     // we call this directly now
00438     BOOL ok = PostCreate(DlgOp, OpeningPage);
00439 
00440     if( ok && 
00441         Mode == MODAL && 
00442         pDialogWnd->IsKindOf( CLASSINFO(wxDialog) ) )
00443     {
00444         ((wxDialog *) pDialogWnd)->ShowModal();
00445     }
00446 
00447 #ifdef USE_WXAUI
00448     if (wxAUImanaged)
00449     {
00450         wxString Title = wxEmptyString;
00451         if (pDialogWnd->IsKindOf(CLASSINFO(wxDialog)))
00452             Title=((wxDialog *)pDialogWnd)->GetTitle();
00453         if (Title.IsEmpty()) Title = pDialogWnd->GetLabel(); // because wxPanel doesn't seem to support a title
00454         if (Title.IsEmpty())
00455         {
00456             const TCHAR * ResString=CamResource::GetTextFail(pDialogWnd->GetId());
00457             if (ResString)
00458                 Title=wxString(ResString);
00459         }
00460         if (Title.IsEmpty())
00461         {
00462             // Finally, in desperation, we (mis-)use the tooltip string because now the wx folks have removed
00463             // the label, even though it's needed for accessibility. Aarrghh
00464             wxToolTip* pTip = pDialogWnd->GetToolTip();
00465             if (pTip) Title=pTip->GetTip();
00466         }
00467         if (Title.IsEmpty())
00468             Title = wxString(CamResource::GetText(_R(IDS_ANONYMOUSBARTITLE)));
00469 
00470 
00471         // We really should take a wxPaneInfo() as an additional parameter to this function to allow this sort
00472         // of stuff to be specified. Or try and retrieve it from the DialogBarOp or similar. Anyway, for now
00473         // give it some default parameters
00474         wxAuiPaneInfo paneinfo;
00475         if (!DlgOp->IsABar())
00476         {
00477             // default galleries to 300 deep. Specifying -1 as a width doesn't seem to work
00478             paneinfo.FloatingSize(100,300);
00479         }
00480         LoadPaneInfo(wxString(CamResource::GetObjectName(pDialogWnd->GetId())), paneinfo);
00481         paneinfo.DestroyOnClose(FALSE);
00482         if (DlgOp->IsABar())
00483         {           
00484             if (DlgOp->IsKindOf(CC_RUNTIME_CLASS(StatusLine)))
00485                 paneinfo.Bottom().Layer(1).Row(2).LeftDockable(FALSE).RightDockable(FALSE).Floatable(FALSE).Movable(FALSE).Gripper(FALSE).CaptionVisible(FALSE).PaneBorder(FALSE);
00486             else    
00487             {
00488                 paneinfo.ToolbarPane().Fixed();
00489                 if (DlgOp->IsVertical())
00490                 {
00491                     paneinfo.Left().Layer(0).GripperTop().TopDockable(FALSE).BottomDockable(FALSE);
00492                 }
00493                 else
00494                 {
00495                     paneinfo.Top().Layer(1).Row(2).LeftDockable(FALSE).RightDockable(FALSE);
00496                 }
00497             }
00498         }
00499         else
00500         {
00501             // Gallery
00502             paneinfo.Layer(3).GripperTop().TopDockable(FALSE).BottomDockable(FALSE).Float().Dockable(FALSE); // temporarilly stop galleries from docking
00503         }
00504 
00505         if (DlgOp->IsKindOf(CC_RUNTIME_CLASS(InformationBarOp)))
00506         {
00507             paneinfo.Floatable(FALSE);  // temporarilly do not allow Info Bars to float as they can be closed
00508                                         // which means they can't be reopened (no UI), and wxAUI rightly objects to the
00509                                         // tool switch that deletes them deleting the window.
00510         }
00511 
00512         paneinfo.Name(pDialogName).Caption(Title).PinButton(TRUE);
00513 
00514         wxSizer * pSizer = pDialogWnd->GetSizer();
00515         if (pSizer)
00516         {
00517             pSizer->SetSizeHints(pDialogWnd);
00518             pDialogWnd->SetSizerAndFit(pSizer);
00519         }
00520 
00521         // Ensure the main frame is shown if the pane is floating, or it can get "behind"
00522         // the main frame on wxGTK
00523         if (paneinfo.IsFloating() && !CCamFrame::GetFrameManager()->GetManagedWindow()->IsShown())
00524             CCamFrame::GetFrameManager()->GetManagedWindow()->Show();
00525 
00526         CCamFrame::GetFrameManager()->AddPane(pDialogWnd, paneinfo);
00527 
00528         CCamFrame::GetMainFrame()->UpdateFrameManager();
00529 
00530         // Make sure newly created floating panes are at the top in an attempt to fix
00531         // Bugzilla bug 1393 (can't duplicate here...)
00532         wxWindow * pTLW = pDialogWnd;
00533         while (pTLW->GetParent())
00534             pTLW=pTLW->GetParent();
00535         if (pTLW->IsKindOf(CLASSINFO(wxAuiFloatingFrame)))
00536             pTLW->Raise();
00537 
00538     }
00539 #endif
00540 
00541     return ok;
00542 }
00543 
00544 /********************************************************************************************
00545 
00546 >   static void DialogManager::CreateRecursor(wxWindow * pwxWindow)
00547 
00548 
00549     Author:     Alex_Bligh <alex@alex.org.uk>
00550     Created:    02/12/2005
00551     Inputs:     pWindow - pointer to window to process
00552     Outputs:    None
00553     Returns:    None
00554     Purpose:    Initialize platform dependent resources
00555     Errors:     -
00556     SeeAlso:    -
00557 
00558 ********************************************************************************************/
00559 
00560 void DialogManager::CreateRecursor(wxWindow * pwxWindow)
00561 {
00562     // Process this one
00563     wxPlatformDependent::Get()->InitWindow(pwxWindow);
00564 
00565     // bodge OD combo boxes not to have scroll bars so often
00566     if (pwxWindow->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
00567     {
00568         ((wxOwnerDrawnComboBox*)pwxWindow)->SetPopupMaxHeight(600);
00569         ((wxOwnerDrawnComboBox*)pwxWindow)->SetPopupAnchor(wxLEFT);
00570     }
00571 
00572     // Now process children if any
00573     wxWindowList::Node * pNode = pwxWindow->GetChildren().GetFirst();
00574     while (pNode)
00575     {
00576         CreateRecursor(pNode->GetData());
00577         pNode = pNode->GetNext();
00578     }
00579     return;
00580 }
00581 
00582 
00583 /********************************************************************************************
00584 
00585 >   BOOL DialogManager::PostCreate(DialogOp * pDialogOp);
00586 
00587     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00588     Created:    6/9/94
00589     Inputs:     DialogWnd: The dialogs window ID, NULL if dialog failed to be created
00590     Returns:    -
00591     Purpose:    This function will get called after a dialog has been created. If a modeless
00592                 dialog has been created then it gets called directly from the Create method.
00593                 For a modal dialog however it gets called after receiving a WM_INIT_DIALOG
00594                 message. It completes the creation process.
00595 
00596                 (for now on wxWindows we are simply calling it from Create)
00597 
00598     Scope:      private
00599 
00600 ********************************************************************************************/
00601 
00602 BOOL DialogManager::PostCreate(DialogOp * pDialogOp, INT32 OpeningPage)
00603 {
00604     ERROR2IF( !pDialogOp || !pDialogOp->pEvtHandler || !pDialogOp->pEvtHandler->pwxWindow,
00605             FALSE, _T("Bad DialogOp / EvtHandler in DialogManager::PostCreate()"));
00606 
00607     wxWindow * pDialogWnd = pDialogOp->pEvtHandler->pwxWindow;
00608 
00609     // If the dialog has been created before then its position will have to be reset
00610     INT32 DlgX=0; // Dialog box X position
00611     INT32 DlgY=0; // Dialog box Y position
00612     CDlgResID ActivePage=0; // Active page for tabbed dialogs
00613     UINT32 ActivePageIndex=0;
00614 
00615     BOOL CreatedBefore = FALSE; // TRUE if the dialog has been created before
00616 
00617     wxBookCtrlBase * pBook=NULL;
00618     // Only do special processing for DialogTabOp
00619     if (pDialogOp->IS_KIND_OF(DialogTabOp))
00620         pBook=GetBookControl(pDialogWnd);
00621 
00622     ResourceID BookGadget=pBook?pBook->GetId():0;
00623 
00624     if (pBook && (OpeningPage>=0))
00625     {
00626         ActivePage = pBook->GetPage(OpeningPage)->GetId();
00627         ActivePageIndex = OpeningPage;
00628     }
00629 
00630     // Search the DialogPositionList to see if the dialog has been created before
00631     DialogPosition* DlgPos = FindDialogPositionRecord(pDialogOp->pEvtHandler->ID);
00632     if (DlgPos != NULL)
00633     {
00634         DlgX = DlgPos->LastX;
00635         DlgY = DlgPos->LastY;
00636 
00637         // Find the last active page if there was one
00638         if (OpeningPage<0)
00639         {
00640             ActivePage = DlgPos->ActivePage;
00641             ActivePageIndex = DlgPos->ActivePageIndex;
00642         }
00643         CreatedBefore = TRUE;
00644     }
00645 
00646     if (pBook && ((ActivePageIndex<0) ||
00647                     (ActivePageIndex >= pBook->GetPageCount()) ||
00648                     ((UINT32)(pBook->GetPage(ActivePageIndex)->GetId()) != ActivePage)
00649                 ))
00650     {
00651         ActivePageIndex=0;
00652         ActivePage = pBook->GetPage(0)->GetId();
00653     }
00654 
00655     // Get the size of the dialog box (Required for the SetWindowPos function)
00656     wxRect  DialogRect( pDialogWnd->GetRect() );
00657     INT32   DialogWidth  = DialogRect.GetWidth();
00658     INT32   DialogHeight = DialogRect.GetHeight();
00659 
00660     // Create the WindowIDItem which will be stored in the DialogPosition.
00661     CWindowIDItem *pWinID = new CWindowIDItem;
00662     if( NULL == pWinID )
00663     {
00664         // We need to destroy the dialog window
00665         pDialogWnd->PopEventHandler(FALSE);
00666         pDialogOp->pEvtHandler->Destroy();
00667         pDialogWnd->Destroy();
00668         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));
00669     }
00670 
00671 
00672     if (!CreatedBefore) // If this is the first time the dialog has been created then position
00673                         // it centrally on the screen
00674     {
00675         // Get the size of the screen
00676         INT32           ScreenWidth  = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
00677         INT32           ScreenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
00678 
00679         // Centre the dialog box
00680         DlgX = (ScreenWidth - DialogWidth) / 2;
00681         DlgY = (ScreenHeight - DialogHeight) / 2;
00682 
00683         // Create a DialogPosition record
00684         DlgPos = new DialogPosition;
00685         if (DlgPos == NULL)
00686         {
00687             // We need to destroy the dialog window
00688             pDialogWnd->PopEventHandler(FALSE);
00689             pDialogOp->pEvtHandler->Destroy();
00690             pDialogWnd->Destroy();
00691             return FALSE; // Failed to created DialogPosition record
00692         }
00693         DlgPos->DlgResourceID = pDialogOp->pEvtHandler->ID;
00694 
00695         // Even though the position is recorded when the dialog is deleted. It is neccessary
00696         // to record it here also because another dialog with the same resource ID could be
00697         // created before this dialog is deleted.
00698         DlgPos->LastX = DlgX;
00699         DlgPos->LastY = DlgY;
00700 
00701         DlgPos->ActivePage = 0;
00702         DlgPos->ActivePageIndex=0;
00703 
00704         if (pBook)
00705         {
00706             // Record the active page.
00707             DlgPos->ActivePage = ActivePage;
00708             DlgPos->ActivePageIndex = ActivePageIndex;
00709         }
00710         // Add the position record to the DialogPositionList
00711         DialogPositionList.AddHead((ListItem*)DlgPos);
00712     }
00713 
00714     // Store the Dialog window handle in the position record.
00715     pWinID->DlgWin = pDialogWnd;
00716     DlgPos->DlgWinList.AddTail( pWinID );
00717 
00718         // Position the dialog
00719     pDialogWnd->SetSize(DlgX, DlgY, DialogWidth, DialogHeight);
00720 
00721         // In japan we need to set the font so it dosen't use the default ANSI MS San Serif
00722 PORTNOTE("dialog","Removed FontFactory usage")
00723 #ifndef EXCLUDE_FROM_XARALX
00724     if( UnicodeManager::IsDBCSOS() )
00725         FontFactory::ApplyFontToWindow( DialogWnd, STOCKFONT_DIALOG ); */
00726 #endif
00727 
00728     // Inform the Dialog that it has been created so that it can be initialised
00729     // Note that for DialogTabOp's seperate Create messages are sent for each page
00730     // from the wxNotebookPage OnCreate handler.
00731     // Alex moved this inside the if statement
00732     BROADCAST_TO_CLASS( DialogMsg( pDialogOp->WindowID, DIM_CREATE, 0 ), DialogOp );
00733 
00734     if (pBook)
00735     {
00736         // BROADCAST a create message to each page
00737         UINT32 i;
00738         for (i=0; i<pBook->GetPageCount(); i++)
00739         {
00740             BROADCAST_TO_CLASS(DialogMsg(pDialogOp->WindowID, DIM_CREATE, BookGadget, 0, pBook->GetPage(i)->GetId()) ,DialogOp);
00741         }
00742 
00743         // And tell the active page which is active
00744         BROADCAST_TO_CLASS( DialogMsg( pDialogOp->WindowID, DIM_SET_ACTIVE, BookGadget, 0, ActivePage ), DialogOp );
00745         pBook->SetSelection(ActivePageIndex);
00746     }
00747 
00748     // If the dialog which has just been created is modal then disable all other
00749     // dialogs.
00750 
00751     if( !GetMainFrame()->IsEnabled() )
00752     {
00753         EnableAllDialogs(FALSE, pDialogWnd);
00754     }
00755 
00756     return TRUE; // Success
00757 }
00758 
00759 /********************************************************************************************
00760 
00761 >   void DialogManager::InitPaneInfoHash
00762 
00763     Author:     Alex Bligh <alex@alex.org.uk>
00764     Created:    25/07/06
00765     Inputs:     -
00766     Outputs:    -
00767     Returns:    -
00768     Purpose:    Initializes the pane info hash if it has not been previously initialized
00769     Scope:      protected
00770 
00771 ********************************************************************************************/
00772 
00773 void DialogManager::InitPaneInfoHash()
00774 {
00775     if (s_pPaneInfoHash)
00776         return;
00777 
00778     s_pPaneInfoHash = new IdToSerializedPaneInfo;
00779 }
00780 
00781 /********************************************************************************************
00782 
00783 >   void DialogManager::FreePaneInfoHash
00784 
00785     Author:     Alex Bligh <alex@alex.org.uk>
00786     Created:    25/07/06
00787     Inputs:     -
00788     Outputs:    -
00789     Returns:    -
00790     Purpose:    Free the pane info hash if it exists
00791     Scope:      protected
00792 
00793 This function MUST be called ONLY after the preference system has been de-inited. This
00794 may be after dialogmanager deinit.
00795 
00796 ********************************************************************************************/
00797 
00798 void DialogManager::FreePaneInfoHash()
00799 {
00800     if (s_pPaneInfoHash)
00801     {
00802         delete s_pPaneInfoHash;
00803         s_pPaneInfoHash = NULL;
00804     }
00805 }
00806 
00807 /********************************************************************************************
00808 
00809 >   void DialogManager::EnsurePanePreferenceDeclared(key)
00810 
00811     Author:     Alex Bligh <alex@alex.org.uk>
00812     Created:    25/07/06
00813     Inputs:     key - the key the pane info will be stored under
00814     Outputs:    None
00815     Returns:    None
00816     Purpose:    Ensures the relevant preference has been declared
00817     Scope:      protected
00818 
00819 ********************************************************************************************/
00820 
00821 void DialogManager::EnsurePanePreferenceDeclared(wxString key)
00822 {
00823     if (!s_pPaneInfoHash)
00824         InitPaneInfoHash();
00825 
00826     if (!s_pPaneInfoHash)
00827         return;
00828 
00829     IdToSerializedPaneInfo::iterator i=s_pPaneInfoHash->find(key);
00830     if (i==s_pPaneInfoHash->end())
00831     {
00832         // ok, it's not in the hash, so it can't have been declared as a preference
00833         // yet. So we will declare it as a preference now
00834         (*s_pPaneInfoHash)[key]=_T("");
00835         i=s_pPaneInfoHash->find(key);
00836         if (i==s_pPaneInfoHash->end())
00837         {
00838             ERROR3("This hash leaks like a seive");
00839             return;
00840         }
00841         // --------------------------------------------------------------------------
00842         // Detect first-time run and make Open File dialog default to Examples folder
00843         if (Camelot.DeclareSection(_T("BarPositions"), 10))
00844         {
00845             Camelot.DeclarePref( NULL, (TCHAR *)(key.c_str()), &(i->second) );
00846         }
00847     }
00848 }
00849 
00850 
00851 
00852 /********************************************************************************************
00853 
00854 >   void DialogManager::LoadPaneInfo(wxString key, wxPaneInfo &paneinfo)
00855 
00856     Author:     Alex Bligh <alex@alex.org.uk>
00857     Created:    25/07/06
00858     Inputs:     key - the key the pane info will be stored under
00859     Outputs:    paneinfo - the wxAUI pane info structure
00860     Returns:    None
00861     Purpose:    Loads the pane info structure from the hash
00862     Scope:      protected
00863 
00864 ********************************************************************************************/
00865 
00866 void DialogManager::LoadPaneInfo(wxString key, wxAuiPaneInfo &paneinfo)
00867 {
00868     if (!s_pPaneInfoHash)
00869         InitPaneInfoHash();
00870 
00871     if (!s_pPaneInfoHash)
00872         return;
00873 
00874     EnsurePanePreferenceDeclared(key);
00875 
00876     IdToSerializedPaneInfo::iterator i=s_pPaneInfoHash->find(key);
00877     if (i==s_pPaneInfoHash->end())
00878         return;
00879 
00880     // do not bother trying to process empty strings
00881     if (i->second.IsEmpty())
00882         return;
00883 
00884     TRACEUSER("amb", _T("key=%s"), (const TCHAR *)key);
00885     TRACEUSER("amb", _T("val=%s"), (const TCHAR *)(i->second));
00886 
00887     wxString name = (wxString)((const TCHAR *)(i->second));
00888     CCamFrame::GetFrameManager()->LoadPaneInfo(name, paneinfo);
00889 }
00890 
00891 /********************************************************************************************
00892 
00893 >   void DialogManager::SavePaneInfo(wxPaneInfo &paneinfo)
00894 
00895     Author:     Alex Bligh <alex@alex.org.uk>
00896     Created:    25/07/06
00897     Inputs:     key - the key the pane info will be stored under
00898                 paneinfo - the wxAUI pane info structure
00899     Returns:    None
00900     Purpose:    Saves the pane info structure to the hash
00901     Scope:      protected
00902 
00903 ********************************************************************************************/
00904 
00905 void DialogManager::SavePaneInfo(wxString key, wxAuiPaneInfo &paneinfo)
00906 {
00907     // work around mysterious wxGTK sizing bug
00908     if ((paneinfo.IsOk()) && (paneinfo.IsFloating()))
00909     {
00910         paneinfo.FloatingSize(paneinfo.window->GetParent()->GetSize());
00911     }
00912 
00913     if (!s_pPaneInfoHash)
00914         InitPaneInfoHash();
00915 
00916     if (!s_pPaneInfoHash)
00917         return;
00918 
00919     EnsurePanePreferenceDeclared(key);
00920 
00921     (*s_pPaneInfoHash)[key]=CCamFrame::GetFrameManager()->SavePaneInfo(paneinfo);
00922 }
00923 
00924 /********************************************************************************************
00925 
00926 >   static DialogPosition* DialogManager::FindDialogPositionRecord(CDlgResID DialogID)
00927 
00928     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00929     Created:    5/12/94
00930     Inputs:     DialogID: The dialog's resource id
00931     Returns:    The DialogPosition record for the dialog, or NULL if the dialog has not been
00932                 created before
00933     Purpose:    Searches the DialogPositionList to see if this dialog has been created before
00934                 if it has then a pointer to its DialogPosition record is returned,
00935                 else NULL is retuned.
00936     Scope:      private
00937 
00938 ********************************************************************************************/
00939 
00940 DialogPosition* DialogManager::FindDialogPositionRecord(CDlgResID DialogID)
00941 {
00942     // Search the DialogPositionList to see if the dialog has been created before
00943     DialogPosition* DlgPos = (DialogPosition*)(DialogPositionList.GetHead());
00944     while (DlgPos != NULL)
00945     {
00946         if (DlgPos->DlgResourceID == DialogID) // The dialog has been created before
00947         {
00948             return DlgPos;
00949             break;
00950         }
00951         // Get the next DialogPosition record
00952         DlgPos = (DialogPosition*)(DialogPositionList.GetNext((ListItem*)DlgPos));
00953     }
00954     return NULL; // Dialog has not been created before
00955 }
00956 
00957 
00958 
00959 /********************************************************************************************
00960 
00961 >   void DialogManager::Open(CWindowID WindowID, DialogOp* pDlgOp)
00962     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
00963     Created:    17/8/93
00964     Inputs:     WindowID: Dialog's window identifier
00965                 pDlgOp:   The DialogOp
00966     Purpose:    The Open method displays a modeless dialog box.
00967                 If the dialog is modal then it will have already been opened in the Create
00968                 method.
00969     SeeAlso:    DialogOp::Open
00970 
00971 ********************************************************************************************/
00972 
00973 void DialogManager::Open(CWindowID WindowID, DialogOp* pDlgOp)
00974 {
00975     // Determine if we are opening a bar
00976 PORTNOTE("dialog","Removed DialogBarOp usage")
00977 #ifndef EXCLUDE_FROM_XARALX
00978     if (pDlgOp->IsKindOf(CC_RUNTIME_CLASS(DialogBarOp)))
00979     {
00980         // Find the BaseBar object
00981         BaseBar         *pCWnd = (wxWindow *)WindowID;
00982         ENSURE( pCWnd != NULL, "Could not find bar object" );
00983         // Show the bar window
00984         if( pCWnd != NULL )
00985         {
00986             pCWnd->Show( (DialogBarOp *)pDlgOp );
00987         }
00988     }
00989     else
00990 #endif
00991     if( !pDlgOp->IsModal() ) // The create method opens a modal dialog
00992     {
00993         ( (wxWindow *)WindowID )->Show( true ); // Show the hidden dialog
00994     }
00995 
00996     if (pDlgOp->pEvtHandler->wxAUImanaged)
00997         CCamFrame::GetMainFrame()->UpdateFrameManager();
00998 
00999 }
01000 
01001 
01002 /********************************************************************************************
01003 
01004 >   void DialogManager::Close(CWindowID WindowID, DialogOp* pDlgOp)
01005 
01006     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01007     Created:    17/8/93
01008     Inputs:     WindowID: Dialog's window identifier
01009                 pDlgOp:   The DialogOp
01010     Purpose:    The close method removes a modeless dialog from the display but keeps all system
01011                 resources associated with it. It hides the dialog.
01012                 It can be called on a modal dialog but it does nothing.
01013     SeeAlso:    DialogOp::Close
01014 
01015 ********************************************************************************************/
01016 
01017 void DialogManager::Close(CWindowID WindowID, DialogOp* pDlgOp)
01018 {
01019     // Hide the dialog
01020 
01021     // Determine if we are hiding a bar
01022 PORTNOTE("dialog","Removed DialogBarOp usage")
01023 #ifndef EXCLUDE_FROM_XARALX
01024     if (pDlgOp->IsKindOf(CC_RUNTIME_CLASS(DialogBarOp)))
01025     {
01026         // Find the BaseBar object
01027         wxWindow* pCWnd = CWnd::FromHandlePermanent(WindowID);
01028         ENSURE(pCWnd != NULL, "Could not find bar object");
01029         // Show the bar window
01030         if (pCWnd != NULL)
01031         {
01032             ((BaseBar*)pCWnd)->Hide((DialogBarOp*)pDlgOp);
01033         }
01034     }
01035     else
01036 #endif
01037     if (!(pDlgOp->IsModal())) // The delete method closes a modal dialog
01038     {
01039         ENSURE(WindowID != NULL,"NULL WindowID");
01040         ( (wxWindow *)WindowID )->Show( false );
01041     }
01042 
01043     if (pDlgOp->pEvtHandler->wxAUImanaged)
01044         CCamFrame::GetMainFrame()->UpdateFrameManager();
01045 }
01046 
01047 
01048 /********************************************************************************************
01049 
01050 >   static BOOL MergeDialogs( CWindowID Dialog, CWindowID Mergee, bool fAbove )
01051 
01052     Author:     Luke_Hart (Xara Group Ltd) <lukeh@xara.com>
01053     Created:    21/07/2006
01054     Inputs:     -
01055     Returns:    FALSE if the function failed.
01056     Purpose:    This function places the contents of a dialog above or below the
01057                 contents of an existing dialog
01058 
01059 ********************************************************************************************/
01060 BOOL DialogManager::MergeDialogs( CWindowID Dialog, CWindowID Mergee, bool fAbove )
01061 {
01062     wxSizer*            pMainSizer = Dialog->GetSizer();
01063     wxSizer*            pVertSizer( new wxBoxSizer( wxVERTICAL ) );
01064     if( fAbove )
01065         pVertSizer->Add( Mergee, wxALL );
01066     pVertSizer->Add( pMainSizer );
01067     if( !fAbove )
01068         pVertSizer->Add( Mergee, wxALL );
01069 
01070     Dialog->SetSizerAndFit( pVertSizer, false );
01071     return TRUE;
01072 }
01073 
01074 
01075 /********************************************************************************************
01076 
01077 >   static BOOL DialogManager::BringToTop(CWindowID WindowID)
01078 
01079     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01080     Created:    27/6/95
01081     Inputs:     -
01082     Returns:    FALSE if the function failed.
01083     Purpose:    This function brings an open dialog to the top of the z-order
01084 
01085 ********************************************************************************************/
01086 
01087 BOOL DialogManager::BringToTop(CWindowID WindowID, DialogOp* pDlgOp)
01088 {
01089     ERROR2IF(!WindowID, FALSE, "BringToTop called on a dialog without a window");
01090     ( (wxWindow *)WindowID )->Raise();
01091     if (pDlgOp->pEvtHandler->wxAUImanaged)
01092         CCamFrame::GetMainFrame()->UpdateFrameManager();
01093     return TRUE;
01094 }
01095 
01096 
01097 
01098 /********************************************************************************************
01099 
01100 >   static void DialogManager::Event (DialogEventHandler *pEvtHandler, wxEvent &event)
01101 
01102     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01103     Created:    16/9/93
01104     Purpose:    OnCommand message handler. Translates a windows Command message into a DIM
01105     Errors:     -
01106     SeeAlso:    -
01107 
01108 ********************************************************************************************/
01109 
01110 void DialogManager::Event (DialogEventHandler *pEvtHandler, wxEvent &event)
01111 {
01112     WXTYPE EventType = event.GetEventType();
01113 //  CDlgMessage DIM = DIM_NONE;
01114     ResourceID id = event.GetId();
01115     UINT_PTR DlgMsgParam = 0;
01116     INT32 PageID = 0;
01117     BOOL HandleMessage=FALSE;
01118     BOOL Defer=TRUE;
01119 
01120     if (!pEvtHandler->pwxWindow || !pEvtHandler->pDialogOp)
01121     {
01122         // We are in the process of destruction
01123         event.Skip();
01124         return;
01125     }
01126 
01127     // First handle events we previously asked to defer processing of
01128     if (event.IsKindOf(CLASSINFO(wxCamDialogEvent)) && (EventType == wxEVT_CAMDIALOG_DEFERREDMSG))
01129     {
01130         // We posted this event and asked it to come back later, and it duly has
01131         wxCamDialogEvent * pDialogEvent = (wxCamDialogEvent *)(&event);
01132         pDialogEvent->msg.DlgWndID = pEvtHandler->pwxWindow; // this ensures we are using a valid window pointer
01133         // Send it around
01134         BROADCAST_TO_CLASS( DialogMsg(pDialogEvent->msg), DialogOp );
01135         return;
01136     }
01137 
01138     wxWindow * pGadget = NULL;
01139     if (id) pGadget = GetGadget(pEvtHandler->pwxWindow, id);
01140 
01141     // We tend to get this second-hand from our child, we handle this differently
01142     if( !pGadget && (event.GetEventObject() != pEvtHandler->pwxWindow))
01143     {
01144         pGadget = (wxWindow *)event.GetEventObject();
01145         id = pGadget->GetId();
01146     }
01147 
01148     // Try and find-out whether our control is part of a tabbed dialog page
01149     if( NULL != pGadget )
01150     {
01151         // pEvtHandler->pwxWindow maybe our immediate wxPanel\wxDialog, but won't
01152         // be in case of tabbed dialog
01153         wxWindow*   pDialog = pGadget->GetParent();
01154         while( NULL != pDialog && !pDialog->IsKindOf( CLASSINFO(wxDialog) ) && 
01155             !pDialog->IsKindOf( CLASSINFO(wxPanel) ) )
01156         {
01157             pDialog = pDialog->GetParent();
01158         }
01159 
01160         // Could this be part of a tabbed dialog?
01161         if( NULL != pDialog && pDialog->IsKindOf( CLASSINFO(wxPanel) ) )
01162         {
01163             // A parent of type wxBookCtrlBase would synch it
01164             wxWindow *pDialogParent = pDialog->GetParent();
01165             if( NULL != pDialogParent && pDialogParent->IsKindOf( CLASSINFO(wxBookCtrlBase) ) )
01166                 PageID = pDialog->GetId();
01167         }
01168     }
01169 
01170     // Make up a default message
01171     DialogMsg msg(pEvtHandler->pwxWindow, DIM_NONE, id, DlgMsgParam, PageID);
01172 
01173     if (!event.IsKindOf(CLASSINFO(wxMouseEvent))) // MouseEvents are too noisy
01174     {
01175         TRACEUSER("amb",_T("event %d(%s) received, ID=%d(%s), wxw=%llx"), EventType, DialogEventHandler::GetEventName(EventType), id,
01176                     CamResource::GetObjectName((ResourceID)id), pEvtHandler->pwxWindow);
01177     }
01178 
01179     if (
01180         (EventType == wxEVT_LEFT_DCLICK) ||
01181         (EventType == wxEVT_MIDDLE_DCLICK) ||
01182         (EventType == wxEVT_RIGHT_DCLICK) ||
01183         FALSE)
01184     {
01185         // OK, these are a bit deadly. We expected there to be TWO mouse up mouse downs. People
01186         // don't seem to hang off double clicks themselves, but do their own double click handling
01187         // (why oh why). So we generate an extra mouse down and mouse up, and sending them to
01188         // ourselves. This may not be necessary on all platforms.
01189         wxMouseEvent *MouseDown = (wxMouseEvent *)(event.Clone());
01190         wxMouseEvent *MouseUp = (wxMouseEvent *)(event.Clone());
01191         if (MouseDown && MouseUp)
01192         {
01193             if (EventType == wxEVT_LEFT_DCLICK)
01194             {
01195                 MouseDown->SetEventType(wxEVT_LEFT_DOWN);
01196                 MouseUp->SetEventType(wxEVT_LEFT_UP);
01197             }
01198             else if (EventType == wxEVT_MIDDLE_DCLICK)
01199             {
01200                 MouseDown->SetEventType(wxEVT_MIDDLE_DOWN);
01201                 MouseUp->SetEventType(wxEVT_MIDDLE_UP);
01202             }
01203             else
01204             {
01205                 MouseDown->SetEventType(wxEVT_RIGHT_DOWN);
01206                 MouseUp->SetEventType(wxEVT_RIGHT_UP);
01207             }
01208             
01209             //MouseDown.SetEventObject(pEvtHandler->pwxWindow);
01210             // MouseUp.SetEventObject(pEvtHandler->pwxWindow);
01211             // set it for processing later
01212             pEvtHandler->pwxWindow->GetEventHandler()->ProcessEvent(*MouseDown);
01213             pEvtHandler->pwxWindow->GetEventHandler()->ProcessEvent(*MouseUp);
01214         }
01215         if (MouseDown) delete MouseDown;
01216         if (MouseUp) delete MouseUp;
01217     }   
01218 
01219     /* Here is a list of possible command events
01220     wxEVT_COMMAND_BUTTON_CLICKED
01221     wxEVT_COMMAND_CHECKBOX_CLICKED
01222     wxEVT_COMMAND_CHOICE_SELECTED
01223     wxEVT_COMMAND_LISTBOX_SELECTED
01224     wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
01225     wxEVT_COMMAND_CHECKLISTBOX_TOGGLED
01226     wxEVT_COMMAND_TEXT_UPDATED  // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01227     wxEVT_COMMAND_TEXT_ENTER    // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01228     wxEVT_COMMAND_TEXT_URL      // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01229     wxEVT_COMMAND_TEXT_MAXLEN   // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01230     wxEVT_COMMAND_MENU_SELECTED
01231     wxEVT_COMMAND_SLIDER_UPDATED
01232     wxEVT_COMMAND_RADIOBOX_SELECTED
01233     wxEVT_COMMAND_RADIOBUTTON_SELECTED
01234     wxEVT_COMMAND_SCROLLBAR_UPDATED // Obselete - see wxWVT_SCROLL
01235     wxEVT_COMMAND_VLBOX_SELECTED
01236     wxEVT_COMMAND_COMBOBOX_SELECTED
01237     wxEVT_COMMAND_TOOL_RCLICKED
01238     wxEVT_COMMAND_TOOL_ENTER
01239     wxEVT_COMMAND_SPINCTRL_UPDATED
01240 
01241     We can't use switch on these - GRRR!
01242     */
01243 
01244     if (
01245         (EventType == wxEVT_COMMAND_BUTTON_CLICKED) ||
01246         FALSE)
01247     {
01248         // We should cope with Right Button here
01249         if ((ResourceID)id == _R(wxID_OK) )
01250         {
01251             msg.DlgMsg = DIM_COMMIT;
01252             HandleMessage = TRUE;
01253         }
01254         else if (id == _R(ID_CC_APPLY_NOW))
01255         {
01256             // Clicking on the apply now button is the same as a soft commit
01257             msg.DlgMsg = DIM_SOFT_COMMIT;
01258             HandleMessage = TRUE;
01259         }
01260         else if (id == _R(wxID_CANCEL))
01261         {
01262             msg.DlgMsg = DIM_CANCEL;
01263             // Do not defer processing of clicks on the close button because the default handler may destroy the window on
01264             // exit from this call
01265             Defer=FALSE; 
01266             HandleMessage = TRUE;
01267         }
01268         else if (id == _R(wxID_HELP))
01269         {
01270             // Our clients expect this ID, so keep them happy
01271             msg.DlgMsg = DIM_LFT_BN_CLICKED;
01272             msg.GadgetID = _R(ID_HELP);
01273             HandleMessage = TRUE;
01274         }
01275         else
01276         {
01277             msg.DlgMsg = DIM_LFT_BN_CLICKED;
01278             HandleMessage = TRUE;
01279         }
01280     }
01281     else if (
01282         (EventType == wxEVT_COMMAND_CHOICE_SELECTED) ||
01283         (EventType == wxEVT_COMMAND_LISTBOX_SELECTED) ||
01284         (EventType == wxEVT_COMMAND_CHECKLISTBOX_TOGGLED) ||
01285 //      We skip this because it's generated when we change the text ourselves. We should probably do something more subtle
01286 //      (EventType == wxEVT_COMMAND_TEXT_UPDATED) ||    // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01287         (EventType == wxEVT_COMMAND_TEXT_URL) ||        // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01288 //      (EventType == wxEVT_COMMAND_TEXT_MAXLEN) ||     // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01289         (EventType == wxEVT_COMMAND_MENU_SELECTED) ||
01290 //      (EventType == wxEVT_COMMAND_SLIDER_UPDATED) ||
01291         (EventType == wxEVT_COMMAND_RADIOBOX_SELECTED) ||
01292         (EventType == wxEVT_COMMAND_VLBOX_SELECTED) ||
01293         (EventType == wxEVT_COMMAND_COMBOBOX_SELECTED) ||
01294         (EventType == wxEVT_COMMAND_SPINCTRL_UPDATED) ||
01295         ((
01296         (EventType == wxEVT_SCROLL_CHANGED) || 
01297         (EventType == wxEVT_SCROLL_THUMBTRACK) || 
01298         (EventType == wxEVT_SCROLL_THUMBRELEASE) ||
01299         (EventType == wxEVT_SCROLL_LINEUP) ||
01300         (EventType == wxEVT_SCROLL_LINEDOWN) ||
01301         (EventType == wxEVT_SCROLL_PAGEUP) ||
01302         (EventType == wxEVT_SCROLL_PAGEDOWN)
01303         ) &&
01304         !(
01305           (pGadget && pGadget->IsKindOf(CLASSINFO(wxSlider))) ||
01306           (pGadget && pGadget->IsKindOf(CLASSINFO(wxSliderCombo)))
01307         )
01308         ) || // Don't handle slider scroll stuff here
01309         (EventType == wxEVT_COMMAND_TREE_SEL_CHANGED) ||
01310         FALSE)
01311     {
01312         msg.DlgMsg = DIM_SELECTION_CHANGED;
01313         msg.DlgMsgParam = NO_COMMIT;
01314         HandleMessage = TRUE;
01315     }
01316     else if( EventType == wxEVT_COMMAND_TEXT_UPDATED &&     // only with WXWIN_COMPATIBILITY_EVENT_TYPES
01317         pGadget == wxWindow::FindFocus() )
01318     {
01319         msg.DlgMsg = DIM_TEXT_CHANGED;
01320         HandleMessage = TRUE;
01321     }
01322     else if(
01323         (EventType == wxEVT_COMMAND_TEXT_ENTER) ||
01324         FALSE)
01325     {
01326         msg.DlgMsg = DIM_SELECTION_CHANGED;
01327         msg.DlgMsgParam = ENTER_COMMIT;
01328         HandleMessage = TRUE;
01329     }
01330     else if(
01331         (( (EventType == wxEVT_SCROLL_THUMBTRACK) ||
01332         (EventType == wxEVT_SCROLL_LINEUP) ||
01333         (EventType == wxEVT_SCROLL_LINEDOWN) ||
01334         (EventType == wxEVT_SCROLL_PAGEUP) ||
01335         (EventType == wxEVT_SCROLL_PAGEDOWN)
01336         ) && (pGadget && ( pGadget->IsKindOf(CLASSINFO(wxSlider)) || pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) ))) || 
01337         FALSE) // Handle slider movements - note SCROLL_CHANGED always comes later
01338     {
01339         msg.DlgMsg = DIM_SLIDER_POS_CHANGING;
01340         HandleMessage = TRUE;
01341     }
01342     else if(
01343         // Do not handle THUMB_RELEASE because we get a SCROLL_CHANGED anyway, and having two means we generate two SETs which will generate 2 undo records
01344         // on (for instance) transparency and Bevel tools
01345         ((/*EventType == wxEVT_SCROLL_THUMBRELEASE ||*/ EventType == wxEVT_SCROLL_CHANGED) &&
01346          ( (pGadget && pGadget->IsKindOf(CLASSINFO(wxSlider))) || (pGadget && pGadget->IsKindOf(CLASSINFO(wxSliderCombo))) )
01347         ) || // Handle slider changes
01348         FALSE)
01349     {
01350         msg.DlgMsg = DIM_SLIDER_POS_SET;
01351         HandleMessage = TRUE;
01352     }
01353     else if(
01354         (EventType == wxEVT_COMMAND_CHECKBOX_CLICKED) ||
01355         (EventType == wxEVT_COMMAND_RADIOBUTTON_SELECTED) ||
01356         FALSE)
01357     {
01358         msg.DlgMsg = DIM_LFT_BN_CLICKED; // apparently not a DIM_SELECTION_CHANGED - the click itself is eaten by the radio control - please do not change - AMB
01359         HandleMessage = TRUE;
01360     }
01361     else if (
01362         (EventType == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED) ||
01363         FALSE)
01364     {
01365         msg.DlgMsg = DIM_SELECTION_CHANGED_COMMIT;
01366         HandleMessage = TRUE;
01367     }
01368     else if (
01369         (EventType == wxEVT_LEFT_DOWN) ||
01370         FALSE)
01371     {
01372         msg.DlgMsg = DIM_LFT_BN_DOWN;
01373         HandleMessage = TRUE;
01374     }   
01375     else if (
01376         (EventType == wxEVT_LEFT_UP) ||
01377         FALSE)
01378     {
01379         msg.DlgMsg = DIM_LFT_BN_UP;
01380         HandleMessage = TRUE;
01381     }   
01382     else if (
01383         (EventType == wxEVT_RIGHT_DOWN) ||
01384         FALSE)
01385     {
01386         msg.DlgMsg = DIM_RGT_BN_DOWN;
01387         HandleMessage = TRUE;
01388     }   
01389     else if (
01390         (EventType == wxEVT_RIGHT_UP) ||
01391         FALSE)
01392     {
01393         msg.DlgMsg = DIM_RGT_BN_UP;
01394         HandleMessage = TRUE;
01395     }   
01396     else if (
01397         (EventType == wxEVT_MIDDLE_DOWN) ||
01398         FALSE)
01399     {
01400         msg.DlgMsg = DIM_MID_BN_DOWN;
01401         HandleMessage = TRUE;
01402     }   
01403     else if (
01404         (EventType == wxEVT_MIDDLE_UP) ||
01405         FALSE)
01406     {
01407         msg.DlgMsg = DIM_MID_BN_UP;
01408         HandleMessage = TRUE;
01409     }   
01410     else if (
01411         (EventType == wxEVT_MOTION) ||
01412         FALSE)
01413     {
01414         msg.DlgMsg = ((wxMouseEvent *)&event)->Dragging()?DIM_MOUSE_DRAG:DIM_MOUSE_MOVE;
01415         HandleMessage = TRUE;
01416     }   
01417     else if (
01418         (EventType == wxEVT_MOUSEWHEEL) ||
01419         FALSE)
01420     {
01421         msg.DlgMsg = (((wxMouseEvent *)&event)->GetWheelRotation()>0)?DIM_MOUSEWHEEL_UP:DIM_MOUSEWHEEL_DOWN;
01422         HandleMessage = TRUE;
01423     }   
01424     else if (
01425         (EventType == wxEVT_MOVE) ||
01426         FALSE)
01427     {
01428         msg.DlgMsg = DIM_DLG_MOVED;
01429         HandleMessage = TRUE;
01430     }   
01431     else if (
01432         (EventType == wxEVT_SIZE) ||
01433         FALSE)
01434     {
01435         if (event.GetEventObject() != pEvtHandler->pwxWindow)
01436         {
01437             Defer = FALSE;
01438             msg.DlgMsg = DIM_CTRL_RESIZED;
01439             HandleMessage = TRUE;   
01440         }
01441         else
01442         {
01443             msg.DlgMsg = DIM_DLG_RESIZED;
01444             HandleMessage = TRUE;
01445         }
01446     }
01447     else if (
01448         (EventType == wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED) &&
01449         pGadget && pGadget->IsKindOf(CLASSINFO(wxBookCtrlBase)))
01450     {
01451         msg.DlgMsg = DIM_SET_ACTIVE;
01452         wxWindow *pPage = ((wxBookCtrlBase*)pGadget)->GetCurrentPage();
01453         msg.PageID = pPage?(pPage->GetId()):0;
01454         HandleMessage = TRUE;
01455     }
01456     else if (
01457         ((EventType == wxEVT_CAMDIALOG_REDRAW) && (pGadget)) ||
01458         FALSE)
01459     {
01460         if (CCamApp::IsDisabled())
01461         {
01462             TRACE( _T("kernel-rendered gadget repaint has been aborted: the system is disabled (due to an error/ensure?)\n"));
01463             HandleMessage = FALSE;
01464         }
01465         else
01466         {
01467             // HDC hDC = pInfo->PaintInfo.hdc;
01468             // HPALETTE OldPalette = PaletteManager::StartPaintPalette(hDC);
01469         
01470             ReDrawInfoType ExtraInfo;
01471         
01472             ExtraInfo.pMousePos = NULL;     // No mouse position info for redraw events
01473 
01474 
01475             // Build a CC dc out of it for rendering to the screen
01476             // Get a MFC CDC to put the DC in
01477             CCPaintDC MyDc(pGadget);
01478 
01479             ExtraInfo.pDC = &MyDc;
01480         
01481             // The devices DPI
01482             ExtraInfo.Dpi = OSRenderRegion::GetFixedDCPPI(MyDc).GetHeight();
01483 
01484             // How big the window is
01485             wxSize WindowSize = pGadget->GetClientSize();
01486             ExtraInfo.dx = (((INT32)WindowSize.GetWidth())*72000) / ExtraInfo.Dpi;
01487             ExtraInfo.dy = (((INT32)WindowSize.GetHeight())*72000) / ExtraInfo.Dpi;
01488         
01489             MyDc.GetDC()->BeginDrawing();
01490 
01491             wxRegionIterator upd(pGadget->GetUpdateRegion()); // get the update rect list
01492 
01493             BOOL Stop = FALSE;
01494 
01495             while (upd && !Stop)
01496             {
01497                 // Alternatively we can do this:
01498                 wxRect ClipRect(upd.GetRect());
01499                 // Should we clip this to the WindowSize here? For reasons which are not entirely clear, setting the
01500                 // ClipRect breaks GRenderRegions. But if we don't set the clip rect, it breaks (at least some)
01501                 // code that uses OSRenderRegion (sigh). Right now this is too painful to debug, so instead we
01502                 // cop out, and ask the control whether or not it would like a ClipRect set. Those that say no
01503                 // will paint the entire area, so we only give them one call
01504 
01505                 BOOL UseClipRect = (pGadget->IsKindOf(CLASSINFO(wxCamDrawControl)))
01506                                     && (((wxCamDrawControl*)pGadget)->GetStyle() & wxCDCS_SETCLIPRECT);
01507 
01508                 if (UseClipRect)
01509                 {
01510                     MyDc.GetDC()->SetClippingRegion(ClipRect);
01511                     ClipRect.Inflate(1,1); // work around wxRect problems.
01512                 }
01513                 else
01514                 {
01515                     ClipRect = wxRect(WindowSize);
01516                     Stop = TRUE; // cease drawing after this one
01517                 }
01518                 
01519                 DocRect DocClipRect;
01520             
01521                 // Convert to millipoints, Also need to flip the y coords to get a
01522                 // rectangle in with the origin in the bottom left.
01523                 DocClipRect.lo.x = (ClipRect.GetLeft() * 72000) / ExtraInfo.Dpi;
01524                 DocClipRect.lo.y = ExtraInfo.dy - ((ClipRect.GetBottom() * 72000) / ExtraInfo.Dpi);
01525             
01526                 DocClipRect.hi.x = (ClipRect.GetRight() * 72000) / ExtraInfo.Dpi;
01527                 DocClipRect.hi.y = ExtraInfo.dy - ((ClipRect.GetTop() * 72000) / ExtraInfo.Dpi);
01528             
01529                 // Set the pointer in the extra info structure
01530                 ExtraInfo.pClipRect = &DocClipRect;
01531             
01532                 // Build the message and send it to the dialog op
01533                 // It is up to the dialog op to build a render region etc and attach the CCDC to it
01534                 // and to tidy the region up after it has finished drawing in it CDlgMessage
01535                 BROADCAST_TO_CLASS(DialogMsg(pEvtHandler->pwxWindow, DIM_REDRAW, id, (UINT_PTR)(void *)&ExtraInfo, PageID), DialogOp);
01536                 
01537                 upd ++ ;
01538             }
01539         
01540             MyDc.GetDC()->EndDrawing();     
01541         
01542             // if (OldPalette)
01543             //  PaletteManager::StopPaintPalette(hDC, OldPalette);
01544         }
01545     }
01546 
01547     //case  wxEVT_COMMAND_TOOL_RCLICKED:
01548     //case  wxEVT_COMMAND_TOOL_ENTER:
01549 
01550 
01551     // Handle filling in ExtraInfo on redraw events
01552     if ((msg.DlgMsg != DIM_NONE) && pGadget && pGadget->IsKindOf(CLASSINFO(wxCamDrawControl)) && event.IsKindOf(CLASSINFO(wxMouseEvent)))
01553     {
01554         switch (msg.DlgMsg)
01555         {
01556             case DIM_LFT_BN_DOWN:
01557             case DIM_LFT_BN_UP:
01558             case DIM_LFT_BN_CLICKED:
01559             case DIM_RGT_BN_DOWN:
01560             case DIM_RGT_BN_UP:
01561             case DIM_RGT_BN_CLICKED:
01562             case DIM_MID_BN_DOWN:
01563             case DIM_MID_BN_UP:
01564             case DIM_MID_BN_CLICKED:
01565             case DIM_MOUSE_DRAG:
01566             case DIM_MOUSE_MOVE:
01567             case DIM_MOUSEWHEEL_UP:
01568             case DIM_MOUSEWHEEL_DOWN:
01569             {
01570 
01571                 // HDC hDC = pInfo->PaintInfo.hdc;
01572                 // HPALETTE OldPalette = PaletteManager::StartPaintPalette(hDC);
01573             
01574                 ReDrawInfoType ExtraInfo;
01575             
01576                 ExtraInfo.pMousePos = NULL;     // No mouse position info for redraw events
01577         
01578         
01579                 // Build a CC dc out of it for rendering to the screen
01580                 // Get a MFC CDC to put the DC in
01581                 CCPaintDC MyDc(pGadget);
01582         
01583                 ExtraInfo.pDC = NULL;
01584             
01585                 // The devices DPI
01586                 ExtraInfo.Dpi = OSRenderRegion::GetFixedDCPPI(MyDc).GetHeight();
01587         
01588                 // How big the window is
01589                 wxSize WindowSize = pGadget->GetClientSize();
01590                 ExtraInfo.dx = (((INT32)WindowSize.GetWidth())*72000) / ExtraInfo.Dpi;
01591                 ExtraInfo.dy = (((INT32)WindowSize.GetHeight())*72000) / ExtraInfo.Dpi;
01592 
01593                 // Work out the MILLIPOINT coordinates of the mouse position
01594                 // Note that the Y value is flipped, as the kernel-origin is at the bottom left
01595                 INT32 XPos = ((wxMouseEvent *)(&event))->GetX();
01596                 INT32 YPos = ((wxMouseEvent *)(&event))->GetY();
01597     
01598                 DocCoord MousePos;
01599                 MousePos.x = (XPos * 72000) / ExtraInfo.Dpi;
01600                 MousePos.y = ExtraInfo.dy - ((YPos * 72000) / ExtraInfo.Dpi);
01601                 ExtraInfo.pMousePos = &MousePos;
01602 
01603                 BROADCAST_TO_CLASS(DialogMsg(pEvtHandler->pwxWindow, msg.DlgMsg, id, (UINT_PTR)(void *)&ExtraInfo, PageID), DialogOp);
01604 
01605                 msg.DlgMsg = DIM_NONE; // Stop further processing
01606             }
01607 
01608             default:
01609                 break;
01610         }
01611     }
01612 
01613 
01614     // If we have a message to send, then send it (or defer it for later)
01615     if (msg.DlgMsg != DIM_NONE)
01616     {
01617         // Restore focus after selection change etc. if the dialog Op is non-modal
01618         if (!(pEvtHandler->pDialogOp->IsModal()) && (( DIM_SELECTION_CHANGED == msg.DlgMsg ) || ( DIM_SLIDER_POS_SET == msg.DlgMsg )))
01619         {
01620             TRACEUSER( "luke", _T("Change focus") );
01621             AfxGetApp().GiveActiveCanvasFocus();
01622         }
01623 
01624         if (Defer)
01625         {
01626             // We should send the message out later - we use the same ID
01627             wxCamDialogEvent deferredevent (wxEVT_CAMDIALOG_DEFERREDMSG, event.GetId(), msg);
01628             deferredevent.SetEventObject(pEvtHandler->pwxWindow);
01629             // set it for processing later
01630             pEvtHandler->pwxWindow->GetEventHandler()->AddPendingEvent(deferredevent);
01631         }
01632         else
01633         {
01634             BROADCAST_TO_CLASS( DialogMsg(msg), DialogOp );
01635         }
01636     }
01637     
01638     // If we haven't marked this message as handled, call Skip() so that others can handle
01639     // it
01640     if (!HandleMessage) event.Skip(); // we didn't handle it
01641     return;
01642 }
01643 
01644 
01645 
01646 /********************************************************************************************
01647 
01648 >   wxBookCtrlBase * DialogManager::GetBookControl(CWindowID WindowID, CGadgetID Gadget =0)
01649 
01650     Author:     Alex Bligh <alex@alex.org.uk>
01651     Created:    11/05/2006
01652     Inputs:     WindowID - Dialog box window identifier
01653                 Gadget - Identifier of the gadget OR zero
01654     Returns     pointer to the book control or NULL
01655     Purpose:    This function will return a pointer to the book control in a window.
01656                 If the window is of type wxPropertySheetDialog then it Gadget is not
01657                 required
01658 
01659 Note that the intelligence to use the default gadget won't be there until the window
01660 has been created properly and the event handler added. So if this is being called
01661 from a window creation function (like AddAPage) it is worth specifying the gadget
01662 explicitly.
01663 
01664 ********************************************************************************************/
01665 
01666 wxBookCtrlBase * DialogManager::GetBookControl(CWindowID WindowID, CGadgetID Gadget /* =0 */)
01667 {
01668     // No window ID? Well no book control then
01669     if (!WindowID) return NULL;
01670 
01671     // If it's a property sheet dialog then we know a quick way...
01672     if (WindowID->IsKindOf(CLASSINFO(wxPropertySheetDialog)))
01673         return ((wxPropertySheetDialog*)WindowID)->GetBookCtrl();
01674 
01675     // Let's see if there is a default gadget to use in the DialogOp
01676     if (!Gadget)
01677     {
01678         if ((WindowID->GetEventHandler())->IsKindOf(CLASSINFO(DialogEventHandler)))
01679         {
01680             DialogOp * pDialogOp = ((DialogEventHandler *)(WindowID->GetEventHandler()))->pDialogOp;
01681             // If it's a DialogTabOp, ask it for its default book gadget. If there isn't
01682             // one, that's OK too
01683             if ((pDialogOp) && (pDialogOp->IS_KIND_OF(DialogTabOp)))
01684                 Gadget=((DialogTabOp*)pDialogOp)->GetDefaultBookGadget();
01685         }
01686     }
01687 
01688     // If we were passed a gadget ID, we can go use it
01689     if (Gadget)
01690     {
01691         wxWindow * pGadget = GetGadget(WindowID, Gadget);
01692         if (pGadget->IsKindOf(CLASSINFO(wxBookCtrlBase)))
01693             return (wxBookCtrlBase*)pGadget;
01694         else
01695             return NULL;
01696     }
01697 
01698     // See if any of the children are wxBookCtrlBase
01699     wxWindowList::Node * pNode = WindowID->GetChildren().GetFirst();
01700     while (pNode)
01701     {
01702         wxWindow * child = pNode->GetData();
01703         if (child->IsKindOf(CLASSINFO(wxBookCtrlBase)))
01704             return (wxBookCtrlBase*)child;
01705         pNode = pNode->GetNext();
01706     }
01707 
01708     // OK, they aren't. Recurse through them
01709     pNode = WindowID->GetChildren().GetFirst();
01710     while (pNode)
01711     {
01712         wxBookCtrlBase * pBook=GetBookControl(WindowID, 0);
01713         if (pBook)
01714             return pBook;
01715         pNode = pNode->GetNext();
01716     }
01717 
01718     return NULL;
01719 }
01720 
01721 
01722 
01723 
01724 /********************************************************************************************
01725 
01726 >   static BOOL DialogManager::IsGadgetTickable(CWindowID WindowID,
01727                                                 CGadgetID Gadget)
01728 
01729 
01730     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01731     Created:    28/6/95
01732     Inputs:     WindowID: Dialog's window identifier
01733                 Gadget:   The Gadget to test
01734 
01735     Purpose:    Determines if the gadget is of a type that can be ticked
01736 
01737 ********************************************************************************************/
01738 
01739 BOOL DialogManager::IsGadgetTickable(CWindowID WindowID,
01740                                     CGadgetID Gadget)
01741 {
01742     wxWindow * pGadget = GetGadget(WindowID, Gadget);
01743     if (!pGadget) return FALSE;
01744 
01745     // Not sure why this is an exhaustive list
01746     return ( pGadget->IsKindOf(CLASSINFO(wxCheckBox)) ||
01747             pGadget->IsKindOf(CLASSINFO(wxButton)) ||
01748             (pGadget->IsKindOf(CLASSINFO(wxCamArtControl)) && (((wxCamArtControl*)pGadget)->GetStyle() & wxCACS_PUSHBUTTON)) ||
01749             pGadget->IsKindOf(CLASSINFO(wxBitmapButton))
01750             );
01751 }
01752 
01753 
01754 /********************************************************************************************
01755 
01756 >   static BOOL DialogManager::ColourPickerAbort(CWindowID WindowID, CGadgetID Gadget)
01757 
01758     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
01759     Created:    27/1/2000
01760     Inputs:     WindowID:   Dialog's window identifier
01761                 Gadget:     The colourpicker that this request is made upon (which is checked
01762                             to ensure that it is a custom colour picker).
01763 
01764     Purpose:    Instructs camelots custom colour control (which I also wrote) to 'shutdown'
01765                 and (indirectly) return control to the colour editor dialog.
01766 
01767 ********************************************************************************************/
01768 
01769 BOOL DialogManager::ColourPickerAbort(CWindowID WindowID, CGadgetID Gadget, WPARAM wParam)
01770 {
01771     PORTNOTETRACE("dialog","DialogManager::ColourPickerAbort - do nothing");
01772 #ifndef EXCLUDE_FROM_XARALX
01773     // Currently the gadget is only tickable if it is a button
01774     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
01775     String_256 ClassNameStr;  // The control type
01776 
01777     // Find out the class type of the gadget
01778     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
01779 
01780     if (ClassNameStr == String_8(TEXT("cc_colPicker")))
01781     {
01782         BOOL RetVal = FALSE;
01783 
01784         RetVal = SendMessage(hGadget, WM_COLOURPICKERABORT, wParam, 0);
01785 
01786         return (RetVal);
01787     }
01788 
01789     return (TRUE);
01790     ENSURE(FALSE, "Calling ColourPickerAbort for an invalid control");
01791 #endif
01792     return FALSE;
01793 }
01794 
01795 
01796 /********************************************************************************************
01797 
01798 >   DialogManager::Delete(CWindowID WindowID, DialogOp* pDlgOp)
01799 
01800     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
01801     Created:    17/8/93
01802     Inputs:     WindowID: Dialog's window identifier
01803                 pDlgOp:   The DialogOp
01804     Purpose:    The delete method will delete all system resources and other information
01805                 which is kept about the dialog. It also records the dialogs current position
01806                 so that it can be restored the next time the dialog is created.
01807     SeeAlso:    DialogOp::Delete
01808 
01809 ********************************************************************************************/
01810 
01811 void DialogManager::Delete(CWindowID WindowID, DialogOp* pDlgOp)
01812 {
01813     ERROR2IF (!pDlgOp, (void)0, "No dialog op to DialogManager::Delete()");
01814     ERROR2IF (!WindowID, (void)0, "No window to DialogManager::Delete()");
01815 
01816     if (!pDlgOp->pEvtHandler)
01817     {
01818         ERROR3("DialogManager::Delete() No dialog op event handler - has this window been deleted twice?");
01819         return;
01820     }
01821 
01822     // If we've already been destroyed (by something else) - a situation which should never happen - then
01823     // return without doing anything
01824     if (pDlgOp->pEvtHandler && pDlgOp->pEvtHandler->m_GrimReaperSent)
01825     {
01826         TRACEALL(_T("DialogManager::Delete() Window has been deleted by something else, then Delete() called"));
01827         return;
01828     }
01829 
01830     if (((wxWindow *)WindowID)->IsBeingDeleted())
01831     {
01832         ERROR3("Trying to delete a window that is already being deleted, has an event handler, but has not sent grim reaper");
01833         return;
01834     }
01835 
01836     wxBookCtrlBase * pBook=NULL;
01837     // Only do special processing for DialogTabOp
01838     if (pDlgOp->IS_KIND_OF(DialogTabOp))
01839         pBook=GetBookControl(WindowID);
01840 //  ResourceID BookGadget=pBook?pBook->GetId():0;
01841 
01842     // See if the dialogs has a position record  (If it's a DialogBarOp it won't have one)
01843     DialogPosition* DlgPos = (DialogPosition*)DialogPositionList.GetHead();
01844     CWindowIDItem* WinID;
01845     while(DlgPos != NULL)
01846     {
01847         // Search the DlgWinList for the DlgPos for WindowID
01848         WinID = (CWindowIDItem*)DlgPos->DlgWinList.GetHead();
01849         while (WinID != NULL)
01850         {
01851             if ((WinID->DlgWin) == WindowID) // Found the dialogs position record
01852             {
01853                 // The Dialogs window is about to be destroyed so delete the WinID from the
01854                 // DlgWinList of DlgPos.
01855                 delete(DlgPos->DlgWinList.RemoveItem((ListItem*)WinID));
01856                 goto FoundPos; // What a rebel
01857             }
01858             WinID = (CWindowIDItem*)DlgPos->DlgWinList.GetNext((ListItem*)WinID);
01859         }
01860         // Get the next position record
01861         DlgPos = ((DialogPosition*)DialogPositionList.GetNext((ListItem*)DlgPos));
01862     }
01863     // No DialogPosition record was found so must be a DialogBarOp
01864 
01865 
01866     FoundPos:
01867 
01868     wxWindow           *pCWnd = (wxWindow *)WindowID;
01869 
01870 
01871     if (DlgPos != NULL)
01872     {
01873         // Record the dialog's position so that it can be restored if the dialog is created again
01874         wxRect          DialogRect( pCWnd->GetRect() );
01875         DlgPos->LastX = DialogRect.x;
01876         DlgPos->LastY = DialogRect.y;
01877         DlgPos->ActivePage = 0;
01878         DlgPos->ActivePageIndex = 0;
01879 
01880         // If the dialog is tabbed then we need to record the active page as well
01881         // We can't find the runtime class of the DialogOp at this point because Delete can be called
01882         // from its destructor
01883         if (pBook)
01884         {
01885             wxNotebookPage* pPage = pBook->GetCurrentPage();
01886             if (pPage)
01887             {
01888                 DlgPos->ActivePage = pPage->GetId();
01889                 // Store the pages index as well
01890                 GetPageWindow(WindowID, DlgPos->ActivePage, &(DlgPos->ActivePageIndex));
01891             }
01892             else
01893                 ERROR3("There is no active page");
01894         }
01895     }
01896 
01897     if (pDlgOp->pEvtHandler->wxAUImanaged)
01898     {
01899         wxAuiPaneInfo paneinfo = CCamFrame::GetMainFrame()->GetFrameManager()->GetPane(pCWnd);
01900         if (paneinfo.IsOk())
01901             SavePaneInfo(wxString(CamResource::GetObjectName(pCWnd->GetId())), paneinfo);
01902         // Remove the bar from wxAUI
01903         CCamFrame::GetMainFrame()->GetFrameManager()->DetachPane(pCWnd);
01904         CCamFrame::GetMainFrame()->UpdateFrameManager();
01905     }
01906 
01907     // Delete all discardable strings associated with the dialog
01908     DlgDiscardString* DiscardStr = (DlgDiscardString*)(DiscardStrList.GetHead());
01909     while (DiscardStr != NULL) // While there are still strings to delete
01910     {
01911         DlgDiscardString* Next = (DlgDiscardString*)(DiscardStrList.GetNext(DiscardStr));
01912         if (DiscardStr->DlgWindow == WindowID)  // The string belongs to the dialog being
01913                                                 // deleted
01914         {
01915             delete (DiscardStr->pStr); // Delete the string
01916             delete(DiscardStrList.RemoveItem(DiscardStr)); // Delete the DiscardStr record
01917         }
01918         DiscardStr = Next;  // Get next string record
01919     }
01920 
01921     // Delete all scrollPageInc information associated with the dialog
01922     ScrollPageInc* PgInc = (ScrollPageInc*)(ScrollPageIncList.GetHead());
01923     while (PgInc != NULL)
01924     {
01925         ScrollPageInc* Next = (ScrollPageInc*)(ScrollPageIncList.GetNext((ListItem*)PgInc));
01926         if( PgInc->pDlgWindow == WindowID ) // The ScrollPageInc record belongs to the dialog
01927                                             // being deleted.
01928             delete (ScrollPageIncList.RemoveItem( (ListItem*)PgInc) );  // Delete the
01929                                                                         // ScrollPageInc record
01930         PgInc = Next; // Get next record
01931     }
01932 
01933     // Delete all ControlInfo records
01934     List* ControlInfoList = GetControlList( (wxWindow *)WindowID );
01935 
01936     // Kill of Dropdowns
01937     DropDown::KillDropDownsByWindow(WindowID);
01938     CGridDropDown::KillDropDownsByWindow(WindowID);
01939 
01940     // Remove new-form control list
01941     ControlList::Get()->RemoveWindowAndChildren((wxWindow *)WindowID);
01942 
01943     // We are about to destroy the window. Disconnecting our event handler sounds like a good
01944     // idea at this point, as Destroy() does not destroy the window immediately, so there
01945     // is a possibility of receiving further events
01946     ((wxWindow *)WindowID)->PopEventHandler(FALSE); // leave the DialogOp's destructor to delete it
01947     pDlgOp->pEvtHandler->Destroy();
01948 
01949 
01950     if (pDlgOp->IsModal() && WindowID->IsKindOf(CLASSINFO(wxDialog)))
01951     // A normal Modal
01952     {
01953         ( (wxDialog *)WindowID )->EndModal( TRUE );
01954         ( (wxWindow *)WindowID )->Destroy();
01955     }
01956     else
01957     {
01958         ( (wxWindow *)WindowID )->Destroy();
01959     }
01960 
01961     if (ControlInfoList)
01962     {
01963         // Its one of our special windows with an attached list
01964 
01965         while (!ControlInfoList->IsEmpty())
01966             delete(ControlInfoList->RemoveHead());
01967         // Delete the ControlInfo list
01968         delete (ControlInfoList);
01969         ControlInfoList = NULL;
01970     }
01971 
01972     // Restore the active/disabled window state
01973     if (pDlgOp->IsModal())
01974     {
01975         // DialogManager::RestoreActiveDialogState();
01976     }
01977 
01978     DefaultKeyboardFocus();
01979     // All spick and span
01980 }
01981 
01982 
01983 
01984 /********************************************************************************************
01985 
01986 >   BOOL DialogManager::SetComboListLength( CWindowID WindowID,
01987                                             CGadgetID Gadget)
01988 
01989     Author:     Chris_Parks (Xara Group Ltd) <camelotdev@xara.com>
01990     Created:    17/7/94
01991     Inputs:     WindowID:    Dialog box window identifier
01992                 Gadget:      Identifier of the gadget
01993     Returns:    -
01994     Purpose:
01995 
01996     Errors:     If the function is called on an invalid control then an ENSURE failure will
01997                 occur in a DEBUG build.
01998 
01999     SeeAlso:    DialogOp::SetComboListLength
02000 
02001 ********************************************************************************************/
02002 
02003 void DialogManager::SetComboListLength(CWindowID WindowID,CGadgetID Gadget)
02004 {
02005     // This function existed to resize the combo box, but under wx combo boxes resize
02006     // automagically when their contents are adjusted.
02007     return;
02008 }
02009 
02010 // -----------------------------------------------------------------------------------------
02011 // The following functions are called by same named functions in the DialogOp
02012 // class. The DialogOp functions are provided for ease of use and do not have a
02013 // CWindowID argument.
02014 
02015 
02016 
02017 
02018 /********************************************************************************************
02019 
02020 >   void DialogManager::SetGadgetBitmaps(CWindowID WindowID, CGadgetID Gadget,
02021                                         UINT32 Bitmap1, UINT32 Bitmap2)
02022 
02023     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
02024     Created:    26/10/94
02025     Inputs:     WindowID - Dialog box window identifier
02026                 Gadget - Identifier of the gadget
02027                 Bitmap1 - The resourse ID of the first bitmap
02028                 Bitmap2 - The resourse ID of the second bitmap
02029     Purpose:    This function will set the bitmaps associated with a gadget.
02030 
02031                 This will only work for cc_Slider and cc_BitmapButton controls
02032 
02033                 cc_Slider:
02034                 In this case Bitmap1 is used as the Base of the slider and Bitmap2 is used
02035                 as the little slideing bar.  (Drop the 'e' before 'ing' Rik)
02036 
02037                 cc_BitmapButton:
02038                 Bitmap1 & Bitmap2 are ignored. Instead, the bitmaps are specified by the window
02039                 title text, in the same way as bitmap buttons in bars. (added by Markn 27/3/95)
02040 
02041 ********************************************************************************************/
02042 
02043 void DialogManager::SetGadgetBitmaps(CWindowID WindowID, CGadgetID Gadget, UINT32 Bitmap1, UINT32 Bitmap2)
02044 {
02045     PORTNOTETRACE("dialog","DialogManager::SetGadgetBitmaps - do nothing");
02046 #ifndef EXCLUDE_FROM_XARALX
02047     // Find out about the Gadget
02048     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
02049 
02050     // Find out the class type of the gadget
02051     String_256 ClassNameStr;
02052     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
02053 
02054     // Only do something if it is a slider
02055     if ((ClassNameStr == String_16(TEXT("cc_Slider"))))
02056     {
02057         // Fill in the details of the bitmaps
02058         SliderBitmapInfo BitmapInfo;
02059         BitmapInfo.hAppInstance = AfxGetResourceHandle(); //AfxGetApp()->m_hInstance;
02060         BitmapInfo.BaseBmpStr = MAKEINTRESOURCE(Bitmap1);
02061         BitmapInfo.SliderBmpStr = MAKEINTRESOURCE(Bitmap2);
02062 
02063         // Send a message to the slider, telling to use the bitmaps
02064         SendMessage(hGadget, WM_SET_CHANNEL_WIDTH, 8, 0);
02065         SendMessage(hGadget, WM_SET_SLIDERBITMAPS, 0, (INT32)&BitmapInfo);
02066 
02067     }
02068 
02069     // Send new style messages to the button classes because they can use PNG
02070     // resources
02071     if (ClassNameStr == String_16(TEXT("cc_BitmapButton"))
02072         || ClassNameStr == String_16(TEXT("cc_SmallBitmapButton")) )
02073     {
02074         SetGadgetBitmaps(hGadget, AfxGetResourceHandle());
02075     }
02076 #endif
02077 }
02078 
02079 /********************************************************************************************
02080 
02081 >   void DialogManager::SetGadgetBitmap(CWindowID WindowID, CGadgetID Gadget,
02082                                         ResourceID Bitmap)
02083 
02084     Author:     Alex Bligh <alex@alex.org.uk>
02085     Created:    07/05/2006
02086     Inputs:     WindowID - Dialog box window identifier
02087                 Gadget - Identifier of the gadget
02088                 Bitmap - The resourse ID of the bitmap, or 0 for default;
02089     Purpose:    This function will set the bitmaps associated with a gadget.
02090 
02091                 This works only for bitmap buttons
02092 
02093 ********************************************************************************************/
02094 
02095 void DialogManager::SetGadgetBitmap(CWindowID WindowID, CGadgetID Gadget, ResourceID Bitmap)
02096 {
02097     wxWindow* pGadget = GetGadget(WindowID, Gadget);
02098     if (!pGadget) return;
02099 
02100     if ( pGadget->IsKindOf(CLASSINFO(wxCamArtControl))
02101         )
02102     {
02103         ((wxCamArtControl *)pGadget)->SetBitmapId(Bitmap);
02104         pGadget->Refresh();
02105     }
02106 }
02107 
02108 /********************************************************************************************
02109 
02110 >   ResourceID DialogManager::SetGadgetBitmap(CWindowID WindowID, CGadgetID Gadget)
02111 
02112     Author:     Alex Bligh <alex@alex.org.uk>
02113     Created:    07/05/2006
02114     Inputs:     WindowID - Dialog box window identifier
02115                 Gadget - Identifier of the gadget
02116     Returns:    The resourse ID of the bitmap
02117     Purpose:    This function will get the bitmaps associated with a gadget.
02118 
02119 ********************************************************************************************/
02120 
02121 ResourceID DialogManager::GetGadgetBitmap(CWindowID WindowID, CGadgetID Gadget)
02122 {
02123     wxWindow* pGadget = GetGadget(WindowID, Gadget);
02124     if (!pGadget) return 0;
02125 
02126     if ( pGadget->IsKindOf(CLASSINFO(wxCamArtControl))
02127         )
02128     {
02129         return ((wxCamArtControl *)pGadget)->GetBitmapId();
02130     }
02131     return 0;
02132 }
02133 
02134 /********************************************************************************************
02135 
02136 >   void DialogManager::SetGadgetBitmaps(CWindowID WindowID, CGadgetID Gadget,
02137                                         const CGadgetImageList& imagelist)
02138 
02139     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
02140     Created:    08/Feb/2006
02141     Inputs:     WindowID - Dialog box window identifier
02142                 Gadget - Identifier of the gadget
02143                 imagelist - the list of images
02144     Purpose:    This function will set the bitmaps associated with a gadget.
02145 
02146 ********************************************************************************************/
02147 
02148 void DialogManager::SetGadgetBitmaps(CWindowID WindowID, CGadgetID Gadget, const CGadgetImageList& imagelist)
02149 {
02150     wxWindow* pGadget = GetGadget(WindowID, Gadget);
02151     if (!pGadget) return;
02152 
02153     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
02154         )
02155     {
02156         wxImageList* plist = new wxImageList(imagelist.GetWidth(), imagelist.GetHeight());
02157 
02158         CamArtProvider* pCAP = CamArtProvider::Get();
02159         ERROR3IF(pCAP==NULL, "Can't find CamArtProvider!");
02160 
02161         ListItem* pItem = NULL;
02162         ResourceID resID=0;
02163         pItem = imagelist.FindFirstBitmap(&resID);
02164         while (pItem)
02165         {
02166             wxBitmap* pBitmap = pCAP->FindBitmap(resID);
02167             plist->Add((const wxBitmap&) *pBitmap);
02168 
02169             pItem = imagelist.FindNextBitmap(pItem, &resID);
02170         }
02171         
02172         ((wxTreeCtrl*)pGadget)->AssignImageList(plist);     // Tree control takes ownership of the list
02173 
02174         return;
02175     }
02176 
02177     ERROR3("SetTreeGadgetItem called on non-tree gadget");
02178     return;
02179 }
02180 
02181 
02182 /********************************************************************************************
02183 
02184 >   void DialogManager::SetBitmapButtonIndexes(CWindowID WindowID, CGadgetID Gadget,
02185                                         UINT32 SelectedIndex, UINT32 UnselectedIndex)
02186 
02187     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
02188     Created:    23/9/99
02189     Inputs:     WindowID - Dialog box window identifier
02190                 Gadget - Identifier of the gadget
02191                 SelectedIndex - The index number into the bitmap strip for the glyph
02192                                 representing the buttons selected state
02193                 UnselectedIndex - The index number into the bitmap strip for
02194                                 the unselected glyph
02195     Purpose:    This function allows you to specify bitmaps for both the
02196                 selected and unselected states of a bitmap button. Most likely you have
02197                 already selected your bitmap for the selected state in your
02198                 resource file, however this allows you to specify the unselected state also.
02199 
02200 
02201 
02202 ********************************************************************************************/
02203 
02204 void DialogManager::SetBitmapButtonIndexes(CWindowID WindowID, CGadgetID Gadget,
02205                                     UINT32 UnselectedIndex, UINT32 SelectedIndex)
02206 
02207 {
02208     PORTNOTETRACE("dialog","DialogManager::SetBitmapButtonIndexes - do nothing");
02209 #ifndef EXCLUDE_FROM_XARALX
02210     // Find out about the Gadget
02211     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
02212 
02213     // Find out the class type of the gadget
02214     String_256 ClassNameStr;
02215     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
02216 
02217 
02218     // Send new style messages to the button classes because they can use PNG
02219     // resources
02220     if (ClassNameStr == String_16(TEXT("cc_BitmapButton"))
02221         || ClassNameStr == String_16(TEXT("cc_SmallBitmapButton")) )
02222     {
02223         SetGadgetBitmaps(hGadget, AfxGetResourceHandle(), SelectedIndex, UnselectedIndex);
02224     }
02225 #endif
02226 }
02227 
02228 /********************************************************************************************
02229 
02230 >   void DialogManager::SetGadgetBitmaps( HWND hGadget,
02231                                         HINSTANCE hResInstance,
02232                                         INT32 SelectedIndex = -1,
02233                                         INT32 UnselectedIndex = -1 )
02234 
02235     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
02236     Created:    05/03/2004
02237     Inputs:     HWND - window handle of gadget
02238                 HINSTANCE - Resource module handle
02239                 INT32 - index of selected item or -1 to derive from gadget title string
02240                 INT32 - index of unselected itemor -1 to derive from gadget title string
02241     Outputs:    -
02242     Returns:    -
02243     Purpose:    Send custom WM_SETBITMAPEX message to custom controls
02244     Errors:     -
02245     SeeAlso:    DialogManager::SetGadgetBitmaps, DialogManager::SetBitmapButtonIndexes
02246 
02247 ********************************************************************************************/
02248 /*void DialogManager::SetGadgetBitmaps( wxWindow *pGadget,
02249                                     // HINSTANCE hResInstance, //
02250                                     INT32 SelectedIndex,
02251                                     INT32 UnselectedIndex)
02252 {
02253     PORTNOTETRACE("dialog","DialogManager::SetGadgetBitmaps - do nothing");
02254 #ifndef EXCLUDE_FROM_XARALX
02255     char AnsiTitle[256];
02256     GetWindowText(hGadget,AnsiTitle,255);
02257     BitmapButtonInfoEx BtnInfo;
02258 
02259     // find the position of the specifier's separator
02260     INT32 SeparatorPos = 0;
02261     while (AnsiTitle[SeparatorPos] != 0 && AnsiTitle[SeparatorPos] != '.')
02262         SeparatorPos++;
02263 
02264     INT32 Index = 0;        // Default to using icon index 0 if no '.' separator was found
02265     if (AnsiTitle[SeparatorPos] == '.')
02266     {
02267         // We found a separator. In that case, truncate the resource string at the '.'
02268         // so we can extract the bitmap name, and convert the text after the '.' into
02269         // an integer index.
02270         Index = _ttoi( AnsiTitle + SeparatorPos+1 );
02271         AnsiTitle[SeparatorPos] = 0;
02272     }
02273 
02274     if (SelectedIndex=-1) SelectedIndex = Index;
02275     if (UnselectedIndex=-1) UnselectedIndex = Index;
02276 
02277     // Fill in the BtnInfo structure
02278     BtnInfo.hAppInstance = hResInstance;
02279 
02280     String_256 Title =("L");
02281     Title += TEXT(AnsiTitle);
02282 
02283     String_256 Ansi32Title = AnsiTitle;
02284     Ansi32Title += ("32");
02285 
02286     String_256 Title32 = ("L");
02287     Title32 += TEXT(Ansi32Title);
02288 
02289     BtnInfo.Bitmap[BBX_BMP_LARGE_UNSELECTED] = (LPTSTR)Title;
02290     BtnInfo.Bitmap[BBX_BMP_SMALL_UNSELECTED] = (LPTSTR)AnsiTitle;
02291 
02292     BtnInfo.Bitmap[BBX_BMP_SMALL_SELECTED] = NULL;  // NULL, or name of selected bitmap
02293     BtnInfo.Bitmap[BBX_BMP_LARGE_SELECTED] = NULL;  // NULL, or name of selected bitmap
02294 
02295     BtnInfo.Bitmap[BBX_BMP32_LARGE_UNSELECTED] = (LPTSTR)Title32;
02296     BtnInfo.Bitmap[BBX_BMP32_SMALL_UNSELECTED] = (LPTSTR)Ansi32Title;
02297 
02298     String_256 HTitle32 = ("H");                    // "H" for highlighted = selected
02299     HTitle32 += Title32;
02300     String_256 HATitle32 = ("H");
02301     HATitle32 += Ansi32Title;
02302 
02303     BtnInfo.Bitmap[BBX_BMP32_LARGE_SELECTED] = (LPTSTR)HTitle32;
02304     BtnInfo.Bitmap[BBX_BMP32_SMALL_SELECTED] = (LPTSTR)HATitle32;
02305 
02306     BtnInfo.UnselectedIndex = UnselectedIndex;      //  Indices of glyph bitmaps within the
02307     BtnInfo.SelectedIndex = SelectedIndex;          //  Unselected/Selected bitmaps
02308 
02309     ::SendMessage(hGadget, WM_SETBITMAPEX, 0, ((LPARAM) &BtnInfo));
02310 #endif
02311 }
02312 */
02313 
02314 
02315 /********************************************************************************************
02316 
02317 >   BOOL DialogManager::SetUnitGadgetValue( CWindowID WindowID,
02318                                             CGadgetID Gadget,
02319                                             UnitType DlgUnitType,
02320                                             MILLIPOINT Value,
02321                                             BOOL EndOfList = TRUE,
02322                                             INT32 ListPos = 0)
02323 
02324     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02325     Created:    17/8/93
02326     Inputs:     WindowID:    Dialog box window identifier
02327                 Gadget:      Identifier of the gadget
02328                 DlgUnitType: The type of the gadget value (cm, mm, pt, etc.)
02329                 Value:       The value to set the gadget to in MILLIPOINTS
02330 
02331                 The following inputs only need to be provided if the gadget has multiple
02332                 values, for example a ListBox.
02333 
02334                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02335                             value list. (Default = TRUE)
02336                             FALSE if the value is to be added to the ListPos position in the
02337                             list.
02338 
02339                 ListPos:     If EndOfList = FALSE then this input specifies the position
02340                             in the list (Default = 0, so if you want to add the value to
02341                             the top of the list simply specify EndOfList = FALSE)
02342 
02343                             If the gadget is a ComboBox then setting ListPos = -1 will
02344                             set the combo box's edit gadget field.
02345 
02346     Outputs:    -
02347     Returns:    TRUE if the gadgets value could be set as specified
02348                 FALSE if it could not.
02349 
02350     Purpose:    This method is used to set a gadget which should hold a number to a certain
02351                 value. The actual type of the gadget does not matter.
02352 
02353                 For example:
02354 
02355                 If gadget g1 is a string then
02356 
02357                 SetGadgetValue(g1win, g1, pt, 100000) will set g1's value to '100pt'
02358 
02359                 If g1 is an integer field then the function would set the gadgets value
02360                 to 100.
02361 
02362                 For Windows
02363                 -----------
02364 
02365                 The function can be used to set the string values of the following controls. The
02366                 string will have a unit suffix.
02367 
02368                 Edit
02369                 Static
02370                 Button
02371                 ListBox
02372                 ComboBox
02373 
02374     Errors:     If the function is called on an invalid control then an ENSURE failure will
02375                 occur in a DEBUG build. In a retail build FALSE is returned.
02376 
02377     SeeAlso:    DialogOp::SetUnitGadgetValue
02378 
02379 ********************************************************************************************/
02380 
02381 BOOL DialogManager::SetUnitGadgetValue( CWindowID WindowID,
02382                                     CGadgetID Gadget,
02383                                     UnitType Unit,
02384                                     MILLIPOINT Value,
02385                                     BOOL EndOfList,
02386                                     INT32 ListPos)
02387 {
02388     // Convert the unit value into a string
02389     String_256      StrValue;
02390 //  Convert::MillipointsToString(Value, Unit, 3, &StrValue);
02391     Convert::MillipointsToString( Value, Unit, &StrValue ); // Display using defaults
02392     return( SetStringGadgetValue( WindowID, Gadget, StrValue, EndOfList, ListPos ) );
02393 }
02394 
02395 
02396 /********************************************************************************************
02397 >   BOOL DialogManager::SetDimensionUnitGadgetValue(CWindowID WindowID,
02398                                                     CGadgetID Gadget,
02399                                                     UnitType  units,
02400                                                     double    Value,
02401                                                     Node*     pNode,
02402                                                     BOOL      IncludeUnitSpecifier = TRUE,
02403                                                     BOOL      EndOfList = TRUE,
02404                                                     INT32       ListPos = 0)
02405 
02406     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
02407     Created:    13/10/95
02408     Inputs:     WindowID:    Dialog box window identifier
02409                 Gadget:      Identifier of the gadget
02410                 units:       unit type
02411                 Value:       The value to set the gadget to in MILLIPOINTS
02412                 pNode:       Ptr to the node from whence Value came from
02413                 IncludeUnitSpecifier :  If TRUE the unit specifier is included
02414                                         e.g. "1.27 cm" or "1.27" for TRUE or FALSE respectively
02415 
02416                 The following inputs only need to be provided if the gadget has multiple
02417                 values, for example a ListBox.
02418 
02419                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02420                             value list. (Default = TRUE)
02421                             FALSE if the value is to be added to the ListPos position in the
02422                             list.
02423 
02424                 ListPos:     If EndOfList = FALSE then this input specifies the position
02425                             in the list (Default = 0, so if you want to add the value to
02426                             the top of the list simply specify EndOfList = FALSE)
02427 
02428                             If the gadget is a ComboBox then setting ListPos = -1 will
02429                             set the combo box's edit gadget field.
02430 
02431     Returns:    FALSE if fails
02432 
02433     Purpose:    as SetDimensionGadgetValue() but you can specify the units in which it is displayed
02434 ********************************************************************************************/
02435 
02436 BOOL DialogManager::SetDimensionUnitGadgetValue(CWindowID WindowID,
02437                                                 CGadgetID Gadget,
02438                                                 UnitType  units,
02439                                                 double    Value,
02440                                                 Node*     pNode,
02441                                                 BOOL      IncludeUnitSpecifier,
02442                                                 BOOL      EndOfList,
02443                                                 INT32       ListPos)
02444 {
02445     DimScale* pDimScale = DimScale::GetPtrDimScale(pNode);
02446     ERROR2IF(pDimScale==NULL,FALSE,"DialogManager::SetDimensionUnitGadgetValue() - pDimScale==NULL");
02447 
02448     String_256 Str;
02449     BOOL ok = pDimScale->ConvertToUnits(Value,&Str,IncludeUnitSpecifier,-1,units);
02450     if (ok) ok = SetStringGadgetValue(WindowID,Gadget,Str,EndOfList,ListPos);
02451 
02452     return ok;
02453 }
02454 
02455 
02456 /********************************************************************************************
02457 
02458 >   BOOL DialogManager::SetLongGadgetValue(CWindowID WindowID,
02459                                         CGadgetID Gadget,
02460                                         INT32 Value,
02461                                         BOOL EndOfList = TRUE,
02462                                         INT32 ListPos = 0)
02463 
02464     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02465     Created:    1/9/93
02466     Inputs:     WindowID: Dialog box window identifier
02467                 Gadget: Identifier of the gadget
02468                 Value:    INT32 value
02469 
02470                 The following inputs only need to be provided if the gadget has multiple
02471                 values, for example a ListBox.
02472 
02473                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02474                             value list. (Default = TRUE)
02475                             FALSE if the value is to be added to the ListPos position in the
02476                             list.
02477                 ListPos:     If EndOfList = FALSE then this input specifies the position
02478                             in the list (Default = 0, so if you want to add the value to
02479                             the top of the list simply specify EndOfList = FALSE)
02480 
02481                             If the gadget is a ComboBox then setting ListPos = -1 will
02482                             set the combo box's edit gadget field.
02483 
02484 
02485 
02486     Outputs:    -
02487     Returns:    TRUE if the gadgets value could be set
02488                 FALSE if it could not
02489 
02490     Purpose:    This function is used to set a numeric gadget value. It performs
02491                 different functions depending on the type of the gadget.
02492 
02493                 For Windows
02494                 -----------
02495 
02496                 If the gadget is a button it sets the button's current state.
02497 
02498                     For check and radio buttons it sets the state to either checked
02499                     (Value = 1) or unchecked (Value = 0). In the case of a 3 state button
02500                     the third state can be specified by a (Value = 2).
02501 
02502                     For Push buttons it can be used to set a depressed (Value = 1)/
02503                     normal state(Value = 0)
02504 
02505                 If the gadget is a scrollbar it sets the current position on the thumb
02506 
02507                 The function can be used to set the values of the following controls.
02508 
02509                 Edit
02510                 Static
02511                 Button
02512                 ListBox
02513                 ComboBox
02514                 ScrollBar
02515                 cc_CheckList
02516                 cc_Slider
02517 
02518     Errors:     If the function is called on an invalid control then an ENSURE failure will
02519                 occur in a DEBUG build. In a retail build FALSE is returned.
02520 
02521     SeeAlso:    DialogOp::SetLongGadgetValue
02522 
02523 ********************************************************************************************/
02524 
02525 BOOL DialogManager::SetLongGadgetValue(CWindowID WindowID,
02526                                     CGadgetID Gadget,
02527                                     INT32 Value,
02528                                     BOOL EndOfList,
02529                                     INT32 ListPos)
02530 {
02531     wxWindow * pGadget = GetGadget(WindowID, Gadget);
02532     if (!pGadget) return FALSE;
02533 
02534     if ( pGadget->IsKindOf(CLASSINFO(wxButton)) ||
02535         pGadget->IsKindOf(CLASSINFO(wxBitmapButton)) )
02536     {
02537         // These bitmap buttons are meant to be tristate
02538         PORTNOTETRACE("dialog","DialogManager::SetLongGadgetValue on BitmapButton - do nothing");
02539         return FALSE;
02540     }
02541 
02542     // Oh if only virtual functions work here. Sadly, they don't, as SetValue is not in wxControl
02543     if ( pGadget->IsKindOf(CLASSINFO(wxCheckBox)) )
02544     {
02545         ((wxCheckBox *)(pGadget))->SetValue(Value !=0);
02546         return TRUE;
02547     }
02548 
02549     if ( pGadget->IsKindOf(CLASSINFO(wxRadioButton)) )
02550     {
02551         ((wxRadioButton *)(pGadget))->SetValue( Value != 0 );
02552         return TRUE;
02553     }
02554 
02555     if ( pGadget->IsKindOf(CLASSINFO(wxScrollBar)) )
02556     {
02557         ((wxScrollBar *)(pGadget))->SetThumbPosition(Value);
02558         return TRUE;
02559     }
02560 
02561     if ( pGadget->IsKindOf(CLASSINFO(wxSlider)) )
02562     {
02563         ((wxSlider *)(pGadget))->SetValue(Value);
02564         return TRUE;
02565     }
02566 
02567     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
02568     {
02569         ((wxSliderCombo *)(pGadget))->SetSliderValue(Value);
02570         return TRUE;
02571     }
02572 
02573     if ( pGadget->IsKindOf(CLASSINFO(wxGauge)) )
02574     {
02575         ((wxGauge *)(pGadget))->SetValue(Value);
02576         return TRUE;
02577     }
02578 
02579     if ( pGadget->IsKindOf(CLASSINFO(wxCamArtControl)) )
02580     {
02581         ((wxCamArtControl *)(pGadget))->SetValue(Value);
02582         return TRUE;
02583     }
02584 
02585 
02586 #if 0
02587     // it seems on an edit box we might be meant to set the garet, but it's difficult to know what's
02588     // going on here
02589     else if (ClassNameStr == String_16(TEXT("cc_CustomEdit")))//?
02590     {
02591         ...
02592     }
02593 #endif
02594 
02595     // Hmmm - no luck so far, let's try a string
02596 
02597     String_256 StrValue;
02598     // Convert Value to a string
02599     Convert::LongToString(Value, &StrValue);
02600     return(SetStringGadgetValue(WindowID, Gadget, StrValue, EndOfList, ListPos));
02601 }
02602 
02603 /********************************************************************************************
02604 
02605 >   BOOL DialogManager::SetDoubleGadgetValue(CWindowID WindowID,
02606                                         CGadgetID Gadget,
02607                                         double Value,
02608                                         BOOL EndOfList = TRUE,
02609                                         INT32 ListPos = 0)
02610 
02611     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> (liberally copied from Simon's SetLongGadgetValue)
02612     Created:    16/12/94
02613     Inputs:     WindowID: Dialog box window identifier
02614                 Gadget: Identifier of the gadget
02615                 Value:    double value
02616 
02617                 The following inputs only need to be provided if the gadget has multiple
02618                 values, for example a ListBox.
02619 
02620                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02621                             value list. (Default = TRUE)
02622                             FALSE if the value is to be added to the ListPos position in the
02623                             list.
02624                 ListPos:     If EndOfList = FALSE then this input specifies the position
02625                             in the list (Default = 0, so if you want to add the value to
02626                             the top of the list simply specify EndOfList = FALSE)
02627 
02628                             If the gadget is a ComboBox then setting ListPos = -1 will
02629                             set the combo box's edit gadget field.
02630 
02631 
02632 
02633     Outputs:    -
02634     Returns:    TRUE if the gadgets value could be set
02635                 FALSE if it could not
02636 
02637     Purpose:    This function is used to set a numeric gadget value. It performs
02638                 different functions depending on the type of the gadget.
02639 
02640                 For Windows
02641                 -----------
02642 
02643                 If the gadget is a button it sets the button's current state.
02644 
02645                     For check and radio buttons it sets the state to either checked
02646                     (Value = 1) or unchecked (Value = 0). In the case of a 3 state button
02647                     the third state can be specified by a (Value = 2).
02648 
02649                     For Push buttons it can be used to set a depressed (Value = 1)/
02650                     normal state(Value = 0)
02651 
02652                 If the gadget is a scrollbar it sets the current position on the thumb
02653 
02654                 The function can be used to set the values of the following controls.
02655 
02656                 Edit
02657                 Static
02658                 Button
02659                 ListBox
02660                 ComboBox
02661                 ScrollBar
02662                 cc_CheckList
02663                 cc_Slider
02664 
02665                 Note most of these only take settings to integer precision so you might as
02666                 well use SetLongGadgetValue instead (the exception being text fields of
02667                 course).
02668 
02669     Errors:     If the function is called on an invalid control then an ENSURE failure will
02670                 occur in a DEBUG build. In a retail build FALSE is returned.
02671 
02672     SeeAlso:    DialogOp::SetDoubleGadgetValue, DialogMgr::SetLongGadgetValue
02673 
02674 ********************************************************************************************/
02675 
02676 BOOL DialogManager::SetDoubleGadgetValue(CWindowID WindowID,
02677                                     CGadgetID Gadget,
02678                                     double Value,
02679                                     BOOL EndOfList,
02680                                     INT32 ListPos)
02681 {
02682     wxWindow * pGadget = GetGadget(WindowID, Gadget);
02683     if (!pGadget) return FALSE;
02684 
02685     if (( pGadget->IsKindOf(CLASSINFO(wxButton))) ||
02686         ( pGadget->IsKindOf(CLASSINFO(wxBitmapButton))) ||
02687         ( pGadget->IsKindOf(CLASSINFO(wxCheckBox))) ||
02688         ( pGadget->IsKindOf(CLASSINFO(wxRadioButton))) ||
02689         ( pGadget->IsKindOf(CLASSINFO(wxScrollBar))) ||
02690         ( pGadget->IsKindOf(CLASSINFO(wxSlider))) ||
02691         ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo))) ||
02692         ( pGadget->IsKindOf(CLASSINFO(wxCamArtControl))) ||
02693         ( pGadget->IsKindOf(CLASSINFO(wxGauge)))
02694         )
02695         return SetLongGadgetValue( WindowID, Gadget, (INT32)(floor(Value+0.5)), EndOfList, ListPos);
02696 
02697     String_256 StrValue;
02698     // Convert Value to a string
02699     Convert::DoubleToString(Value, &StrValue);
02700     return(SetStringGadgetValue(WindowID, Gadget, StrValue, EndOfList, ListPos));
02701 }
02702 
02703 /********************************************************************************************
02704 
02705 >   BOOL DialogManager::SetStringGadgetValue(CWindowID WindowID,
02706                                             CGadgetID Gadget,
02707                                             UINT32 IDStr,
02708                                             BOOL EndOfList = TRUE,
02709                                             INT32 ListPos = 0)
02710 
02711 
02712 
02713 
02714     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02715     Created:    17/8/93
02716     Inputs:     WindowID: Dialog box window identifier
02717                 Gadget: Gadget identifier
02718                 StrID:    Resource ID of string
02719 
02720                 The following inputs only need to be provided if the gadget has multiple
02721                 values, for example a ListBox.
02722 
02723                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02724                             value list. (Default = TRUE)
02725                             FALSE if the value is to be added to the ListPos position in the
02726                             list.
02727 
02728                 ListPos:     If EndOfList = FALSE then this input specifies the position
02729                             in the list (Default = 0, so if you want to add the value to
02730                             the top of the list simply specify EndOfList = FALSE)
02731 
02732                             If the gadget is a ComboBox then setting ListPos = -1 will
02733                             set the combo box's edit gadget field.
02734 
02735 
02736     Outputs:    -
02737 
02738     Returns:    TRUE if the gadgets value could be set
02739                 FALSE if it could not
02740 
02741     Purpose:    This function is used to set a gadgets value to a resource string. It can only
02742                 be used on gadgets with a string value type.
02743 
02744                 For Windows
02745                 -----------
02746 
02747                 This function can be used to set the string values of the following controls:
02748 
02749                 Button
02750                 Static
02751                 Edit
02752                 ListBox
02753                 ComboBox
02754 
02755 
02756     Errors:     If the function is called on an invalid control then an ENSURE failure will
02757                 occur in a DEBUG build. In a retail build FALSE is returned.
02758 
02759     SeeAlso:    DialogOp::SetStringGadgetValue
02760 
02761 ********************************************************************************************/
02762 
02763 BOOL DialogManager::SetStringGadgetValue(CWindowID WindowID,
02764                                         CGadgetID Gadget,
02765                                         UINT32 IDStr,
02766                                         BOOL EndOfList,
02767                                         INT32 ListPos)
02768 {
02769     String_256* StrVal = new String_256(IDStr); // Obtain the string resource
02770     ERROR1IF(StrVal == NULL, FALSE, _R(IDS_OUT_OF_MEMORY));
02771 
02772     // It is neccessary to store the new strings on the DiscardStrList so that
02773     // when the dialog is deleted the strings are also deleted.
02774     DlgDiscardString   *DiscardStr = new DlgDiscardString;
02775     if( DiscardStr == NULL )
02776     {
02777         delete StrVal;
02778         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));
02779     }
02780 
02781     // If we are setting a string in a gadget on a page within a
02782     // property sheet then we need to store the windowID of the property sheet
02783     // This way it will get deleted when the property sheet is deleted in the
02784     // Delete method
02785 
02786     wxWindow           *pCWnd = (wxWindow *)WindowID;
02787     wxWindow           *WndID = pCWnd;
02788 /*  if (pCWnd != NULL)
02789     {
02790         if (pCWnd->IsKindOf(RUNTIME_CLASS(wxNotebookPage)))
02791         {
02792             wxWindow* Parent = pCWnd->GetParent();
02793             ERROR2IF(Parent == NULL, FALSE, "Property page found without parent property sheet");
02794             ERROR2IF(!(Parent->IsKindOf(RUNTIME_CLASS(wxPropertySheetDialog))), FALSE,"Property page parent not a property sheet");
02795             WndID = Parent->GetSafeHwnd();
02796         }
02797     } */
02798 
02799     DiscardStr->DlgWindow = WndID;
02800     DiscardStr->pStr = StrVal;
02801     DiscardStrList.AddHead( DiscardStr );
02802 
02803     return (SetStringGadgetValue(WindowID, Gadget, *StrVal, EndOfList, ListPos));
02804 }
02805 
02806 /********************************************************************************************
02807 
02808 >   static wxWindow * DialogManager::GetGadget(CWindowID WindowID, CGadgetID Gadget)
02809 
02810     Author:     Alex Bligh (alex@alex.org.uk)
02811     Created:    20/12/2005
02812     Inputs:     WindowID: Dialog box window identifier
02813                 Gadget: Gadget identifier
02814                 StrID:    Resource ID of string
02815 
02816 ********************************************************************************************/
02817 
02818 wxWindow * DialogManager::GetGadget(CWindowID WindowID, CGadgetID Gadget)
02819 {
02820     ERROR2IF(!WindowID || !WindowID->IsKindOf(CLASSINFO(wxWindow)), FALSE, "Bad Window ID passed");
02821     wxWindow * pGadget=WindowID->FindWindow(Gadget);
02822 //  TRACEUSER("amb",_T("pwxDialog=0x%016llx Gadget=%d(%s) pGadget=0x%016llx"), WindowID, Gadget, CamResource::GetObjectName((ResourceID)Gadget), pGadget);
02823     if (!pGadget)
02824     {
02825         // Some dialogs seem to consciously do this, EG galleries
02826 //      ERROR3_PF((_T("Bad Gadget ID %d(%s) passed"), Gadget, CamResource::GetObjectName((ResourceID)Gadget)));
02827         return NULL;
02828     }
02829 #if 0
02830     const TCHAR * pGadgetClassName = (const TCHAR *) pGadget->GetClassInfo()->GetClassName();
02831     TRACEUSER("amb",_T("Gadget is a %s"),pGadgetClassName);
02832 #endif
02833     return pGadget;
02834 }
02835 
02836 /********************************************************************************************
02837 
02838 >   static OpDescriptor * DialogManager::GetGadgetOpDescritpor(CWindowID WindowID, CGadgetID Gadget);
02839 
02840     Author:     Alex Bligh (alex@alex.org.uk)
02841     Created:    20/12/2005
02842     Inputs:     WindowID: Dialog box window identifier
02843                 Gadget: Gadget identifier
02844     Returns:    pointer to an OpDescriptor, or NULL if not found
02845 
02846 ********************************************************************************************/
02847 
02848 OpDescriptor * DialogManager::GetGadgetOpDescriptor(CWindowID WindowID, CGadgetID Gadget)
02849 {
02850     wxWindow * pWindow = GetGadget(WindowID, Gadget);
02851     if (!pWindow) return NULL;
02852 
02853     // If it's not a wxControl, return
02854     if (!pWindow->IsKindOf(CLASSINFO(wxControl)))
02855         return NULL;
02856 
02857     wxControl * pControl = (wxControl *)pWindow;
02858     return ControlList::Get()->Find(pControl);
02859 }
02860 
02861 /********************************************************************************************
02862 
02863 >   BOOL DialogManager::SetStringGadgetValue(CWindowID WindowID,
02864                                         CGadgetID Gadget,
02865                                         StringBase* StrVal,
02866                                         BOOL EndOfList,
02867                                         INT32 ListPos)
02868 {
02869     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
02870     Created:    17/8/93
02871     Inputs:     WindowID: Dialog box window identifier
02872                 Gadget: Gadget identifier
02873                 StrID:    Resource ID of string
02874 
02875 
02876                 The following inputs only need to be provided if the gadget has multiple
02877                 values, for example a ListBox.
02878 
02879                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
02880                             value list. (Default = TRUE)
02881                             FALSE if the value is to be added to the ListPos position in the
02882                             list.
02883 
02884                 ListPos:     If EndOfList = FALSE then this input specifies the position
02885                             in the list (Default = 0, so if you want to add the value to
02886                             the top of the list simply specify EndOfList = FALSE)
02887 
02888                             If the gadget is a ComboBox then setting ListPos = -1 will
02889                             set the combo box's edit gadget field.
02890 
02891 
02892     Outputs:    -
02893     Returns:    TRUE if the gadgets value could be set
02894                 FALSE if it could not
02895 
02896     Purpose:    This function is used to set a gadgets string value. It can only
02897                 be used on gadgets with a string value type.
02898 
02899                 For Windows
02900                 -----------
02901 
02902                 This function can be used to set the string values of the following controls:
02903 
02904                 Button
02905                 Static
02906                 Edit
02907                 ListBox
02908                 ComboBox
02909 
02910 
02911     Errors:     If the function is called on an invalid control then an ENSURE failure will
02912                 occur in a DEBUG build. In a retail build FALSE is returned.
02913 
02914     SeeAlso:    DialogOp::SetStringGadgetValue
02915 
02916 ********************************************************************************************/
02917 
02918 BOOL DialogManager::SetStringGadgetValue(CWindowID WindowID,
02919                                         CGadgetID Gadget,
02920                                         const StringBase& StrVal,
02921                                         BOOL EndOfList,
02922                                         INT32 ListPos)
02923 {
02924     wxWindow * pGadget = GetGadget(WindowID, Gadget);
02925     if (!pGadget) return FALSE;
02926 
02927     wxString String( (const TCHAR*)StrVal );
02928 
02929     //if ( pGadget->IsKindOf(CLASSINFO(wxControlWithItems)) ) // Includes wxListBox - this seems to have false positives
02930     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
02931         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
02932         pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ||
02933         pGadget->IsKindOf(CLASSINFO(wxChoice))
02934         )
02935     {
02936         if (EndOfList)
02937         {
02938             if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
02939                 ((wxOwnerDrawnComboBox *)pGadget)->Append(String);
02940             else
02941                 ((wxControlWithItems *)pGadget)->Append(String);
02942             return TRUE;
02943         }
02944 
02945         if (pGadget->IsKindOf(CLASSINFO(wxComboBox)) && (pGadget->GetWindowStyle() & wxCB_SORT))
02946         {
02947             PORTNOTETRACE("dialog", "Mainting original order of combos displayed sorted is not supported");
02948             pGadget->SetWindowStyle(pGadget->GetWindowStyle() & ~wxCB_SORT);
02949         }
02950 
02951         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) && (pGadget->GetWindowStyle() & wxCB_SORT))
02952         {
02953             PORTNOTETRACE("dialog", "Mainting original order of combos displayed sorted is not supported");
02954             pGadget->SetWindowStyle(pGadget->GetWindowStyle() & ~wxCB_SORT);
02955         }
02956 
02957         if (pGadget->IsKindOf(CLASSINFO(wxListBox)) && (pGadget->GetWindowStyle() & wxLB_SORT))
02958         {
02959             PORTNOTETRACE("dialog", "Mainting original order of list boxes displayed sorted is not supported");
02960             pGadget->SetWindowStyle(pGadget->GetWindowStyle() & ~wxLB_SORT);
02961         }
02962 
02963         if (ListPos >=0)
02964         {
02965             if (
02966                 (pGadget->IsKindOf(CLASSINFO(wxComboBox)) && (pGadget->GetWindowStyle() & wxCB_SORT)) ||
02967                 (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) && (pGadget->GetWindowStyle() & wxCB_SORT)) ||
02968                 (pGadget->IsKindOf(CLASSINFO(wxListBox)) && (pGadget->GetWindowStyle() & wxLB_SORT)) ||
02969                 (pGadget->IsKindOf(CLASSINFO(wxChoice)))
02970                 )
02971             {
02972                 // Control does not support inserting at a position as it is sorted. We should append it and
02973                 // it will appear in the right place
02974                 if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
02975                     ((wxOwnerDrawnComboBox *)pGadget)->Append(String);
02976                 else
02977                     ((wxControlWithItems *)pGadget)->Append(String);
02978                 return TRUE;
02979             }
02980             if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
02981                 return (((wxOwnerDrawnComboBox *)pGadget)->Insert(String, ListPos) <0 )?FALSE:TRUE;
02982             else
02983                 return (((wxControlWithItems *)pGadget)->Insert(String, ListPos) <0 )?FALSE:TRUE;
02984         }
02985 
02986         if (pGadget->IsKindOf(CLASSINFO(wxComboBox)))
02987         {
02988             ((wxComboBox *)pGadget)->SetValue(String);
02989             return TRUE;
02990         }
02991 
02992         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
02993         {
02994             ((wxOwnerDrawnComboBox *)pGadget)->SetValue(String);
02995             return TRUE;
02996         }
02997 
02998         ERROR3("Attempt to insert item into edit field of gadget without one");
02999         return FALSE;
03000     }
03001 
03002     if ( pGadget->IsKindOf(CLASSINFO(wxTextCtrl)) )
03003     {
03004         ((wxTextCtrl *)pGadget)->SetValue(String);
03005         return TRUE;
03006     }
03007 
03008     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
03009     {
03010         ((wxSliderCombo *)pGadget)->SetValue(String);
03011         return TRUE;
03012     }
03013 
03014     pGadget->SetLabel(String);
03015 
03016     return TRUE;
03017 }
03018 
03019 
03020 
03021 /********************************************************************************************
03022 
03023 >   BOOL DialogManager::SetCustomComboGadgetValue(CWindowID WindowID,
03024                                                 CGadgetID Gadget,
03025                                                 CustomComboBoxControlDataItem* TheItem,
03026                                                 BOOL EndOfList,
03027                                                 INT32 ListPos)
03028 {
03029     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> S
03030     Created:    12/8/99
03031     Inputs:     WindowID: Dialog box window identifier
03032                 Gadget: Gadget identifier
03033                 TheItem:  The CustomComboBoxControlDataItem that is to be inserted
03034 
03035 
03036                 EndOfList and ListPos do not actually do anything (as yet),
03037                 BUT have been left a function arguments to avoid having to change
03038                 too many function calls when converting calls on windows
03039                 ComboBoxes into our new custom comboboxes!
03040 
03041                 NOTES on ListPos value:
03042 
03043                     >= 0        Insert the item into the control (only at end of list)
03044                     == -1       Select the item with this index (TheItem should be
03045                                 equal to NULL)
03046 
03047     Outputs:    -
03048     Returns:    TRUE if the gadgets value could be set
03049                 FALSE if it could not
03050 
03051     Purpose:    This function is used to set a CustomComboBoxes item (i.e.  basically
03052                 insert another item)
03053 
03054                 For Windows
03055                 -----------
03056 
03057                 This function can be used to set items in the following controls:
03058 
03059                 cc_1dBitmapComboBoxEdit
03060                 cc_2dBitmapComboBoxEdit
03061 
03062     Errors:     If the function is called on an invalid control then an ENSURE failure will
03063                 occur in a DEBUG build. In a retail build FALSE is returned.
03064 
03065     SeeAlso:    nothing else!
03066 
03067 ********************************************************************************************/
03068 
03069 BOOL DialogManager::SetCustomComboGadgetValue(CWindowID WindowID,
03070                                             CGadgetID Gadget,
03071                                             CustomComboBoxControlDataItem* TheItem,
03072                                             BOOL EndOfList,
03073                                             INT32 ListPos)
03074 {
03075     PORTNOTETRACE("dialog","DialogManager::SetCustomComboGadgetValue - do nothing");
03076 #ifndef EXCLUDE_FROM_XARALX
03077     String_256 ClassNameStr;  // The control type
03078 
03079     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
03080     // Find out the class type of the gadget
03081     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
03082 
03083     if ((ClassNameStr == String_64(TEXT("cc_1dBitmapComboBoxEdit"))) ||
03084         (ClassNameStr == String_64(TEXT("cc_2dBitmapComboBoxEdit")))   )
03085     {
03086         BOOL RetVal = FALSE;
03087 
03088         if (ListPos == 0) // Insert the string in the combo box's edit gadget
03089         {
03090             ASSERT (TheItem);
03091 
03092             RetVal = SendMessage (hGadget, WM_CCINSERTBITMAP, 0, (WPARAM) (CustomComboBoxControlDataItem*) TheItem);
03093 
03094         }
03095         else if (ListPos >= 1)      // but ListPos can be used to set the selected
03096                                     // item (other than tbe many/custom representations)
03097         {
03098             ASSERT (TheItem == NULL);
03099 
03100             RetVal = SendMessage (hGadget, CB_SETCURSEL, (WPARAM) (ListPos-1), (LPARAM) 0);
03101         }
03102         else if ((ListPos == -1) || (ListPos == -2))
03103         {
03104             ASSERT (TheItem == NULL);
03105 
03106             RetVal = SendMessage (hGadget, CB_SETCURSEL, (WPARAM) (ListPos), (LPARAM) 0);
03107         }
03108 
03109         return (RetVal);
03110     }
03111     return (TRUE);
03112     ENSURE(FALSE, "Calling SetCustomComboGadgetValue for an invalid control");
03113 #endif
03114     return FALSE;
03115 }
03116 
03117 /********************************************************************************************
03118 
03119 >   BOOL DialogManager::SelectCustomComboGadgetValueOnString (CWindowID WindowID,
03120                                                             CGadgetID Gadget,
03121                                                             StringBase* StrVal)
03122 {
03123     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> S
03124     Created:    9/9/99
03125     Inputs:     WindowID: Dialog box window identifier
03126                 Gadget: Gadget identifier
03127                 StrVal:   The name of the item that is to be selected
03128     Outputs:    -
03129     Returns:    TRUE if the item could be selected
03130                 FALSE if it could not
03131 
03132     Purpose:    This function is used to select an item (StrVal) within
03133                 cc_2dBitmapComboBoxEdit custom comboboxes
03134 
03135     Errors:     If the function is called on an invalid control then an ENSURE failure will
03136                 occur in a DEBUG build. In a retail build FALSE is returned.
03137 
03138     SeeAlso:    nothing else!
03139 
03140 ********************************************************************************************/
03141 
03142 BOOL DialogManager::SelectCustomComboGadgetValueOnString (CWindowID WindowID,
03143                                                         CGadgetID Gadget,
03144                                                         StringBase* StrVal)
03145 {
03146     PORTNOTETRACE("dialog","DialogManager::SelectCustomComboGadgetValueOnString - do nothing");
03147 #ifndef EXCLUDE_FROM_XARALX
03148     String_256 ClassNameStr;  // The control type
03149 
03150     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
03151     // Find out the class type of the gadget
03152     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
03153 
03154     if( ClassNameStr == String_64( TEXT("cc_2dBitmapComboBoxEdit") ) )
03155     {
03156         BOOL RetVal = FALSE;
03157 
03158         RetVal = SendMessage (hGadget, CB_FINDSTRINGEXACT, (WPARAM) (-1), (INT32)(TCHAR*)(*StrVal));
03159 
03160         return (RetVal);
03161     }
03162     return (TRUE);
03163     ENSURE(FALSE, "Calling SelectCustomComboGadgetValueOnString for an invalid control");
03164 #else
03165     return FALSE;
03166 #endif
03167 }
03168 
03169 
03170 
03171 /********************************************************************************************
03172 
03173 >   BOOL DialogManager::SetGadgetRange(CWindowID WindowID,
03174                                     CGadgetID Gadget,
03175                                     INT32 Min,
03176                                     INT32 Max,
03177                                     INT32 PageInc = 1)
03178 
03179     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
03180     Created:    2/9/93
03181     Inputs:     WindowID:       Dialog box window identifier
03182                 Gadget:     Gadget identifier
03183     Outputs:    Min:            Minimum range value
03184                 Max:            Maximum range value
03185                 PageInc:        For gadgets which allow their value to be increased or
03186                                 decreased by a fixed value other than 1.
03187                                 Eg. a scroll bar allows the user to move the scroll
03188                                 bar's thumb a 'page' at a time. PageInc specifies how many
03189                                 units the scroll bar's thumb should move.
03190 
03191     Returns:    -
03192     Purpose:    For setting the range of a gadget.
03193 
03194                 Fow Windows
03195                 -----------
03196 
03197                 For scrollbar or trackbar gadgets this function sets the scrollbar's Min and Max
03198                 values. The PageInc value specifies how many units the scroll bar should move
03199                 when a PAGE message is received.
03200 
03201                 This function can also be used to set the range of cc_Slider controls.
03202 
03203     Errors:     If the function is called on an invalid control then an ENSURE failure will
03204                 occur in a DEBUG build. In a retail build FALSE is returned.
03205 
03206     SeeAlso:    DialogOp::SetGadgetRange
03207 
03208 ********************************************************************************************/
03209 
03210 
03211 BOOL DialogManager::SetGadgetRange(CWindowID WindowID,
03212                                 CGadgetID Gadget,
03213                                 INT32 Min,
03214                                 INT32 Max,
03215                                 INT32 PgIncr)
03216 {
03217     wxWindow * pGadget = GetGadget(WindowID, Gadget);
03218     if (!pGadget) return FALSE;
03219 
03220     INT32 LineIncr = (Max-Min+50)/100;
03221 //  Don't set PgIncr for now
03222 //  if (LineIncr>PgIncr/2)
03223 //      LineIncr = PgIncr/2;
03224     if (LineIncr<1)
03225         LineIncr=1;
03226 
03227     if ( pGadget->IsKindOf(CLASSINFO(wxScrollBar)) )
03228     {
03229         wxScrollBar * pScroll = (wxScrollBar *)pGadget;
03230         ERROR3IF(Min !=0 , "Scrollbars with non-zero minimum need to be subclassed");
03231         pScroll->SetScrollbar(pScroll->GetThumbPosition(), pScroll->GetThumbSize(), Max-Min, PgIncr, TRUE);
03232         return TRUE;
03233     }
03234 
03235     if ( pGadget->IsKindOf(CLASSINFO(wxSlider)) )
03236     {
03237         ((wxSlider *)(pGadget))->SetRange(Min, Max);
03238         ((wxSlider *)(pGadget))->SetLineSize(LineIncr);
03239         return TRUE;
03240     }
03241 
03242     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
03243     {
03244         ((wxSliderCombo *)(pGadget))->SetRange(Min, Max);
03245         ((wxSliderCombo *)(pGadget))->SetLineSize(LineIncr);
03246         return TRUE;
03247     }
03248 
03249     if ( pGadget->IsKindOf(CLASSINFO(wxGauge)) )
03250     {
03251         ERROR3IF(Min !=0 , "Gauges with non-zero minimum need to be subclassed");
03252         ((wxGauge *)(pGadget))->SetRange(Max-Min);
03253         return TRUE;
03254     }
03255 
03256     return FALSE;
03257 }
03258 
03259 
03260 
03261 /********************************************************************************************
03262 
03263 >   static BOOL BOOL DialogManager::SetListBoxSelection( CWindowID WindowID, CGadgetID Gadget,
03264                                 INT32 Index, BOOL SelectIt, BOOL SingleSelection )
03265 
03266     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03267     Created:    11/10/94
03268     Inputs:     hGadget:        Control window handle
03269                 Index:          Index of value to be selected  (0..Number_of_Items - 1)
03270                                 OR -1 to {de}select all items in the gadget
03271                 SelectIt:       TRUE to select the item
03272                                 FALSE to deselect the item
03273                 SingleSelection:
03274                                 TRUE to set the selection state of a single item (clears
03275                                 any existing selection)
03276                                 FALSE to set selection in a multiple-selection box (does
03277                                 not affect the selection other than on this item). Note
03278                                 that if this is really a single-selection listbox, this
03279                                 flag is effectively always forced to TRUE.
03280 
03281     Returns:    TRUE if the value specified by Index could be selected, FALSE otherwise
03282     Purpose:    For selecting the Value specified by Index in a list Gadget.
03283                 A subroutine used by the selection-setting DialogManager calls
03284 
03285     Scope:      private
03286 
03287     Errors:     If the function is called on an invalid control then an ERROR3 failure will
03288                 occur in a DEBUG build.
03289 
03290 ********************************************************************************************/
03291 
03292 BOOL DialogManager::SetListBoxSelection( CWindowID WindowID, CGadgetID Gadget, INT32 Index, BOOL SelectIt, BOOL SingleSelection )
03293 {
03294     wxWindow * pGadget = GetGadget(WindowID, Gadget);
03295     if (!pGadget) return FALSE;
03296 
03297     if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
03298     {
03299         if (SingleSelection)
03300         {
03301             ((wxListBox *)pGadget)->SetSelection(wxNOT_FOUND);
03302             // It's not clear from the docs that that actually clears the selection in a list box (it
03303             // says "doesn't affect other selected items" so try this to be safe
03304             wxArrayInt sels;
03305             INT32 i;
03306             for (i=0; i<((wxListBox *)pGadget)->GetSelections(sels); i++)
03307                 ((wxListBox *)pGadget)->Deselect(sels[i]);
03308         }
03309 
03310         if (Index>=0)
03311         {
03312             if (SelectIt)
03313             {
03314                 ((wxListBox *)pGadget)->SetSelection(Index);
03315             }
03316             else
03317             {
03318                 ((wxListBox *)pGadget)->Deselect(Index);
03319             }
03320             return TRUE;
03321         }
03322         else
03323         {
03324             INT32 i;
03325             for (i=0; i<(INT32)((wxListBox *)pGadget)->GetCount(); i++)
03326             {
03327                 if (SelectIt)
03328                 {
03329                     ((wxListBox *)pGadget)->SetSelection(i);
03330                 }
03331                 else
03332                 {
03333                     ((wxListBox *)pGadget)->Deselect(i);
03334                 }
03335             }           
03336         }
03337     }
03338 
03339     ERROR3("SetListBoxSelection called for non-listbox control");
03340     return(FALSE);
03341 }
03342 
03343 
03344 /********************************************************************************************
03345 
03346 >   BOOL DialogManager::SetBoolGadgetSelected(CWindowID WindowID, CGadgetID Gadget,
03347                                                 BOOL SelectIt, INT32 Index = 0)
03348 
03349     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03350     Created:    11/10/94
03351     Inputs:     WindowID:       Dialog box window identifier
03352                 Gadget:     Gadget identifier
03353                 SelectIt:       TRUE to select, FALSE to deselect the control/item
03354                 Index:          The index of the item within a combo or list box which
03355                                 you wish to (de)select, or -1 to (de)select all items
03356                                 in the list.
03357     Returns:    TRUE if it succeeded
03358     Purpose:    For setting the selection state of a gadget, or an item within a list gadget
03359 
03360                 For Windows
03361                 -----------
03362                 Can be used to set the selection state for any on/off button type things
03363                 Can be used on combo/list boxes to (de)select items. Note that if the listbox
03364                 is a multiple selection box, setting the selection state of an item does NOT
03365                 affect the state of any other items in the list (so to set only one item
03366                 selected you must either deselect all before calling this function, or call
03367                 SetSelectedGadgetIndex.
03368 
03369     Errors:     If the function is called on an invalid control then an ENSURE failure will
03370                 occur in a DEBUG build. In a retail build FALSE is returned.
03371 
03372     SeeAlso:    DialogOp::SetBoolGadgetSelected
03373 
03374 ********************************************************************************************/
03375 
03376 BOOL DialogManager::SetBoolGadgetSelected(CWindowID WindowID, CGadgetID Gadget,
03377                                             BOOL SelectIt, INT32 Index)
03378 {
03379 //  INT32 Count = -1;
03380     wxWindow * pGadget = GetGadget(WindowID, Gadget);
03381     if (!pGadget) return FALSE;
03382 
03383     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
03384         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
03385         pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ||
03386         pGadget->IsKindOf(CLASSINFO(wxChoice))
03387         )
03388     {   
03389         // Support listboxes with multiple selections
03390         if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
03391         {
03392             return SetListBoxSelection(WindowID, Gadget, Index, SelectIt, FALSE);
03393         }
03394         
03395         if (Index>=0)
03396         {
03397             if (SelectIt)
03398             {
03399                 if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
03400                     ((wxOwnerDrawnComboBox *)pGadget)->SetSelection(Index);
03401                 else    
03402                     ((wxControlWithItems *)pGadget)->SetSelection(Index);
03403             }
03404             else
03405             {
03406                 // We clear the current selection if it is current
03407                 if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
03408                 {
03409                     if (((wxOwnerDrawnComboBox *)pGadget)->GetSelection() == Index)
03410                         ((wxOwnerDrawnComboBox *)pGadget)->SetSelection(wxNOT_FOUND);
03411                 }
03412                 else
03413                 {
03414                     if (((wxControlWithItems *)pGadget)->GetSelection() == Index)
03415                         ((wxControlWithItems *)pGadget)->SetSelection(wxNOT_FOUND);
03416                 }   
03417             }
03418             return TRUE;
03419         }
03420         else
03421         {
03422             if (SelectIt)
03423             {
03424                 // Hmmm - we've been asked to set the selection on every item
03425                 // in a control where only one thing can be selected. Give
03426                 // it a go then..
03427                 INT32 i;
03428                 if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
03429                     for (i=0; i<(INT32)((wxOwnerDrawnComboBox *)pGadget)->GetCount(); i++)
03430                         ((wxOwnerDrawnComboBox *)pGadget)->SetSelection(i);
03431                 else
03432                     for (i=0; i<(INT32)((wxControlWithItems *)pGadget)->GetCount(); i++)
03433                         ((wxControlWithItems *)pGadget)->SetSelection(i);
03434             }
03435             else
03436             {
03437                 if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
03438                     ((wxOwnerDrawnComboBox *)pGadget)->SetSelection(wxNOT_FOUND);
03439                 else
03440                     ((wxControlWithItems *)pGadget)->SetSelection(wxNOT_FOUND);
03441             }
03442         }
03443     }
03444 
03445     // The following types are cannot be ticked /.unticked. OpDescriptors
03446     // do this then break the control setting
03447     if ( pGadget->IsKindOf(CLASSINFO(wxScrollBar))
03448         || pGadget->IsKindOf(CLASSINFO(wxSlider)) 
03449         || pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) 
03450         || pGadget->IsKindOf(CLASSINFO(wxGauge))  )
03451         return TRUE;
03452 
03453     // Assume that we can set it via the SetLongGadgetValue function (radio buttons, etc)
03454     return(SetLongGadgetValue(WindowID, Gadget, SelectIt));
03455 }
03456 
03457 
03458 /********************************************************************************************
03459 
03460 >   BOOL DialogManager::SetSelectedValueIndex(CWindowID WindowID,
03461                                         CGadgetID Gadget,
03462                                         INT32 Index)
03463 
03464     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
03465     Created:    20/9/93
03466     Inputs:     WindowID:       Dialog box window identifier
03467                 Gadget:     Dialog identifier
03468                 Index:          Index of value to be selected  (0..Number_of_Items - 1)
03469                                 OR -1 to deselect all values in the gadget (set no-selection)
03470     Outputs:    -
03471     Returns:    TRUE if the value specified by Index could be selected, FALSE otherwise
03472     Purpose:    For selecting the Value specified by Index in a list Gadget
03473 
03474                 For Windows
03475                 -----------
03476 
03477                 The function can be called on ListBox and ComboBox gadgets to set the
03478                 currently selected value
03479 
03480     Errors:     If the function is called on an invalid control then an ENSURE failure will
03481                 occur in a DEBUG build. In a retail build FALSE is returned.
03482 
03483                 NOTE that windows controls cannot be guaranteed to accept more than 32768
03484                 items, as an (INT32) is used to pass the index. These controls generate an
03485                 ENSURE failure at present if values outside the range -1 .. 32767 are given.
03486                 In future, special CC controls for Camelot may not have this restriction.
03487 
03488     SeeAlso:    DialogOp::SetSelectedValueIndex
03489 
03490 ********************************************************************************************/
03491 
03492 BOOL DialogManager::SetSelectedValueIndex(CWindowID WindowID,
03493                                         CGadgetID Gadget,
03494                                         INT32 Index)
03495 {
03496     if (Index>=0)
03497         return SetBoolGadgetSelected(WindowID, Gadget, TRUE, Index);
03498     return SetBoolGadgetSelected(WindowID, Gadget, FALSE, -1);
03499 }
03500 
03501 
03502 
03503 /********************************************************************************************
03504 
03505 >   BOOL DialogManager::SetSelectedValueRange(CWindowID WindowID,
03506                                         CGadgetID Gadget,
03507                                         WORD StartIndex,
03508                                         WORD EndIndex,
03509                                         BOOL Selected)
03510 
03511     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
03512     Created:    29/04/94
03513     Inputs:     WindowID:       Dialog box window identifier
03514                 Gadget:     Dialog identifier
03515                 StartIndex:     Index of first value to be selected  (0..Number_of_Items - 1)
03516                 EndIndex:       Index of last value to be selected  (0..Number_of_Items - 1)
03517                 Selected:       Flag specifying whether range should be selected or not.
03518     Outputs:    -
03519     Returns:    TRUE if the value specified by Index could be selected, FALSE otherwise
03520     Purpose:    For selecting the Value specified by Index in a list Gadget
03521 
03522                 For Windows
03523                 -----------
03524 
03525                 The function can be called on ListBox or cc_CheckList gadgets to set the
03526                 currently selected value
03527 
03528     Errors:     If the function is called on an invalid control then an ENSURE failure will
03529                 occur in a DEBUG build. In a retail build FALSE is returned.
03530 
03531     SeeAlso:    DialogOp::SetSelectedValueRange
03532 
03533 ********************************************************************************************/
03534 
03535 BOOL DialogManager::SetSelectedValueRange(CWindowID WindowID,
03536                                         CGadgetID Gadget,
03537                                         WORD StartIndex,
03538                                         WORD EndIndex,
03539                                         BOOL Selected)
03540 {
03541     INT32 i;
03542     for (i=StartIndex; i<=EndIndex; i++)
03543         SetBoolGadgetSelected(WindowID, Gadget, Selected, i);
03544     return (TRUE);
03545 }
03546 
03547 /********************************************************************************************
03548 
03549 >   BOOL DialogManager::SetDimensionGadgetValue(CWindowID WindowID,
03550                                                 CGadgetID Gadget,
03551                                                 MILLIPOINT Value,
03552                                                 Node* pNode,
03553                                                 BOOL IncludeUnitSpecifier = TRUE,
03554                                                 BOOL EndOfList = TRUE,
03555                                                 INT32 ListPos = 0)
03556 
03557     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03558     Created:    15/6/94
03559     Inputs:     WindowID:    Dialog box window identifier
03560                 Gadget:      Identifier of the gadget
03561                 Value:       The value to set the gadget to in MILLIPOINTS
03562                 pNode:       Ptr to the node from whence Value came from
03563                 IncludeUnitSpecifier :  If TRUE the unit specifier is included
03564                                         e.g. "1.27 cm" or "1.27" for TRUE or FALSE respectively
03565 
03566                 The following inputs only need to be provided if the gadget has multiple
03567                 values, for example a ListBox.
03568 
03569                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
03570                             value list. (Default = TRUE)
03571                             FALSE if the value is to be added to the ListPos position in the
03572                             list.
03573 
03574                 ListPos:     If EndOfList = FALSE then this input specifies the position
03575                             in the list (Default = 0, so if you want to add the value to
03576                             the top of the list simply specify EndOfList = FALSE)
03577 
03578                             If the gadget is a ComboBox then setting ListPos = -1 will
03579                             set the combo box's edit gadget field.
03580 
03581     Outputs:    -
03582     Returns:    TRUE if the gadgets value could be set as specified
03583                 FALSE if it could not.
03584 
03585     Purpose:    This is the routine to call for displaying a node's dimension
03586                 in a control.  It creates a string that represents 'Value' in the units
03587                 the user wants, possibly scaled up/down if the user has specified a
03588                 dimension scaling factor (e.g. 1 mile = 2 cm)
03589                 Once the string is created, SetStringGadgetValue is called on the control,
03590                 so you should be aware of this routine's features/limitations before calling
03591                 SetDimensionGadgetValue.
03592 
03593     Errors:     If the function is called on an invalid control then an ENSURE failure will
03594                 occur in a DEBUG build. In a retail build FALSE is returned.
03595 
03596     SeeAlso:    DialogOp::SetDimensionGadgetValue
03597     SeeAlso:    DialogManager::SetStringGadgetValue
03598 
03599 ********************************************************************************************/
03600 
03601 BOOL DialogManager::SetDimensionGadgetValue( CWindowID WindowID,
03602                                             CGadgetID Gadget,
03603                                             MILLIPOINT Value,
03604                                             Node* pNode,
03605                                             BOOL IncludeUnitSpecifier,
03606                                             BOOL EndOfList,
03607                                             INT32 ListPos)
03608 {
03609     DimScale           *pDimScale = DimScale::GetPtrDimScale(pNode);
03610     String_256          Str;
03611 
03612     pDimScale->ConvertToUnits( Value, &Str, IncludeUnitSpecifier );
03613     SetStringGadgetValue( WindowID, Gadget, Str, EndOfList, ListPos );
03614 
03615     return TRUE;
03616 }
03617 
03618 /********************************************************************************************
03619 
03620 >   BOOL DialogManager::SetMemoryGadgetValue( CWindowID WindowID,
03621                                             CGadgetID Gadget,
03622                                             UINT32 Value,
03623                                             BOOL EndOfList = TRUE,
03624                                             INT32 ListPos = 0)
03625 
03626     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
03627     Created:    30/1/95
03628     Inputs:     WindowID:    Dialog box window identifier
03629                 Gadget:      Identifier of the gadget
03630                 Value:       The value to set the gadget to in bytes.
03631 
03632                 The following inputs only need to be provided if the gadget has multiple
03633                 values, for example a ListBox.
03634 
03635                 EndOfList:   TRUE if the value is to be a added to the end of the gadgets
03636                             value list. (Default = TRUE)
03637                             FALSE if the value is to be added to the ListPos position in the
03638                             list.
03639 
03640                 ListPos:     If EndOfList = FALSE then this input specifies the position
03641                             in the list (Default = 0, so if you want to add the value to
03642                             the top of the list simply specify EndOfList = FALSE)
03643 
03644                             If the gadget is a ComboBox then setting ListPos = -1 will
03645                             set the combo box's edit gadget field.
03646 
03647     Outputs:    -
03648     Returns:    TRUE if the gadgets value could be set as specified
03649                 FALSE if it could not.
03650 
03651     Purpose:    This method is used to set a gadget which should display an amount of memory
03652                 being used or allocated. The value will be rounded to the nearest K or M or G
03653                 byte value. The actual type of the gadget does not matter.
03654 
03655                 For example:
03656 
03657                 If gadget g1 is a string then
03658 
03659                 SetMemoryGadgetValue(g1win, g1, 4*1024) will set g1's value to '4 Mbytes'
03660 
03661                 For Windows
03662                 -----------
03663 
03664                 The function can be used to set the string values of the following controls.
03665 
03666                 Edit
03667                 Static
03668                 Button
03669                 ListBox
03670                 ComboBox
03671 
03672     Errors:     If the function is called on an invalid control then an ENSURE failure will
03673                 occur in a DEBUG build. In a retail build FALSE is returned.
03674 
03675     SeeAlso:    DialogOp::SetMemoryGadgetValue; DialogOp::GetMemoryGadgetValue;
03676 
03677 ********************************************************************************************/
03678 
03679 BOOL DialogManager::SetMemoryGadgetValue( CWindowID WindowID,
03680                                         CGadgetID Gadget,
03681                                         UINT32 Value,
03682                                         BOOL EndOfList,
03683                                         INT32 ListPos)
03684 {
03685     String_256 StrValue;
03686     Convert::BytesToString(&StrValue, Value);
03687     return (SetStringGadgetValue(WindowID, Gadget, StrValue, EndOfList, ListPos));
03688 }
03689 
03690 
03691 /********************************************************************************************
03692 
03693 >   BOOL DialogManager::SetGadgetHelp( CWindowID WindowID,
03694                                     CGadgetID Gadget,
03695                                     UINT32 BubbleID,
03696                                     UINT32 StatusID,
03697                                     UINT32 ModuleID = 0)
03698 
03699     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
03700     Created:    21/4/95
03701     Inputs:     WindowID:    Dialog box window identifier
03702                 Gadget:      Identifier of the gadget
03703 
03704     Outputs:    -
03705     Returns:    TRUE if the gadgets value could be set as specified
03706                 FALSE if it could not.
03707 
03708     Purpose:    Allows the Bubble and Status ID's of a control to be changed at runtime.
03709 
03710     Errors:     Return FALSE if the Gadget could not be found.
03711 
03712     SeeAlso:    DialogOp::SetMemoryGadgetValue; DialogOp::GetMemoryGadgetValue;
03713 
03714 ********************************************************************************************/
03715 
03716 BOOL DialogManager::SetGadgetHelp( CWindowID WindowID,
03717                                 CGadgetID Gadget,
03718                                 UINT32 BubbleID,
03719                                 UINT32 StatusID,
03720                                 UINT32 ModuleID)
03721 {
03722     PORTNOTE("dialog","DialogManager::SetGadgetHelp - do nothing")
03723 #ifndef EXCLUDE_FROM_XARALX
03724     // Find the gadgets window
03725     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
03726 
03727     // Setup the Control help Info structure
03728     ControlHelpInfo Info;
03729     Info.BubbleID = BubbleID;
03730     Info.StatusID = StatusID;
03731     Info.ModuleID = ModuleID;
03732 
03733     // Tell the the control helper to update the ID's in it's table
03734     // We must also update any child window's entries.
03735     do
03736     {
03737         if (!ControlHelper::NotifyControlChanged(hGadget, &Info))
03738             return FALSE;
03739 
03740         hGadget = GetWindow(hGadget, GW_CHILD);
03741     }
03742     while (hGadget != NULL);
03743 #endif
03744     return TRUE;
03745 }
03746 
03747 
03748 //-------------------------------------------------------------------------------------------
03749 
03750 
03751 /********************************************************************************************
03752 
03753 >   MILLIPOINT DialogManager::GetUnitGadgetValue(CWindowID WindowID,
03754                                             CGadgetID Gadget,
03755                                             UnitType DefaultType,
03756                                             MILLIPOINT StartRange,
03757                                             MILLIPOINT EndRange,
03758                                             UINT32 IDSInvalidMsg,
03759                                             BOOL* Valid)
03760 
03761     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
03762     Created:    17/8/93
03763     Inputs:     WindowID:       Dialog box window identifier
03764                 Gadget:     Dialog identifier
03765                 TheType:        The type of the gadgets value
03766                 StartRange:     Minimum gadget value
03767                 EndRange:       Maximum gadget value
03768                 InvalidMsgID:   Message displayed to the user when they have entered
03769                                 invalid data (either not the correct type or not in the
03770                                 correct range)
03771                                 This may be 0 if you do not wish an error to be reported
03772 
03773     Outputs:    Valid:          Flag indicating if the value entered was valid or not.
03774                                 If the Valid parameter is NULL, then validity of the result
03775                                 will not be checked, and the actual value of the control
03776                                 will be returned even if it was out of range.
03777                                 If this flag is returned FALSE then the return value will be 0.
03778 
03779     Returns:    The value entered by the user in MILLIPOINTS. If Valid is FALSE then
03780                 NULL will be returned.
03781 
03782     Purpose:    This function will obtain the gadget value and validate it. Validation will
03783                 check that data has been entered in a correct unit type, and that it is
03784                 in the range StartRange..EndRange. If the user enters an incorrect value
03785                 the InvalidMsgID string will be displayed to the user in a dialog
03786                 box, and Valid will have a FALSE value.
03787 
03788                 For Windows
03789                 -----------
03790 
03791                 The function can be used to obtain a unit value from the string value of the
03792                 following controls:
03793 
03794                 Edit
03795                 ListBox
03796                 ComboBox
03797                 Static
03798 
03799                 For ListBox and ComboBox controls the unit value of the currently selected
03800                 listitem is returned. This function would normally be called in response to a
03801                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
03802 
03803     Errors:     If the function is called on an invalid control then an ENSURE failure will
03804                 occur in a DEBUG build. In a retail build FALSE is returned.
03805 
03806     SeeAlso:    DialogOp::GetUnitGadgetValue
03807 
03808 ********************************************************************************************/
03809 
03810 MILLIPOINT DialogManager::GetUnitGadgetValue(CWindowID WindowID,
03811                                         CGadgetID Gadget,
03812                                         UnitType DefaultType,
03813                                         MILLIPOINT StartRange,
03814                                         MILLIPOINT EndRange,
03815                                         UINT32 IDSInvalidMsg,
03816                                         BOOL* Valid)
03817 {
03818     MILLIPOINT          Value = 0;    // The return value
03819 
03820     BOOL IsValid;
03821 
03822     // Obtain the controls text
03823     String_256 StrValue = GetStringGadgetValue(WindowID, Gadget, NULL);
03824 
03825     // Convert the string to millipoints if it's valid
03826     Value = Convert::StringToMillipoints(StrValue, DefaultType, &IsValid);
03827 
03828     if (Valid == NULL)      // If don't want it validated, return the value now
03829         return(Value);
03830 
03831     if (IsValid)
03832     {
03833         // Check that the value is in the range StartRange..EndRange
03834         if ((Value >= StartRange) && (Value <= EndRange))
03835         {
03836             *Valid = TRUE;
03837             return (Value); // A correct value was entered
03838         }
03839     }
03840 
03841     // The value is invalid
03842     if (IDSInvalidMsg != 0)
03843         InformWarning(IDSInvalidMsg); // Scold the user, if a message was supplied
03844 
03845     return( 0 );
03846 }
03847 
03848 /********************************************************************************************
03849 
03850 >   INT32 DialogManager::GetLongGadgetValue(CWindowID WindowID,
03851                                         CGadgetID Gadget,
03852                                         INT32 StartRange,
03853                                         INT32 EndRange,
03854                                         UINT32 IDSInvalidMsg,
03855                                         BOOL* Valid,
03856                                         DialogManager::PFNSTRINGTOINT32 pfnParser = ::StringToLong)
03857 
03858     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
03859     Created:    1/9/93
03860 
03861     Inputs:     WindowID:       Dialog box window identifier
03862                 Gadget:     Dialog identifier
03863                 StartRange:     Minimum gadget value
03864                 EndRange:       Maximum gadget value
03865                 InvalidMsgID:   Message displayed to the user when they have entered
03866                                 invalid data (either not the correct type or not in the
03867                                 correct range)
03868                                 This may be 0 if you do not wish an error to be reported
03869                 pfnParser       optional pointer to a function that converts a StringBase
03870                                 to a INT32.  The default is:-
03871                                     BOOL ::StringToLong(StringBase* in, INT32* out)
03872                                 but any function with a similar prototype will work.
03873                                 This function is called for controls that contain text,
03874                                 eg. a combo-box.  Ask JustinF about this if you aren't
03875                                 sure.
03876 
03877     Outputs:    Valid:          Flag indicating if the value entered was valid or not.
03878                                 If the Valid parameter is NULL, then validity of the result
03879                                 will not be checked, and the actual value of the control
03880                                 will be returned even if it was out of range.
03881                                 If this flag is returned FALSE then the return value will be 0.
03882 
03883     Returns:    The value entered by the user. If Valid is FALSE then
03884                 NULL will be returned.
03885 
03886     Purpose:    This function will obtain the gadget value and validate it. Validation will
03887                 check that a correct INT32 value has been entered, and that it is
03888                 in the range StartRange..EndRange. If the user enters an incorrect value
03889                 the InvalidMsgID string will be displayed to the user in a dialog
03890                 box, and Valid will have a FALSE value.
03891 
03892                 For Windows
03893                 -----------
03894 
03895                 The function can be used to obtain a INT32 value from the string value of the
03896                 following controls:
03897 
03898                 Edit
03899                 ListBox
03900                 ComboBox
03901                 Static
03902                 cc_CheckList
03903                 Button
03904 
03905                 For ListBox and ComboBox controls the INT32 value of the currently selected
03906                 listitem is returned. This function would normally be called in response to a
03907                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
03908 
03909                 You can override the conversion from the string value to the INT32 by
03910                 providing your own pfnParser parameter.   This could, for example,
03911                 remove percentage signs from the text before conversion.
03912 
03913                 For Button controls this function returns back the current state of the button
03914 
03915                 For ScrollBar controls this function returns back the current position of
03916                 the scroll bars thumb.
03917 
03918                 For cc_Slider controls this function returns the current position of the
03919                 bar in the slider.
03920 
03921     Errors:     If the function is called on an invalid control then an ENSURE failure will
03922                 occur in a DEBUG build. In a retail build FALSE is returned.
03923 
03924     SeeAlso:    DialogOp::GetLongGadgetValue
03925 
03926 ********************************************************************************************/
03927 
03928 INT32 DialogManager::GetLongGadgetValue(CWindowID WindowID,
03929                                     CGadgetID Gadget,
03930                                     INT32 StartRange,
03931                                     INT32 EndRange,
03932                                     UINT32 IDSInvalidMsg,
03933                                     BOOL* Valid,
03934                                     Convert::PFNSTRINGTOINT32 pfnParser)
03935 {
03936     wxWindow * pGadget = GetGadget(WindowID, Gadget);
03937     if (!pGadget) return FALSE;
03938 
03939     if ( pGadget->IsKindOf(CLASSINFO(wxButton)) ||
03940         pGadget->IsKindOf(CLASSINFO(wxBitmapButton)) )
03941     {
03942         // These bitmap buttons are meant to be tristate
03943         PORTNOTETRACE("dialog","DialogManager::GetLongGadgetValue on BitmapButton - do nothing");
03944         return 0;
03945     }
03946 
03947     if ( pGadget->IsKindOf(CLASSINFO(wxCheckBox)) )
03948     {
03949         if (Valid) *Valid=TRUE;
03950         return ((wxCheckBox *)(pGadget))->GetValue() != 0;
03951     }
03952 
03953     if ( pGadget->IsKindOf(CLASSINFO(wxRadioButton)) )
03954     {
03955         if (Valid) *Valid=TRUE;
03956         return ((wxRadioButton *)(pGadget))->GetValue() != 0;
03957     }
03958 
03959     if ( pGadget->IsKindOf(CLASSINFO(wxScrollBar)) )
03960     {
03961         if (Valid) *Valid=TRUE;
03962         return (INT32)(((wxScrollBar *)(pGadget))->GetThumbPosition());
03963     }
03964 
03965     if ( pGadget->IsKindOf(CLASSINFO(wxSlider)) )
03966     {
03967         if (Valid) *Valid=TRUE;
03968         return (INT32)(((wxSlider *)(pGadget))->GetValue());
03969     }
03970 
03971     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
03972     {
03973         if (Valid) *Valid=TRUE;
03974         return (INT32)(((wxSliderCombo *)(pGadget))->GetSliderValue());
03975     }
03976 
03977     if ( pGadget->IsKindOf(CLASSINFO(wxGauge)) )
03978     {
03979         if (Valid) *Valid=TRUE;
03980         return (INT32)(((wxGauge *)(pGadget))->GetValue());
03981     }
03982 
03983     if ( pGadget->IsKindOf(CLASSINFO(wxCamArtControl)) )
03984     {
03985         if (Valid) *Valid=TRUE;
03986         return (INT32)(((wxCamArtControl *)(pGadget))->GetValue());
03987     }
03988 
03989 #if 0
03990     // it seems on an edit box we might be meant to set the garet, but it's difficult to know what's
03991     // going on here
03992     else if (ClassNameStr == String_16(TEXT("cc_CustomEdit")))//?
03993     {
03994         CCustomEdit* pCEdit = (CCustomEdit*)CWnd::FromHandlePermanent(hGadget);
03995         Value = pCEdit->GetPos();
03996         IsValid = ((Value >= StartRange) && (Value <= EndRange));
03997         TRACEUSER( "Marc", _T("dlgmgr.cpp, getting pos %d\n"),Value);
03998     }
03999 #endif
04000 
04001     // Hmmm - no luck so far, let's try a string
04002 
04003     // Obtain the controls text
04004     String_256 StrValue = GetStringGadgetValue(WindowID, Gadget, NULL);
04005 
04006     // Convert the string to an INT32 if it's valid
04007     INT32 Value=0;
04008     BOOL IsValid = (*pfnParser)(StrValue, &Value);
04009     if (IsValid)
04010     {
04011         IsValid = ((Value >= StartRange) && (Value <= EndRange));
04012     }
04013 
04014     if (Valid != NULL)
04015     {
04016         *Valid = IsValid;
04017 
04018         if (!IsValid)   // The value is invalid
04019         {
04020             if (IDSInvalidMsg != 0)
04021                 InformWarning(IDSInvalidMsg); // Scold the user, if a message was supplied
04022             return (0);
04023         }
04024     }
04025 
04026     return Value; // Valid input, or caller did not want validation
04027 }
04028 
04029 
04030 /********************************************************************************************
04031 
04032 >   double DialogManager::GetDoubleGadgetValue(CWindowID WindowID,
04033                                         CGadgetID Gadget,
04034                                         double StartRange,
04035                                         double EndRange,
04036                                         UINT32 IDSInvalidMsg,
04037                                         BOOL* Valid,
04038                                         DialogManager::PFNSTRINGTODOUBLE pfnParser = ::StringToDouble)
04039 
04040     Author:     Alex_Bligh (Xara Group Ltd) <camelotdev@xara.com> (liberally copied from GetLongGadgetValue)
04041     Created:    16/12/94
04042 
04043     Inputs:     WindowID:       Dialog box window identifier
04044                 Gadget:     Dialog identifier
04045                 StartRange:     Minimum gadget value
04046                 EndRange:       Maximum gadget value
04047                 InvalidMsgID:   Message displayed to the user when they have entered
04048                                 invalid data (either not the correct type or not in the
04049                                 correct range)
04050                                 This may be 0 if you do not wish an error to be reported
04051                 pfnParser       optional pointer to a function that converts a StringBase
04052                                 to a double.  The default is:-
04053                                     double ::StringToDouble(StringBase* in, Double* out)
04054                                 but any function with a similar prototype will work.
04055                                 This function is called for controls that contain text,
04056                                 eg. a combo-box.  Ask JustinF about this if you aren't
04057                                 sure.
04058 
04059     Outputs:    Valid:          Flag indicating if the value entered was valid or not.
04060                                 If the Valid parameter is NULL, then validity of the result
04061                                 will not be checked, and the actual value of the control
04062                                 will be returned even if it was out of range.
04063                                 If this flag is returned FALSE then the return value will be 0.
04064 
04065     Returns:    The value entered by the user. If Valid is FALSE then
04066                 NULL will be returned.
04067 
04068     Purpose:    This function will obtain the gadget value and validate it. Validation will
04069                 check that a correct double value has been entered, and that it is
04070                 in the range StartRange..EndRange. If the user enters an incorrect value
04071                 the InvalidMsgID string will be displayed to the user in a dialog
04072                 box, and Valid will have a FALSE value.
04073 
04074                 For Windows
04075                 -----------
04076 
04077                 The function can be used to obtain a double value from the string value of the
04078                 following controls:
04079 
04080                 Edit
04081                 ListBox
04082                 ComboBox
04083                 Static
04084                 cc_CheckList
04085                 Button
04086 
04087                 For ListBox and ComboBox controls the INT32 value of the currently selected
04088                 listitem is returned. This function would normally be called in response to a
04089                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
04090 
04091                 You can override the conversion from the string value to the double by
04092                 providing your own pfnParser parameter.   This could, for example,
04093                 remove percentage signs from the text before conversion.
04094 
04095                 For Button controls this function returns back the current state of the button
04096 
04097                 For ScrollBar controls this function returns back the current position of
04098                 the scroll bars thumb.
04099 
04100                 For cc_Slider controls this function returns the current position of the
04101                 bar in the slider.
04102 
04103                 Note for some controls, like sliders, the value comes back as an INT32 converted
04104                 to a double so you might as well use GetLongGadgetValue.
04105 
04106     Errors:     If the function is called on an invalid control then an ENSURE failure will
04107                 occur in a DEBUG build. In a retail build FALSE is returned.
04108 
04109     SeeAlso:    DialogOp::GetDoubleGadgetValue, DialogManager::GetLongGadgetValue
04110 
04111 ********************************************************************************************/
04112 
04113 double DialogManager::GetDoubleGadgetValue(CWindowID WindowID,
04114                                     CGadgetID Gadget,
04115                                     double StartRange,
04116                                     double EndRange,
04117                                     UINT32 IDSInvalidMsg,
04118                                     BOOL* Valid,
04119                                     Convert::PFNSTRINGTODOUBLE pfnParser)
04120 {
04121     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04122     if (!pGadget) return FALSE;
04123 
04124     if (( pGadget->IsKindOf(CLASSINFO(wxButton))) ||
04125         ( pGadget->IsKindOf(CLASSINFO(wxBitmapButton))) ||
04126         ( pGadget->IsKindOf(CLASSINFO(wxCheckBox))) ||
04127         ( pGadget->IsKindOf(CLASSINFO(wxRadioButton))) ||
04128         ( pGadget->IsKindOf(CLASSINFO(wxScrollBar))) ||
04129         ( pGadget->IsKindOf(CLASSINFO(wxSlider))) ||
04130         ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo))) ||
04131         ( pGadget->IsKindOf(CLASSINFO(wxGauge)))
04132         )
04133         return (double)GetLongGadgetValue( WindowID, Gadget, (INT32)(floor(StartRange+0.5)), (INT32)(floor(EndRange+0.5)), IDSInvalidMsg, Valid);
04134 
04135     String_256 StrValue = GetStringGadgetValue(WindowID, Gadget, NULL);
04136 
04137     // Convert the string to an INT32 if it's valid
04138     double Value=0.0;
04139     BOOL IsValid = (*pfnParser)(StrValue, &Value);
04140     if (IsValid)
04141     {
04142         IsValid = ((Value >= StartRange) && (Value <= EndRange));
04143     }
04144 
04145     if (Valid != NULL)
04146     {
04147         *Valid = IsValid;
04148 
04149         if (!IsValid)   // The value is invalid
04150         {
04151             if (IDSInvalidMsg != 0)
04152                 InformWarning(IDSInvalidMsg); // Scold the user, if a message was supplied
04153             return (0);
04154         }
04155     }
04156 
04157     return Value; // Valid input, or caller did not want validation
04158 }
04159 
04160 /********************************************************************************************
04161 
04162 >   BOOL DialogManager::GetBoolGadgetSelected(CWindowID WindowID,
04163                                             CGadgetID Gadget,
04164                                             UINT32 IDSInvalidMsg = 0,
04165                                             BOOL* Valid = NULL,
04166                                             INT32 ListPos = 0)
04167 
04168     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
04169     Created:    10/4/94
04170 
04171     Inputs:     WindowID:       Dialog box window identifier
04172                 Gadget:     Dialog identifier
04173                 InvalidMsgID:   Message displayed to the user when they have entered
04174                                 invalid data (either not the correct type or not in the
04175                                 correct range)
04176                                 This may be 0 if you do not wish an error to be reported
04177                 ListPos:        Specifies which item in a list to read (defaults to 0)
04178 
04179     Outputs:    Valid:          Flag indicating if the value entered was valid or not.
04180                                 If the Valid parameter is NULL, then validity of the result
04181                                 will not be checked, and the actual value of the control
04182                                 will be returned even if it was "invalid".
04183                                 If this flag is returned FALSE then the return value will be 0.
04184 
04185     Returns:    The value entered by the user. If Valid is FALSE then
04186                 FALSE will be returned.
04187 
04188     Purpose:    This function will obtain the gadget value and validate it. Validation will
04189                 check that a correct INT32 value has been entered, and that it is
04190                 in the range StartRange..EndRange. If the user enters an incorrect value
04191                 the InvalidMsgID string will be displayed to the user in a dialog
04192                 box, and Valid will have a FALSE value. [This does not seem correct - AMB]
04193 
04194                 For Windows
04195                 -----------
04196 
04197                 The function can be used to obtain a BOOL value from the
04198                 following controls:
04199 
04200                 Button
04201                 ListBox
04202                 cc_CheckList
04203 
04204                 For ListBox/cc_CheckList controls the bool value of the currently selected
04205                 listitem is returned. This function would normally be called in response to a
04206                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
04207 
04208     Errors:     If the function is called on an invalid control then an ENSURE failure will
04209                 occur in a DEBUG build. In a retail build FALSE is returned.
04210 
04211     SeeAlso:    DialogOp::GetLongGadgetValue
04212 
04213 ********************************************************************************************/
04214 
04215 BOOL DialogManager::GetBoolGadgetSelected(CWindowID WindowID,
04216                                             CGadgetID Gadget,
04217                                             UINT32 IDSInvalidMsg,
04218                                             BOOL* Valid,
04219                                             INT32 ListPos)
04220 {
04221     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04222     if (!pGadget) return FALSE;
04223 
04224     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04225         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04226         pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ||
04227         pGadget->IsKindOf(CLASSINFO(wxChoice)) )
04228     {
04229         // Support listboxes with multiple selections
04230         if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
04231         {
04232             return ((wxListBox *)pGadget)->IsSelected(ListPos);
04233         }
04234         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04235             return (((wxOwnerDrawnComboBox *)pGadget)->GetSelection() == ListPos);
04236         else
04237             return (((wxControlWithItems *)pGadget)->GetSelection() == ListPos);
04238     }
04239 
04240     return GetLongGadgetValue(WindowID, Gadget, 0, 1, IDSInvalidMsg, Valid);
04241 }
04242 
04243 
04244 
04245 
04246 
04247 /********************************************************************************************
04248 
04249 >   String_256 DialogManager::GetStringGadgetValue(CWindowID WindowID,
04250                                                 CGadgetID Gadget,
04251                                                 BOOL* Valid,
04252                                                 INT32 ListPos = -1)
04253 
04254     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
04255     Created:    2/9/93
04256     Inputs:     WindowID:       Dialog box window identifier
04257                 Gadget:     Gadget identifier
04258                 ListPos:        Index into list if needed (defaults to -1 to mean read
04259                                 the text of the selected item. In the case of a combo
04260                                 this is the text in the editable field - which may be
04261                                 a value which does not exist in the combo's list.
04262 
04263     Outputs:    Valid:          Flag indicating if the string could be read or not
04264                                 You may pass NULL if you don't care about the validity
04265                                 (if invalid, the returned string will be a NULL string)
04266 
04267     Returns:    The gadgets string value if Valid is TRUE, else a NULL string
04268 
04269     Purpose:    For finding a gadgets string value. This function can only be used for
04270                 gadgets with a text value.
04271 
04272                 For Windows
04273                 -----------
04274 
04275                 This function returns the string value for the following controls
04276 
04277                 Edit
04278                 ListBox
04279                 ComboBox
04280                 Static
04281                 Button
04282 
04283                 For ListBox and ComboBox controls the string value of the currently selected
04284                 listitem is returned. This function would normally be called in response to a
04285                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
04286 
04287     Errors:     If the function is called on an invalid control then an ENSURE failure will
04288                 occur in a DEBUG build. In a retail build FALSE is returned.
04289 
04290     SeeAlso:    DialogOp::GetStringGadgetValue
04291 
04292 ********************************************************************************************/
04293 
04294 String_256 DialogManager::GetStringGadgetValue(CWindowID WindowID,
04295                                             CGadgetID Gadget,
04296                                             BOOL* Valid,
04297                                             INT32 ListPos)
04298 {
04299     if (Valid)
04300         *Valid = TRUE;
04301     String_256 StrVal;
04302 
04303     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04304     wxString String;
04305 
04306     if (!pGadget) goto invalid;
04307 
04308 //  if ( pGadget->IsKindOf(CLASSINFO(wxControlWithItems)) ) // Includes wxListBox - this seems to have false positives
04309     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04310         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04311         pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ||
04312         pGadget->IsKindOf(CLASSINFO(wxChoice)) )
04313     {
04314         if (ListPos >=0)
04315         {
04316             if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04317             {
04318                 if (ListPos>=(INT32)((wxOwnerDrawnComboBox *)pGadget)->GetCount()) goto invalid;
04319                 String = ((wxOwnerDrawnComboBox *)pGadget)->GetString(ListPos);
04320             }
04321             else
04322             {
04323                 if (ListPos>=(INT32)((wxControlWithItems *)pGadget)->GetCount()) goto invalid;
04324                 String = ((wxControlWithItems *)pGadget)->GetString(ListPos);
04325             }
04326             goto out;
04327         }
04328 
04329         if (pGadget->IsKindOf(CLASSINFO(wxComboBox)))
04330         {
04331             String = ((wxComboBox *)pGadget)->GetValue();
04332             goto out;
04333         }
04334 
04335         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04336         {
04337             String = ((wxOwnerDrawnComboBox *)pGadget)->GetValue();
04338             goto out;
04339         }
04340 
04341         INT32 sel;
04342         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04343             sel = ((wxOwnerDrawnComboBox *)pGadget)->GetSelection();
04344         else
04345             sel = ((wxControlWithItems *)pGadget)->GetSelection();
04346 
04347         if ( (sel == wxNOT_FOUND) || (sel < 0)) goto invalid;
04348 
04349         if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04350             String = ((wxOwnerDrawnComboBox *)pGadget)->GetString(sel);
04351         else
04352             String = ((wxControlWithItems *)pGadget)->GetString(sel);
04353 
04354         goto out;
04355     }
04356 
04357     if ( pGadget->IsKindOf(CLASSINFO(wxTextCtrl)) )
04358     {
04359         String = ((wxTextCtrl *)pGadget)->GetValue();
04360         goto out;
04361     }
04362 
04363     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
04364     {
04365         String = ((wxSliderCombo *)pGadget)->GetValue();
04366         goto out;
04367     }
04368 
04369     String = pGadget->GetLabel();
04370 
04371 out:
04372     StrVal = String.c_str();
04373     return StrVal;
04374 
04375 invalid:
04376     if (Valid)
04377         *Valid=FALSE;
04378     return StrVal;
04379 }
04380 
04381 /********************************************************************************************
04382 
04383 >   BOOL DialogManager::GetGadgetRange(CWindowID WindowID,
04384                                     CGadgetID Gadget,
04385                                     INT32* Min,
04386                                     INT32* Max)
04387 
04388     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
04389     Created:    2/9/93
04390     Inputs:     WindowID:       Dialog box window identifier
04391                 Gadget:     Gadget identifier
04392     Outputs:    Min:            Minimum range value
04393                 Max:            Maximum range value
04394 
04395     Returns:    TRUE if the gadget's range could be read, FALSE otherwise
04396 
04397     Purpose:    For obtaining the range of a gadget.
04398 
04399                 For Windows
04400                 -----------
04401 
04402                 The function returns a ScrollBar control's Min and Max values.
04403 
04404     Errors:     If the function is called on an invalid control then an ENSURE failure will
04405                 occur in a DEBUG build. In a retail build FALSE is returned.
04406 
04407     SeeAlso:    DialogOp::GetGadgetRange
04408 
04409 ********************************************************************************************/
04410 
04411 
04412 BOOL DialogManager::GetGadgetRange(CWindowID WindowID,
04413                                 CGadgetID Gadget,
04414                                 INT32* Min,
04415                                 INT32* Max)
04416 {
04417     INT32 min=0;
04418     INT32 max=0;
04419 
04420     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04421     if (!pGadget) return FALSE;
04422 
04423     if ( pGadget->IsKindOf(CLASSINFO(wxScrollBar)) )
04424     {
04425         max = ((wxScrollBar *)pGadget)->GetRange();
04426     }
04427 
04428     if ( pGadget->IsKindOf(CLASSINFO(wxSlider)) )
04429     {
04430         min=((wxSlider *)(pGadget))->GetMin();
04431         max=((wxSlider *)(pGadget))->GetMax();
04432     }
04433 
04434     if ( pGadget->IsKindOf(CLASSINFO(wxSliderCombo)) )
04435     {
04436         min=((wxSliderCombo *)(pGadget))->GetSliderMin();
04437         max=((wxSliderCombo *)(pGadget))->GetSliderMax();
04438     }
04439 
04440     if ( pGadget->IsKindOf(CLASSINFO(wxGauge)) )
04441     {
04442         max = ((wxGauge *)(pGadget))->GetRange();
04443     }
04444 
04445     if (Min) *Min=min;
04446     if (Max) *Max=max;
04447 
04448     return TRUE;
04449 }
04450 
04451 
04452 /********************************************************************************************
04453 
04454 >   MILLIPOINT DialogManager::GetDimensionGadgetValue(  CWindowID WindowID,
04455                                                         CGadgetID Gadget,
04456                                                         Node* pNode,
04457                                                         BOOL* Valid)
04458                                                         INT32 ListPos = -1)
04459     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04460     Created:    15/6/94
04461     Inputs:     WindowID:    Dialog box window identifier
04462                 Gadget:      Identifier of the gadget
04463                 pNode:       The node the dimenstion is for
04464     Outputs:    Valid - TRUE if a valid dimension has been read from the control
04465                 Valid may be a NULL pointer if you are uninterested in the result
04466 
04467     Returns:    The internal millipoint representation of the string in this control
04468     Purpose:    This is the routine to call for getting user-entered dimensions from
04469                 a control.  The value is scaled from user dimensions to an internal millipoint
04470                 value.
04471                 The routine uses DialogManager::GetStringGadgetValue to extract the string from
04472                 the control.  The caller should be aware of the features/limitations of this routine
04473                 before calling GetDimensionGadgetValue.
04474 
04475     Errors:     If the function is called on an invalid control then an ENSURE failure will
04476                 occur in a DEBUG build. In a retail build FALSE is returned.
04477 
04478     SeeAlso:    DialogOp::GetDimensionGadgetValue
04479     SeeAlso:    DialogManager::GetStringGadgetValue
04480 
04481 ********************************************************************************************/
04482 
04483 MILLIPOINT DialogManager::GetDimensionGadgetValue(  CWindowID WindowID,
04484                                                     CGadgetID Gadget,
04485                                                     Node* pNode,
04486                                                     BOOL* Valid,
04487                                                     INT32 ListPos)
04488 {
04489     MILLIPOINT Val=72000;
04490     DimScale* pDimScale = DimScale::GetPtrDimScale(pNode);
04491     String_256 Str;
04492 
04493     Str = GetStringGadgetValue(WindowID,Gadget,Valid,ListPos);
04494     if (Valid != NULL && *Valid)
04495         *Valid = pDimScale->ConvertToMillipoints(Str,&Val);
04496     return Val;
04497 }
04498 
04499 
04500 /********************************************************************************************
04501 BOOL DialogManager::GetDoubleAndUnitGadgetValue(double*   pMPValue,
04502                                                 double*   pUnitValue,
04503                                                 UnitType* pUnitType,
04504                                                 CWindowID WindowID,
04505                                                 CGadgetID Gadget,
04506                                                 Node*     pNode)
04507     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
04508     Created:    13/9/95
04509     Inputs:     WindowID   -
04510                 Gadget   -
04511                 pNode      - node from which to determine default units (ie page units)
04512     Outputs:    pMPValue   - value of gadget converted to millipoints (accounting for scaling)
04513                 pUnitValue - value of gadget in terms of units output in pUnitType
04514                 pUnitType  - type of unit the value was specified in (or page units if none)
04515     Returns:    FALSE if fails
04516     Purpose:    Read the value from a gadget as a double millipont values accounting for unit scaling
04517                 ALSO read the type of unit specified and the gadget value in terms of these units
04518                 ie 0.5m would return 36000.0, 0.5 and METERS (assuming scaling 1m->1in)
04519 ********************************************************************************************/
04520 
04521 BOOL DialogManager::GetDoubleAndUnitGadgetValue(double*   pMPValue,
04522                                                 double*   pUnitValue,
04523                                                 UnitType* pUnitType,
04524                                                 CWindowID WindowID,
04525                                                 CGadgetID Gadget,
04526                                                 Node*     pNode)
04527 {
04528     ERROR2IF(  pMPValue==NULL,FALSE,"DialogManager::GetDoubleAndUnitGadgetValue() - pMPValue==NULL");
04529     ERROR2IF(pUnitValue==NULL,FALSE,"DialogManager::GetDoubleAndUnitGadgetValue() - pUnitValue==NULL");
04530     ERROR2IF( pUnitType==NULL,FALSE,"DialogManager::GetDoubleAndUnitGadgetValue() - pUnitType==NULL");
04531     ERROR2IF(     pNode==NULL,FALSE,"DialogManager::GetDoubleAndUnitGadgetValue() - pNode==NULL");
04532     DimScale* pDimScale = DimScale::GetPtrDimScale(pNode);
04533     ERROR2IF( pDimScale==NULL,FALSE,"DialogManager::GetDoubleAndUnitGadgetValue() - pDimScale==NULL");
04534 
04535     // separate string into double value and unit type
04536     BOOL     ok         = TRUE;
04537     double   UnitValue  = 1.0;
04538     UnitType units;
04539     String_256 GadgetString=GetStringGadgetValue(WindowID,Gadget,&ok);
04540     if (ok) ok=Convert::StringToComponents(GadgetString, &UnitValue, &units);
04541     if (!ok) return FALSE;
04542 
04543     // if no unit type specified, use units associated with the specified node
04544     if (units==NOTYPE)
04545         units=pDimScale->GetUnits();
04546 
04547     // and get the value in millipoints accounting for scaled units
04548     double MPValue = 1.0;
04549     ok=pDimScale->ConvertToDouble(GadgetString,&MPValue);
04550     if (!ok) return FALSE;
04551 
04552     // set outputs and return
04553     *pMPValue   = MPValue;
04554     *pUnitValue = UnitValue;
04555     *pUnitType  = units;
04556 
04557     return TRUE;
04558 }
04559 
04560 
04561 /********************************************************************************************
04562 
04563 >   UINT32 DialogManager::GetMemoryGadgetValue(CWindowID WindowID,
04564                                             CGadgetID Gadget,
04565                                             UINT32 StartRange,
04566                                             UINT32 EndRange,
04567                                             UINT32 IDSInvalidMsg,
04568                                             BOOL* Valid)
04569 
04570     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04571     Created:    30/1/95
04572     Inputs:     WindowID:       Dialog box window identifier
04573                 Gadget:     Dialog identifier
04574                 StartRange:     Minimum gadget value
04575                 EndRange:       Maximum gadget value
04576                 InvalidMsgID:   Message displayed to the user when they have entered
04577                                 invalid data (either not the correct type or not in the
04578                                 correct range)
04579                                 This may be 0 if you do not wish an error to be reported
04580 
04581     Outputs:    Valid:          Flag indicating if the value entered was valid or not.
04582                                 If the Valid parameter is NULL, then validity of the result
04583                                 will not be checked, and the actual value of the control
04584                                 will be returned even if it was out of range.
04585                                 If this flag is returned FALSE then the return value will be 0.
04586 
04587     Returns:    The value entered by the user in bytes. If Valid is FALSE then
04588                 NULL will be returned.
04589 
04590     Purpose:    This function allows a memory value to be read back from a control. It will
04591                 cope with the memory being specified in bytes, K, M or G bytes and will also
04592                 validate it. Validation will check that data has been entered in a correct unit
04593                 type, and that it is in the range StartRange..EndRange. If the user enters an
04594                 incorrect value the InvalidMsgID string will be displayed to the user in a
04595                 dialog box, and Valid will have a FALSE value.
04596 
04597                 For Windows
04598                 -----------
04599 
04600                 The function can be used to obtain a memory value from the string value of the
04601                 following controls:
04602 
04603                 Edit
04604                 ListBox
04605                 ComboBox
04606                 Static
04607 
04608                 For ListBox and ComboBox controls the unit value of the currently selected
04609                 listitem is returned. This function would normally be called in response to a
04610                 DIM_SELECTION_CHANGED or DIM_SELECTION_CHANGED_COMMIT message.
04611 
04612     Errors:     If the function is called on an invalid control then an ENSURE failure will
04613                 occur in a DEBUG build. In a retail build FALSE is returned.
04614 
04615     SeeAlso:    DialogOp::GetMemoryGadgetValue; DialogOp::SetMemoryGadgetValue
04616 
04617 ********************************************************************************************/
04618 
04619 UINT32 DialogManager::GetMemoryGadgetValue(CWindowID WindowID,
04620                                         CGadgetID Gadget,
04621                                         UINT32 StartRange,
04622                                         UINT32 EndRange,
04623                                         UINT32 IDSInvalidMsg,
04624                                         BOOL* Valid)
04625 {
04626     BOOL IsValid;
04627 
04628     // Obtain the controls text
04629     String_256 StrValue = GetStringGadgetValue(WindowID, Gadget, NULL);
04630 
04631     // Convert the string to millipoints if it's valid
04632     UINT32 Value = Convert::StringToBytes(StrValue, &IsValid);
04633 
04634     if (Valid == NULL)      // If don't want it validated, return the value now
04635         return(Value);
04636 
04637     if (IsValid)
04638     {
04639         // Check that the value is in the range StartRange..EndRange
04640         if ((Value >= StartRange) && (Value <= EndRange))
04641         {
04642             *Valid = TRUE;
04643             return (Value); // A correct value was entered
04644         }
04645     }
04646 
04647     // The value is invalid
04648     if (IDSInvalidMsg != 0)
04649         InformWarning(IDSInvalidMsg); // Scold the user, if a message was supplied
04650 
04651     return( 0 );
04652 }
04653 
04654 //-------------------------------------------------------------------------------------------
04655 
04656 /********************************************************************************************
04657 
04658 >   BOOL DialogManager::DeleteAllValues(CWindowID WindowID, CGadgetID Gadget)
04659 
04660     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04661     Created:    13/5/94
04662     Inputs:     WindowID:       Dialog box window identifier
04663                 Gadget:     Gadget identifier
04664 
04665     Returns:    TRUE if the values could be deleted, else FALSE.
04666     Purpose:    For deleting all values in a list-gadget
04667 
04668                 For Windows
04669                 -----------
04670 
04671                 This function can be used to delete list items from ComboBox, ListBox,
04672                 or cc_ListBox controls. ALL items in the given Gadget will be deleted
04673                 (i.e. it resets the list to containing no items at all. This is equivalent
04674                 to calling DeleteValue for each list item in turn)
04675 
04676     Errors:     If the function is called on an invalid control then an ENSURE failure will
04677                 occur in a DEBUG build. In a retail build FALSE is returned.
04678 
04679     SeeAlso:    DialogOp::DeleteAllValues; DialogManager::DeleteValue
04680 
04681 ********************************************************************************************/
04682 
04683 BOOL DialogManager::DeleteAllValues(CWindowID WindowID, CGadgetID Gadget)
04684 {
04685     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04686     if (!pGadget) return FALSE;
04687 
04688     //if ( pGadget->IsKindOf(CLASSINFO(wxControlWithItems)) ) // Includes wxListBox - this seems to have false positives
04689     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04690         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04691         pGadget->IsKindOf(CLASSINFO(wxChoice))
04692         )
04693     {
04694         ((wxControlWithItems *)pGadget)->Clear();
04695         return TRUE;
04696     }
04697     else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04698     {
04699         ((wxOwnerDrawnComboBox *)pGadget)->Clear();
04700         return TRUE;
04701     }
04702     else if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
04703         )
04704     {
04705         ((wxTreeCtrl*)pGadget)->DeleteAllItems();
04706         return TRUE;
04707     }
04708 
04709     ERROR3("Invalid control");
04710     return FALSE;
04711 }
04712 
04713 
04714 
04715 /********************************************************************************************
04716 
04717 >   BOOL DialogManager::DeleteValue(CWindowID WindowID,
04718                                     CGadgetID Gadget,
04719                                     BOOL EndOfList = TRUE,
04720                                     INT32 ListPos = 0)
04721 
04722     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
04723     Created:    9/9/93
04724     Inputs:     WindowID:       Dialog box window identifier
04725                 Gadget:     Gadget identifier
04726 
04727                 The following inputs only need to be provided if the gadget has multiple
04728                 values, for example a ListBox.
04729 
04730                 EndOfList:   TRUE if the value is to be deleted from the end of the gadgets
04731                             value list. (Default = TRUE)
04732 
04733                 ListPos:     If EndOfList = FALSE then this input specifies the position
04734                             in the list (Default = 0, so if you want to delete the value at
04735                             the top of the list simply specify EndOfList = FALSE)
04736 
04737     Returns:    TRUE if the value could be deleted, else FALSE.
04738     Purpose:    For deleting a gadget value
04739 
04740                 For Windows
04741                 -----------
04742 
04743                 This function can be used to delete list items from ListBox or ComboBox
04744                 controls.
04745 
04746     Errors:     If the function is called on an invalid control then an ENSURE failure will
04747                 occur in a DEBUG build. In a retail build FALSE is returned.
04748 
04749     SeeAlso:    DialogOp::DeleteValue
04750 
04751 ********************************************************************************************/
04752 
04753 BOOL DialogManager::DeleteValue(CWindowID WindowID,
04754                                 CGadgetID Gadget,
04755                                 BOOL EndOfList,
04756                                 INT32 ListPos)
04757 {
04758     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04759     if (!pGadget) return FALSE;
04760 
04761     //if ( pGadget->IsKindOf(CLASSINFO(wxControlWithItems)) ) // Includes wxListBox - this seems to have false positives
04762     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04763         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04764         pGadget->IsKindOf(CLASSINFO(wxChoice))
04765         )
04766     {
04767         if (EndOfList)
04768             ((wxControlWithItems *)pGadget)->Delete(((wxControlWithItems *)pGadget)->GetCount()-1);
04769         else
04770             ((wxControlWithItems *)pGadget)->Delete(ListPos);
04771         return TRUE;
04772     }
04773     else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04774     {
04775         if (EndOfList)
04776             ((wxOwnerDrawnComboBox *)pGadget)->Delete(((wxOwnerDrawnComboBox *)pGadget)->GetCount()-1);
04777         else
04778             ((wxOwnerDrawnComboBox *)pGadget)->Delete(ListPos);
04779         return TRUE;
04780     }
04781 
04782     ERROR3("Invalid control");
04783     return FALSE;
04784 }
04785 
04786 /********************************************************************************************
04787 
04788 >   BOOL GetValueCount(CWindowID WindowID,
04789                     CGadgetID Gadget,
04790                     INT32* Count)
04791 
04792     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
04793     Created:    9/9/93
04794     Inputs:     WindowID:       Dialog box window identifier
04795                 Gadget:     Gadget identifier
04796     Outputs:    Count:          The number of items in the gadget
04797 
04798     Returns:    FALSE if an error occurred
04799 
04800     Purpose:    For finding the number of values stored in a gadget
04801 
04802                 For Windows
04803                 -----------
04804 
04805                 This function can be called on ListBox and ComboBox controls to obtain the
04806                 number of values in their lists.
04807 
04808     Errors:     If the function is called on an invalid control then an ENSURE failure will
04809                 occur in a DEBUG build. In a retail build FALSE is returned.
04810 
04811     SeeAlso:    DialogOp::GetValueCount
04812 
04813 ********************************************************************************************/
04814 
04815 
04816 BOOL DialogManager::GetValueCount(CWindowID WindowID,
04817                                 CGadgetID Gadget,
04818                                 INT32* Count)
04819 {
04820     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04821     if (!pGadget) return FALSE;
04822 
04823     //if ( pGadget->IsKindOf(CLASSINFO(wxControlWithItems)) ) // Includes wxListBox - this seems to have false positives
04824     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04825         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04826         pGadget->IsKindOf(CLASSINFO(wxChoice))
04827         )
04828     {
04829         INT32 c = ((wxControlWithItems *)pGadget)->GetCount();
04830         if (Count) *Count=c;
04831         return TRUE;
04832     }
04833     else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04834     {
04835         INT32 c = ((wxOwnerDrawnComboBox *)pGadget)->GetCount();
04836         if (Count) *Count=c;
04837         return TRUE;
04838     }
04839 
04840     ERROR3("Invalid control");
04841     return FALSE;
04842 }
04843 
04844 /********************************************************************************************
04845 
04846 >   INT32 DialogManager::GetSelectedCount(CWindowID WindowID,CGadgetID Gadget, INT32* Count)
04847 
04848     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04849     Created:    4/10/95
04850     Inputs:     WindowID = ID of window that contains the gadget
04851                 Gadget = ID of list-type gadget
04852     Returns:    The number of selected items in the list-type gadget, or -1 if it fails
04853     Purpose:    Returns the number of selected items in a list-type gadget
04854     SeeAlso:    -
04855 
04856 ********************************************************************************************/
04857 
04858 INT32 DialogManager::GetSelectedCount(CWindowID WindowID,CGadgetID Gadget)
04859 {
04860 //  INT32 Count = -1;
04861     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04862     if (!pGadget) return FALSE;
04863 
04864     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04865         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04866         pGadget->IsKindOf(CLASSINFO(wxChoice))
04867         )
04868     {
04869         // Support listboxes with multiple selections
04870         if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
04871         {
04872             wxArrayInt sels;
04873             return ((wxListBox *)pGadget)->GetSelections(sels);
04874         }
04875 
04876         return (((wxControlWithItems *)pGadget)->GetSelection() == wxNOT_FOUND)?0:1;
04877     }
04878     else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04879         return (((wxOwnerDrawnComboBox *)pGadget)->GetSelection() == wxNOT_FOUND)?0:1;
04880 
04881     return -1;
04882 }
04883 
04884 /********************************************************************************************
04885 
04886 >   INT32 DialogManager::GetFirstSelectedItem(CWindowID WindowID, CGadgetID Gadget)
04887 
04888     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04889     Created:    4/10/95
04890     Inputs:     WindowID = ID of window that contains the gadget
04891                 Gadget = ID of list-type gadget
04892     Returns:    The index of the firsted selected items in the list-type gadget, or -1 if it fails
04893     Purpose:    Returns the index of the first selected item in a list-type gadget
04894     SeeAlso:    -
04895 
04896 ********************************************************************************************/
04897 
04898 INT32 DialogManager::GetFirstSelectedItem( CWindowID WindowID, CGadgetID Gadget )
04899 {
04900     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04901     if (!pGadget) return -1;
04902 
04903     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04904         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04905         pGadget->IsKindOf(CLASSINFO(wxChoice)) )
04906     {
04907         // Support listboxes with multiple selections
04908         if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
04909         {
04910             wxArrayInt sels;
04911             if ( ((wxListBox *)pGadget)->GetSelections(sels) )
04912             {
04913                 return sels[0];
04914             }
04915             return -1;
04916         }
04917         return ((wxControlWithItems *)pGadget)->GetSelection();
04918     }
04919     else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04920         return ((wxOwnerDrawnComboBox *)pGadget)->GetSelection();
04921 
04922     return -1;
04923 }
04924 
04925 /********************************************************************************************
04926 
04927 >   INT32* DialogManager::GetSelectedItems(CWindowID WindowID, CGadgetID Gadget)
04928 
04929     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
04930     Created:    4/10/95
04931     Inputs:     WindowID = ID of window that contains the gadget
04932                 Gadget = ID of list-type gadget
04933     Returns:    ptr to the INT32 array, or NULL if it fails
04934     Purpose:    Returns a ptr to an INT32 array that holds the list of selected indexes.
04935                 The last array entry contains -1.
04936 
04937                 NULL is returned if there's no selection, or not enough memory for the required array
04938 
04939                 The caller is responsible for deleting the array that's returned.
04940                 e.g
04941                     INT32* pArray = GetSelectedItems(WindowID,Gadget);
04942                     if (pArray != NULL)
04943                     {
04944                         ..... // Use the array
04945                         delete [] pArray;
04946                     }
04947     SeeAlso:    -
04948 
04949 ********************************************************************************************/
04950 
04951 INT32* DialogManager::GetSelectedItems(CWindowID WindowID, CGadgetID Gadget)
04952 {
04953     INT32* pList = NULL;
04954 
04955     wxArrayInt sels;
04956 
04957     wxWindow * pGadget = GetGadget(WindowID, Gadget);
04958     if (!pGadget) return NULL;
04959 
04960     if ( pGadget->IsKindOf(CLASSINFO(wxListBox)) ||
04961         pGadget->IsKindOf(CLASSINFO(wxComboBox)) ||
04962         pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)) ||
04963         pGadget->IsKindOf(CLASSINFO(wxChoice)) )
04964     {
04965         // Support listboxes with multiple selections
04966         if (pGadget->IsKindOf(CLASSINFO(wxListBox)))
04967         {
04968             ((wxListBox *)pGadget)->GetSelections(sels);
04969         }
04970         else if (pGadget->IsKindOf(CLASSINFO(wxOwnerDrawnComboBox)))
04971         {
04972             sels[0]=((wxOwnerDrawnComboBox *)pGadget)->GetSelection();
04973         }
04974         else
04975         {
04976             sels[0]=((wxControlWithItems *)pGadget)->GetSelection();
04977         }
04978 
04979         size_t Count = sels.GetCount();
04980 
04981         pList = new INT32[Count+1];
04982 
04983         if (pList)
04984         {
04985             UINT32 i;
04986             for (i=0; i<Count; i++)
04987             {
04988                 pList[i]=sels[i];
04989             }
04990             pList[Count] = -1;  // terminate the list
04991         }
04992 
04993         return pList; // may be NULL if no memory
04994 
04995     }
04996     return NULL;
04997 }
04998 
04999 /********************************************************************************************
05000 
05001 >   BOOL DialogManager::GetValueIndex(CWindowID WindowID,
05002                                     CGadgetID Gadget,
05003                                     INT32* Index)
05004 
05005     Author:     Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> / Jason (Based on Simon's stuff...)
05006     Created:    11/10/95
05007     Inputs:     WindowID:       Dialog box window identifier
05008                 Gadget:     Gadget identifier
05009 
05010     Outputs:    Index:          The index of the currently selected item in the gadget. The
05011                                 index value starts at 0 for the first item in the list.
05012 
05013                                 THIS CAN NOW RETURN -1 AS IT SHOULD ALWAYS OF BEEN ABLE TO DO !!!
05014 
05015     Returns:    TRUE if the index value could be read, else FALSE.
05016 
05017     Purpose:    For finding the index of the currently selected item in a gadget
05018 
05019                 For Windows
05020                 -----------
05021 
05022                 The function can be called for ListBox and ComboBox controls
05023 
05024     Errors:     If the function is called on an invalid gadget then an ENSURE failure will
05025                 occur in a DEBUG build. In a retail build FALSE is returned.
05026 
05027     Notes:      ALWAYS USE THIS ONE IN PREFERENCE TO THE WORD ONE, IE ALWAYS PASS A INT32 IN,
05028                 NOT A WORD !!!
05029 
05030                 This function now works internally as well, since comparing a INT32 -1 with a
05031                 word -1 didn't work out too well...
05032 
05033     SeeAlso:    DialogOp::GetValueIndex
05034 
05035 ********************************************************************************************/
05036 
05037 BOOL DialogManager::GetValueIndex(CWindowID WindowID,
05038                                 CGadgetID Gadget,
05039                                 INT32* Index)
05040 {
05041     INT32 index = GetFirstSelectedItem(WindowID, Gadget);
05042     if (Index) *Index=index;
05043     TRACEUSER("amb", _T("Index is %d"),index);
05044     return TRUE;
05045 }
05046 
05047 
05048 /********************************************************************************************
05049 
05050 >   BOOL DialogManager::GetValueIndex(CWindowID WindowID,
05051                                     CGadgetID Gadget,
05052                                     WORD* Index)
05053 
05054     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05055     Created:    9/9/93
05056     Inputs:     WindowID:       Dialog box window identifier
05057                 Gadget:     Gadget identifier
05058 
05059     Outputs:    Index:          The index of the currently selected item in the gadget. The
05060                                 index value starts at 0 for the first item in the list.
05061 
05062     Returns:    TRUE if the index value could be read, else FALSE.
05063 
05064     Purpose:    For finding the index of the currently selected item in a gadget
05065 
05066                 For Windows
05067                 -----------
05068 
05069                 The function can be called for ListBox and ComboBox controls
05070                 (including our custom combobox cc_1dBitmapComboBoxEdit)
05071 
05072     Errors:     If the function is called on an invalid gadget then an ENSURE failure will
05073                 occur in a DEBUG build. In a retail build FALSE is returned.
05074 
05075     SeeAlso:    DialogOp::GetValueIndex
05076 
05077 ********************************************************************************************/
05078 
05079 BOOL DialogManager::GetValueIndex(CWindowID WindowID,
05080                                 CGadgetID Gadget,
05081                                 WORD* Index)
05082 {
05083     if (Index) *Index=GetFirstSelectedItem(WindowID, Gadget);
05084     return TRUE;
05085 }
05086 
05087 
05088 
05089 /********************************************************************************************
05090 
05091 >   BOOL DialogManager::AddDialogControlToHelper(CWindowID WindowID, CGadgetID Gadget)
05092 
05093     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05094     Created:    14/7/2000
05095     Inputs:     WindowID:       Dialog box window identifier
05096                 Gadget:     Gadget identifier
05097     Outputs:
05098     Returns:    TRUE if successful, else FALSE
05099     Purpose:    To add this control to the static dialog control helper, which will subclass it
05100 
05101 ********************************************************************************************/
05102 
05103 BOOL DialogManager::AddDialogControlToHelper(CWindowID WindowID, CGadgetID Gadget)
05104 {
05105     // For the time being, we do this by Hide/Unhide
05106     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05107     if (!pGadget) return FALSE;
05108     pGadget->Show(TRUE);
05109     return TRUE;
05110 }
05111 
05112 
05113 /********************************************************************************************
05114 
05115 >   BOOL DialogManager::RemoveDialogControlFromHelper(CWindowID WindowID, CGadgetID Gadget)
05116 
05117     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
05118     Created:    14/7/2000
05119     Inputs:     WindowID:       Dialog box window identifier
05120                 Gadget:     Gadget identifier
05121     Outputs:
05122     Returns:    TRUE if successful, else FALSE
05123     Purpose:    To add this control to the static dialog control helper, which will subclass it
05124 
05125 ********************************************************************************************/
05126 
05127 BOOL DialogManager::RemoveDialogControlFromHelper(CWindowID WindowID, CGadgetID Gadget)
05128 {
05129     // For the time being, we do this by Hide/Unhide
05130     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05131     if (!pGadget) return FALSE;
05132     pGadget->Show(FALSE);
05133     return TRUE;
05134 }
05135 
05136 /********************************************************************************************
05137 
05138 >   BOOL DialogManager::EnableGadget(CWindowID WindowID, CGadgetID Gadget, BOOL Enabled);
05139 
05140     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05141     Created:    1/9/93
05142     Inputs:     WindowID:       Dialog box window identifier
05143                 Gadget:     Gadget identifier
05144                 Enabled:        TRUE if the gadget is to be enabled.
05145                                 FALSE if the gadget is to be disabled.
05146     Outputs:
05147     Returns:    TRUE if successful, else FALSE
05148     Purpose:    For enabling/disabling a gadget.
05149 
05150                 For Windows
05151                 -----------
05152 
05153                 This function can be called for all controls
05154 
05155     Errors:     -
05156     SeeAlso:    DialogOp::EnableGadget
05157 
05158 ********************************************************************************************/
05159 
05160 BOOL DialogManager::EnableGadget(CWindowID WindowID, CGadgetID Gadget, BOOL Enabled)
05161 {
05162     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05163     if (!pGadget) return FALSE;
05164     pGadget->Enable( FALSE != Enabled );
05165     return (TRUE);
05166 }
05167 
05168 /********************************************************************************************
05169 
05170 >   void DialogManager::SetGadgetWritable(CWindowID id, BOOL enable)
05171 
05172     Author:     DMC
05173     Created:    15/11/94
05174     Inputs:     id, the 'IDC_?' of the control.
05175                 enable, TRUE to allow the control to be typed into. FALSE to make it
05176                         read only.
05177     Purpose:    Sets the state of the 'Read Only' flag of an edit field or combo box.
05178 
05179 ********************************************************************************************/
05180 
05181 BOOL DialogManager::SetGadgetWritable(CWindowID WindowID, CGadgetID Gadget, BOOL enable)
05182 {
05183     // Get the window handle of the gadget, from the gadget ID
05184     wxWindow*           pGadget = GetGadget( WindowID, Gadget );
05185     if( !pGadget )
05186         return FALSE;
05187 
05188     if( pGadget->IsKindOf( CLASSINFO(wxTextCtrl) ) )
05189         ( (wxTextCtrl*)pGadget )->SetEditable( FALSE != enable );
05190     else
05191     {
05192 PORTNOTETRACE("other", "Removed SetGadgetWritable handling of on TextCtrl");
05193 #ifndef EXCLUDE_FROM_XARALX
05194         // See if it's got a child window (it may be a Combo Box)
05195         HWND hEdit = ::ChildWindowFromPoint(gadget, CPoint(1,1));
05196 
05197         if (hEdit)              // Was there a child window ?
05198             gadget = hEdit;     // Yes, so send the message to it
05199 
05200         if (enable)
05201             ::SendMessage(gadget, EM_SETREADONLY, FALSE, 0);    // Clear the Read Only Flag
05202         else
05203             ::SendMessage(gadget, EM_SETREADONLY, TRUE, 0);     // Set the Read Only Flag
05204 #else
05205         return FALSE;
05206 #endif
05207     }
05208 
05209     return TRUE;
05210 }
05211 
05212 /********************************************************************************************
05213 
05214 >   BOOL DialogManager::IsGadgetEnabled( CWindowID WindowID, CGadgetID Gadget );
05215 
05216     Author:     Luke_Hart (Xara Group Ltd) <lukeh@xara.com>
05217     Created:    07/09/06
05218     Inputs:     WindowID:       Dialog box window identifier
05219                 Gadget:         Gadget identifier
05220     Outputs:
05221     Returns:    TRUE if enabled, else FALSE
05222     Purpose:    For checking if a gadget is enabled/disabled.
05223 
05224     Errors:     -
05225     SeeAlso:    DialogOp::IsGadgetEnabled
05226 
05227 ********************************************************************************************/
05228 
05229 BOOL DialogManager::IsGadgetEnabled( CWindowID WindowID, CGadgetID Gadget )
05230 {
05231     wxWindow*           pGadget = GetGadget(WindowID, Gadget);
05232     if (!pGadget)
05233         return FALSE;
05234     
05235     return pGadget->IsEnabled();
05236 }
05237 
05238 
05239 /********************************************************************************************
05240 
05241 >   BOOL DialogManager::HideGadget(CWindowID WindowID, CGadgetID Gadget, BOOL Hide)
05242 
05243     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05244     Created:    1/9/93
05245     Inputs:     WindowID:       Dialog box window identifier
05246                 Gadget:     Gadget identifier
05247                 Enabled:        TRUE if the gadget is to be hidden.
05248                                 FALSE if the gadget is to be shown.
05249     Outputs:    -
05250     Returns:    TRUE if successful, else FALSE
05251     Purpose:    For hiding/showing gadgets
05252 
05253                 For Windows
05254                 -----------
05255 
05256                 This function can be called for all controls
05257 
05258     Errors:     -
05259     SeeAlso:    DialogOp::HideGadget
05260 
05261 ********************************************************************************************/
05262 
05263 BOOL DialogManager::HideGadget(CWindowID WindowID, CGadgetID Gadget, BOOL Hide)
05264 {
05265     // For the time being, we do this by Hide/Unhide
05266     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05267     if (!pGadget) return FALSE;
05268     pGadget->Show(!Hide);
05269     return TRUE;
05270 }
05271 
05272 /********************************************************************************************
05273 
05274 >   void DialogManager::Layout(CWindowID WindowID, BOOL CanYield=FALSE)
05275 
05276     Author:     Alex Bligh <alex@alex.org.uk>
05277     Created:    10/05/2006
05278     Inputs:     WindowID:       Dialog box window identifier
05279     Outputs:    -
05280     Returns:    -
05281     Purpose:    Relayout dialog - for sizer changes
05282     Errors:     -
05283     SeeAlso:    -
05284 
05285 ********************************************************************************************/
05286 
05287 void DialogManager::Layout(CWindowID WindowID, BOOL CanYield /*=FALSE*/)
05288 {
05289     ((wxWindow *)WindowID)->Layout();
05290     if (CanYield)
05291     {
05292         // wxWidgets needs a yield to process these, but we can't always yield
05293         wxWindowDisabler(WindowID);
05294         wxYieldIfNeeded();
05295     }
05296 }
05297 
05298 /********************************************************************************************
05299 
05300 >   BOOL DialogManager::GadgetRedraw(CWindowID WindowID, CGadgetID Gadget, BOOL Redraw)
05301 
05302     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05303     Created:    9/9/93
05304     Inputs:     WindowID:       Dialog box window identifier
05305                 Gadget:     Gadget identifier
05306                 Redraw:         TRUE to turn on gadget redraw
05307                                 FALSE to turn off gadget redraw
05308     Outputs:    -
05309     Returns:    TRUE if successful, else FALSE
05310     Purpose:    This function sets a gadgets redraw state. If Redraw = FALSE then the gadget
05311                 will not be redrawn when changes are made to it. Conversely if Redraw = TRUE
05312                 then the Gadget will redraw itself after any changes are made.
05313 
05314                 For Windows
05315                 -----------
05316 
05317                 This function can be called for all controls
05318 
05319     Errors:     -
05320     SeeAlso:    DialogOp::GadgetRedraw
05321 
05322 ********************************************************************************************/
05323 
05324 BOOL DialogManager::GadgetRedraw(CWindowID WindowID, CGadgetID Gadget, BOOL Redraw)
05325 {
05326     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05327     if (!pGadget) return FALSE;
05328 
05329     if( Redraw )
05330     {
05331         pGadget->Thaw();
05332     }
05333     else
05334     {
05335         pGadget->Freeze();
05336     }
05337 
05338     return TRUE;
05339 }
05340 
05341 
05342 
05343 /********************************************************************************************
05344 >   static BOOL DialogManager::SetKeyboardFocus(CWindowID WindowID, CGadgetID Gadget)
05345 
05346     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
05347     Created:    10/11/94
05348     Inputs:     WindowID            ID of the window / dialogue box containing . . .
05349                 Gadget          ID of the "gadget" (control) to receive the focus
05350     Outputs:    -
05351     Returns:    TRUE if successful.
05352     Purpose:    Sets the keyboard focus to the given control.
05353     Errors:     -
05354     SeeAlso:    DialogManager::DefaultKeyboardFocus; DialogOp::SetKeyboardFocus
05355 ********************************************************************************************/
05356 
05357 BOOL DialogManager::SetKeyboardFocus(CWindowID WindowID, CGadgetID Gadget)
05358 {
05359     // Set the focus to the control within the given window/dialogue box.
05360     // For the time being, we do this by Hide/Unhide
05361     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05362     if (!pGadget) return FALSE;
05363 
05364     pGadget->SetFocus();
05365     return TRUE;
05366 }
05367 
05368 
05369 
05370 /********************************************************************************************
05371 >   static BOOL DialogManager::CaptureMouse(CWindowID WindowID, CGadgetID Gadget)
05372 
05373     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
05374     Created:    28/04/97
05375     Inputs:     WindowID            ID of the window / dialogue box containing . . .
05376                 Gadget          ID of the "gadget" (control) to receive the focus
05377     Outputs:    -
05378     Returns:    TRUE if successful.
05379     Purpose:    Allows the given control to Capture the mouse.
05380     Errors:     -
05381     SeeAlso:    DialogManager::DefaultKeyboardFocus; DialogOp::SetKeyboardFocus
05382 ********************************************************************************************/
05383 
05384 BOOL DialogManager::CaptureMouse(CWindowID WindowID, CGadgetID Gadget)
05385 {
05386     // Set the focus to the control within the given window/dialogue box.
05387     // For the time being, we do this by Hide/Unhide
05388     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05389     if (!pGadget) return FALSE;
05390 
05391     pGadget->CaptureMouse();
05392     return TRUE;
05393 }
05394 
05395 
05396 
05397 /********************************************************************************************
05398 >   static BOOL DialogManager::ReleaseMouse(CWindowID WindowID, CGadgetID Gadget)
05399 
05400     Author:     Stefan_Stoykov (Xara Group Ltd) <camelotdev@xara.com>
05401     Created:    28/04/97
05402     Inputs:     WindowID            ID of the window / dialogue box containing . . .
05403                 Gadget          ID of the "gadget" (control) to receive the focus
05404     Outputs:    -
05405     Returns:    TRUE if successful.
05406     Purpose:    Release the mouse captured by the given control
05407     Errors:     -
05408     SeeAlso:    DialogManager::DefaultKeyboardFocus; DialogOp::SetKeyboardFocus
05409 ********************************************************************************************/
05410 
05411 BOOL DialogManager::ReleaseMouse(CWindowID WindowID, CGadgetID Gadget)
05412 {
05413     // get the handle off the control
05414     // For the time being, we do this by Hide/Unhide
05415     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05416     if (!pGadget) return FALSE;
05417 
05418     // Check whether the control has the mouse capture
05419     if( wxWindow::GetCapture() == pGadget )
05420     {
05421         pGadget->ReleaseMouse();
05422         return TRUE;
05423     }
05424     else
05425         return FALSE;
05426 }
05427 
05428 
05429 
05430 /********************************************************************************************
05431 >   static BOOL DialogManager::DefaultKeyboardFocus()
05432 
05433     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
05434     Created:    10/11/94
05435     Inputs:     -
05436     Outputs:    -
05437     Returns:    TRUE if successful.
05438     Purpose:    Sets the keyboard focus to the "default" window, which currently is the
05439                 main frame window (which in turn sets it to the active view window).
05440     Errors:     -
05441     SeeAlso:    DialogManager::SetKeyboardFocus; DialogOp::SetKeyboardFocus
05442 ********************************************************************************************/
05443 
05444 BOOL DialogManager::DefaultKeyboardFocus()
05445 {
05446     // Set the focus to the main window, which will in turn set it to the active view.
05447     GetMainFrame()->SetFocus();
05448     return TRUE;
05449 }
05450 
05451 
05452 
05453 /********************************************************************************************
05454 >   static BOOL DialogManager::HighlightText(CWindowID WindowID, CGadgetID Gadget,
05455                                             INT32 nStart = 0, INT32 nEnd = -1)
05456 
05457     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
05458     Created:    10/11/94
05459     Inputs:     WindowID            Window/dialogue box ID (handle)
05460                 Gadget          control ID within the window/dialogue box
05461                 nStart          first letter to highlight (by default the very first)
05462                 nEnd            last letter to highlight (by default the very last)
05463     Outputs:    -
05464     Returns:    TRUE if successful
05465     Purpose:    Highlights the given range of text (by default all of it) within a
05466                 control that holds editable text, eg. an edit field.
05467     Errors:     ERROR3 if you try to highlight text in a control without any, eg. a
05468                 button or a scroller.
05469     SeeAlso:    DialogOp::HighlightText
05470 ********************************************************************************************/
05471 
05472 BOOL DialogManager::HighlightText(CWindowID WindowID, CGadgetID Gadget, INT32 nStart, INT32 nEnd)
05473 {
05474     // Find out the window class of the control.  Only those with editable text can
05475     // be highlighted.
05476     // For the time being, we do this by Hide/Unhide
05477     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05478     if (!pGadget) return FALSE;
05479 
05480 #ifdef _DEBUG
05481     ERROR3IF( !pGadget->IsKindOf( CLASSINFO(wxListBox) ) &&
05482         !pGadget->IsKindOf( CLASSINFO(wxComboBox) ) &&
05483         !pGadget->IsKindOf( CLASSINFO(wxOwnerDrawnComboBox) ) &&
05484         !pGadget->IsKindOf( CLASSINFO(wxTextCtrl) ),
05485                 "Wrong kind of control in DialogManager::HighlightText");
05486 #endif
05487 
05488     if( pGadget->IsKindOf( CLASSINFO(wxTextCtrl) ) )
05489     {
05490         ( (wxTextCtrl *)pGadget )->SetSelection( -1, -1 );
05491     }
05492     else if( pGadget->IsKindOf( CLASSINFO(wxComboBox) ) )
05493     {
05494         ( (wxComboBox *)pGadget )->SetSelection( -1, -1 );
05495     }
05496     else if( pGadget->IsKindOf( CLASSINFO(wxOwnerDrawnComboBox) ) )
05497     {
05498         ( (wxOwnerDrawnComboBox *)pGadget )->SetSelection( -1 );
05499     }
05500 
05501     return TRUE;
05502 }
05503 
05504 
05505 
05506 /********************************************************************************************
05507 >   static void DialogManager::PaintGadgetNow(CWindowID WindowID, CGadgetID gid)
05508 
05509     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
05510     Created:    1/9/94
05511     Inputs:     WindowID            Window identifier
05512                 gid         Gadget (control) identifier,  or zero for the whole window
05513     Outputs:    -
05514     Returns:    -
05515     Purpose:    Immediate paints any invalid areas of the given control (like the Windows
05516                 "UpdateWindow" function).
05517     Errors:     -
05518     SeeAlso:    -
05519 ********************************************************************************************/
05520 
05521 void DialogManager::PaintGadgetNow(CWindowID WindowID, CGadgetID Gadget)
05522 {
05523     if (!Gadget)
05524     {
05525         ((wxWindow *)WindowID)->Update();
05526         wxPlatformDependent::Get()->FixUpdate((wxWindow *)WindowID);
05527         return;
05528     }
05529     // For the time being, we do this by Hide/Unhide
05530     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05531     if (!pGadget) return;
05532 
05533     pGadget->Update();
05534     wxPlatformDependent::Get()->FixUpdate(pGadget);
05535 }
05536 
05537 
05538 
05539 /********************************************************************************************
05540 
05541 >   static void DialogManager::InvalidateGadget(CWindowID WindowID, CGadgetID Gadget, BOOL EraseBackground)
05542 
05543     Author:     Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
05544     Created:    20/10/94
05545     Inputs:     WindowID - The Window identifier
05546                 Gadget - The control that requires invalidating
05547     Purpose:    Invalidates the control so that it will be repainted soon.
05548 
05549 ********************************************************************************************/
05550 
05551 void DialogManager::InvalidateGadget(CWindowID WindowID, CGadgetID Gadget, BOOL EraseBackground /*=TRUE*/)
05552 {
05553     if (!Gadget)
05554     {
05555         ((wxWindow *)WindowID)->Refresh(EraseBackground);
05556         return;
05557     }
05558     // For the time being, we do this by Hide/Unhide
05559     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05560     if (!pGadget) return;
05561 
05562     pGadget->Refresh(EraseBackground);
05563 }
05564 
05565 
05566 
05567 /********************************************************************************************
05568 
05569 >   static void DialogManager::InvalidateGadget(CWindowID WindowID, CGadgetID Gadget,
05570                                                 RedrawInfoType *ExtraInfo,
05571                                                 DocRect *InvalidRect);
05572 
05573     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05574     Created:    28/11/94
05575     Inputs:     WindowID - The Window identifier
05576                 Gadget - The ID of the gadget that you want to be redrawn
05577 
05578                 ExtraInfo - The information passed to your DIM_ mouse event handler
05579 
05580                 InvalidRect - The MILLIPOINT rectangle to invalidate, in the (0,0)->(dx,dy)
05581                 coordinate space used in ReDrawInfoType structures. (or NULL to invalidate
05582                 the entire window)
05583 
05584     Purpose:    Causes the Dialog Manager to tell the host os to get the cc_DialogDraw
05585                 gadget to be redrawn, over the specfied rectangle. You should recieve
05586                 a DIM_REDRAW message in the not too distant future.
05587 
05588     Notes:      If you are using a Virtual coordinate space which differs from the
05589                 (0,0)->(dx,dy) space that this requires, then you'll need to call
05590                 some conversion methods which do not yet exist!
05591 
05592 ********************************************************************************************/
05593 
05594 void DialogManager::InvalidateGadget(CWindowID WindowID, CGadgetID Gadget,
05595                                         ReDrawInfoType *ExtraInfo,
05596                                         DocRect *InvalidRect)
05597 {
05598     if (InvalidRect == NULL)    // No rect - invalidate the entire window
05599     {
05600         InvalidateGadget(WindowID, Gadget);
05601         return;
05602     }
05603 
05604     if (ExtraInfo == NULL || WindowID == 0)
05605     {
05606         ERROR2RAW("DialogManager::InvalidateGadget was passed illegal NULL parameter(s)");
05607         return;
05608     }
05609 
05610     ERROR3IF(ExtraInfo->Dpi == 0, "Screen DPI is zero? I think not! Divide-by-zeros imminent!");
05611     if (!ExtraInfo->Dpi) return;
05612 
05613     INT32 PixelSize = 72000 / ExtraInfo->Dpi;       // Size of a pixel in MILLIPOINTS
05614 
05615     DocRect irect=*InvalidRect;
05616     if (irect.lo.y > irect.hi.y)
05617     {
05618         // not an ERROR3 because this is in rendering code
05619         TRACEALL( _T("Rectangle upside down in InvalidateGadget\n") );
05620         // swap over the rect Y co-ords
05621         INT32 temp=irect.lo.y;
05622         irect.lo.y=irect.hi.y;
05623         irect.lo.y=temp;
05624     }
05625 
05626     wxRect ToRedraw(irect.lo.x / PixelSize, (ExtraInfo->dy-irect.hi.y) / PixelSize,
05627                     (irect.hi.x-irect.lo.x) / PixelSize, (irect.hi.y-irect.lo.y)/PixelSize);
05628 
05629     wxWindow * pGadget = GetGadget(WindowID, Gadget);
05630     // Invalidate the gadget, but only if we found a legal window to invalidate
05631     ERROR3IF((!pGadget), "DialogManager::InvalidateGadget - Gadget not valid");
05632 
05633     if (pGadget)
05634     {
05635         // GTK seems a bit precious about invalid coordinates, so clip to the client size
05636         wxRect GadgetRect(pGadget->GetClientSize());
05637         ToRedraw=ToRedraw.Intersect(GadgetRect);
05638         pGadget->Refresh(TRUE, &ToRedraw);
05639     }
05640 }
05641 
05642 
05643 /********************************************************************************************
05644 
05645 >   static void DialogManager::ScrollKernelRenderedGadget(CWindowID WindowID, CGadgetID Gadget,
05646                                                 DocRect *RectToScroll, DocCoord *ScrollBy)
05647 
05648     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05649     Created:    21/1/95
05650     Inputs:     WindowID - The Window identifier
05651                 Gadget - The ID of the gadget that you want to be redrawn
05652 
05653                 RectToScroll - The MILLIPOINT rectangle to scroll, in the (0,0)->(dx,dy)
05654                 coordinate space used in ReDrawInfoType structures. Think of this rectangle
05655                 as the visible portion of the window which will be copied (some of which
05656                 will be scrolled out of view), and let this method worry about invalidating
05657                 the 'hole' left behind to finish off the display.
05658                 This parameter may be NULL, in which case the entire gadget will be scrolled
05659 
05660                 ScrollBy - Gives the X and Y amounts in millipoints to scroll the given
05661                 rectangle. I don't know what will happen if neither of these values is zero!
05662 
05663     Outputs:    ScrollBy will be returned with the x and y values grid-locked to the
05664                 underlying display-pixel grid. If you do not use the returned values to
05665                 update your millipoint scroll position, your scroll position will get out
05666                 of sync with the displayed image, and you'll be screwed.
05667 
05668     Purpose:    Causes the Dialog Manager to tell the host os to get the cc_DialogDraw
05669                 gadget to be scrolled, over the specfied rectangle. You should recieve
05670                 a DIM_REDRAW message in the not too distant future, to update any portions
05671                 that 'scroll into view'.
05672 
05673     Notes:      If you are using a Virtual coordinate space which differs from the
05674                 (0,0)->(dx,dy) space that this requires, then you'll need to convert
05675                 your coords.
05676 
05677                 If ScrollBy is such that the entire visible region will be scrolled out of
05678                 view, this ends up just invalidating the scrollrect.
05679 
05680                 I have not tried scrolling an entire window with this method, so it may
05681                 be that it doesn't work properly (it should work, but you might need to
05682                 set up a proper clipping rectangle to stop masty redraw effects)
05683 
05684                 To produce the best results, you should udate your scroll position after
05685                 calling this method and immediately call PaintGadgetNow to minimise the
05686                 time for which the window layout is in a state of flux.
05687 
05688 ********************************************************************************************/
05689 
05690 void DialogManager::ScrollKernelRenderedGadget(CWindowID WindowID, CGadgetID Gadget,
05691                                                 DocRect *RectToScroll, DocCoord *ScrollBy)
05692 {
05693     ERROR3IF(ScrollBy == NULL || WindowID == 0 || Gadget == 0,
05694             "DialogManager::ScrollKernelRenderedGadget - NULL Params are illegal");
05695 
05696     // For the time being, we do this by Hide/Unhide
05697     wxWindow * pWinToScroll = GetGadget(WindowID, Gadget);
05698     if (!pWinToScroll) return;
05699 
05700     ERROR3IF( pWinToScroll == 0,
05701         "DialogManager::ScrollKernelRenderedGadget - Illegal window/gadget");
05702 
05703     if( pWinToScroll == 0 )
05704         return;
05705 
05706     ReDrawInfoType ExtraInfo;
05707     GetKernelRenderedGadgetInfo(WindowID, Gadget, &ExtraInfo);
05708 
05709     INT32 PixelSize = 72000 / ExtraInfo.Dpi;        // Size of a pixel in MILLIPOINTS
05710 
05711     INT32 ScrollDX = ScrollBy->x / PixelSize;
05712     INT32 ScrollDY = ScrollBy->y / PixelSize;
05713 
05714     // Grid-lock the scroll offsets to a multiple of device pixels in size, for return
05715     ScrollBy->x = ScrollDX * PixelSize;
05716     ScrollBy->y = ScrollDY * PixelSize;
05717 
05718     if (abs(ScrollBy->x) >= RectToScroll->Width() ||
05719         abs(ScrollBy->y) >= RectToScroll->Height())
05720     {
05721         // Have scrolled far enough that none of the currently visible stuff will be
05722         // visible after scrolling, so just force redraw the affected rectangle
05723         // (Actually, the 'else' part should get this right anyway, but I don't
05724         // want to have to test everything on 6 billion OSes, and it's probably
05725         // marginally more efficient this way)
05726         InvalidateGadget(WindowID, Gadget, &ExtraInfo, RectToScroll);
05727     }
05728     else
05729     {
05730         if (RectToScroll != NULL)
05731         {
05732             // Get the base scroll area in Windows OS coords
05733             wxRect      BaseRect;
05734             BaseRect.x      = RectToScroll->lo.x / PixelSize;
05735             BaseRect.width  = ( RectToScroll->hi.x - RectToScroll->lo.x ) / PixelSize;
05736             BaseRect.y      = ( ExtraInfo.dy - RectToScroll->hi.y ) / PixelSize;
05737 //          BaseRect.height = ( ExtraInfo.dy + RectToScroll->lo.y - RectToScroll->hi.y ) / PixelSize;
05738             BaseRect.height = ( RectToScroll->hi.y - RectToScroll->lo.y ) / PixelSize;
05739 
05740             // Copy the scroll area contents with a blit, and invalidate the 'hole'
05741             pWinToScroll->ScrollWindow( -ScrollDX, -ScrollDY, &BaseRect );
05742         }
05743         else
05744         {
05745             // Just scroll the entire window client area
05746             pWinToScroll->ScrollWindow( -ScrollDX, -ScrollDY, NULL );
05747         }
05748     }
05749 }
05750 
05751 
05752 
05753 /********************************************************************************************
05754 
05755 >   static BOOL DialogManager::GetKernelRenderedGadgetInfo(CWindowID WindowID, CGadgetID Gadget,
05756                                                             ReDrawInfoType *Result)
05757 
05758     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05759     Created:    19/1/95
05760 
05761     Inputs:     WindowID - The parent window identifier
05762                 Gadget - The ID of the gadget that you want info for
05763 
05764     Returns:    FALSE if there was a catastrophic error (it will report an ERROR2 if necessary),
05765                 in which case the returned data is invalid (well, it defaults to 96 Dpi and
05766                 an area of 72000x72000 millipoints, so is 'safe' to use, but probably wrong)
05767                 TRUE under normal conditions
05768 
05769     Outputs:    Result - will be returned filled in with appropriate kernel-rendered-
05770                 dialogue information (dx, dy, and Dpi will be filled in with the appropriate
05771                 values; pMousePOs, pDC, and pClipRect will all be NULL)
05772 
05773     Purpose:    Allows the user access to the same information which is passed in to
05774                 DIM_REDRAW and the kernel-rendered-dialogue mouse-handling messages. This
05775                 is just for convenience so they can calculate stuff at a time other than
05776                 handling those two types of dialogue event (e.g. if a document message
05777                 causes you to have to redraw a small portion of your gadget, you need this
05778                 information to calculate the invalidation rectangle from)
05779 
05780 ********************************************************************************************/
05781 
05782 BOOL DialogManager::GetKernelRenderedGadgetInfo(CWindowID WindowID, CGadgetID Gadget,
05783                                                 ReDrawInfoType *Result)
05784 {
05785     ERROR3IF(WindowID == 0 || Gadget == 0 || Result == NULL,
05786         "DialogManager::GetKernelRenderedGadgetInfo: NULL parameters are illegal!");
05787 
05788     // For the time being, we do this by Hide/Unhide
05789     wxWindow * pTheWindow = GetGadget(WindowID, Gadget);
05790     if (!pTheWindow) return FALSE;
05791 
05792     Result->pDC = NULL;
05793     Result->pClipRect = NULL;
05794     Result->pMousePos = NULL;
05795 
05796     // Install some 'safe' defaults, just in case of serious error
05797     Result->dx = Result->dy = 72000;
05798     Result->Dpi = 96;
05799 
05800     // If a totally rampant call, error (debug) and return failure
05801     ERROR3IF( NULL == pTheWindow,
05802                 "DialogManager::GetKernelRenderedGadgetInfo - Illegal window/gadget");
05803     if( pTheWindow == 0 )
05804         return(FALSE);
05805 
05806     // Get the screen DPI
05807     wxScreenDC          ScreenDC;
05808 PORTNOTE("dialog","Can't handle different DPIs, using X")
05809     Result->Dpi = OSRenderRegion::GetFixedDCPPI(ScreenDC).x; // x;
05810 
05811     // Calculate how big the window is, in MILLIPOINTS
05812     wxSize              WindowSize( pTheWindow->GetClientSize() );
05813 
05814     Result->dx = ( INT32(WindowSize.GetWidth())*72000 ) / Result->Dpi;
05815     Result->dy = ( INT32(WindowSize.GetHeight())*72000) / Result->Dpi;
05816     return(TRUE);
05817 }
05818 
05819 
05820 
05821 
05822 // -----------------------------------------------------------------------------------------
05823 // Message handler functions
05824 
05825 /********************************************************************************************
05826 
05827 >   static void DialogManager::SetGadgetIDToFocus(HWND DialogWnd)
05828 
05829     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05830     Created:    17/4/94
05831     Inputs:     DialogWnd: The dialog window
05832     Outputs:    -
05833     Returns:    -
05834     Purpose:    If a child control of the dialog window has the focus then the function
05835                 sets the Gadget to the ID of this control.
05836 
05837     Scope:      private
05838     Errors:     -
05839     SeeAlso:    -
05840 
05841 ********************************************************************************************/
05842 
05843 void DialogManager::SetGadgetIDToFocus( wxWindow *pDialogWnd )
05844 {
05845     PORTNOTETRACE("dialog","DialogManager::SetGadgetIDToFocus - do nothing");
05846 #ifndef EXCLUDE_FROM_XARALX
05847     // Determine which gadget has the focus
05848     wxWindow           *pFocusWindow = wxWindow::FindFocus();
05849 
05850     // If the Focus Window is a child of the dialog window then set Gadget equal
05851     // to the control ID of this window
05852     wxWindow           *pCurrentChild;
05853     wxWindowList       &listChild = pDialogWnd->GetChildren();
05854     wxWindowList::iterator iter = listChild.begin();
05855     wxWindowList::iterator end = listChild.end();
05856     for(;
05857         iter != end;
05858         ++iter )
05859     {
05860         if( CurrentChild == FocusWindow )
05861         {
05862             // The focus is with a gadget
05863             Gadget = GetDlgCtrlID( FocusWindow );
05864             break;
05865         }
05866     }
05867 #endif
05868 }
05869 /********************************************************************************************
05870 
05871 >   static BOOL CustomControlMsg(HWND hdlg, UINT32 wParam, INT32 lParam)
05872 
05873     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05874     Created:    19/4/94
05875     Inputs:     hdlg: Dialog HWND
05876     Outputs:    -
05877     Returns:    TRUE if message handled
05878     Purpose:    Handles custom control messages
05879     Errors:     -
05880     SeeAlso:    -
05881 
05882 ********************************************************************************************/
05883 
05884 BOOL DialogManager::CustomControlMsg( wxWindow *pDlg, UINT32 wParam, INT32 lParam )
05885 {
05886     PORTNOTETRACE("dialog","DialogManager::CustomControlMsg - do nothing");
05887 #ifndef EXCLUDE_FROM_XARALX
05888     String_256 ClassNameStr;
05889     GetClassName( HWND(lParam), (TCHAR*)ClassNameStr, 255);
05890     if ((ClassNameStr == String_16(TEXT("cc_BitmapButton")))||
05891         ClassNameStr == String_16(TEXT("cc_SmallButton")))
05892     {
05893         Gadget = HIWORD(wParam);
05894         switch (LOWORD(wParam))
05895         {
05896         case BN_CLICKED:
05897             DialogManager::DIM = DIM_LFT_BN_CLICKED;
05898             DialogManager::HandleMessage = TRUE;
05899             return TRUE;
05900 
05901         case BN_BUTTONUP:
05902             DialogManager::DIM = DIM_LFT_BN_UP;
05903             DialogManager::HandleMessage = TRUE;
05904             return TRUE;
05905 
05906         case WM_MOUSEMOVE:
05907             DialogManager::DIM = DIM_MOUSE_MOVE;
05908             DialogManager::HandleMessage = TRUE;
05909             return TRUE;
05910 
05911 
05912         default:
05913             TRACEUSER( "JustinF", _T("Unknown message ID in DialogManager::CustomControlMsg\n"));
05914             break;
05915         }
05916     }
05917 #endif
05918     return FALSE; // Not a custom control message
05919 }
05920 
05921 /********************************************************************************************
05922 
05923 >   void DialogManager::EnableAllDialogs(BOOL Enable, HWND ExceptMe = NULL)
05924 
05925     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05926     Created:    25/4/95
05927 
05928     Inputs:     Enable: When TRUE all dialogs are enabled
05929 
05930                 ExceptMe: An optional dialog to exclude. If a modal dialog X has just
05931                         been created then all dialogs except X will need disabling
05932     Outputs:    -
05933     Returns:    -
05934     Purpose:    Enables or Disables all Dialogs on the DialogOp message handler list.
05935                 This is useful when opening/closing modal dialogs.
05936 
05937 ********************************************************************************************/
05938 
05939 void DialogManager::EnableAllDialogs( BOOL Enable, wxWindow *pExceptMe )
05940 {
05941     // Obtain a list of all live dialogs
05942     List               *pDlgList = MessageHandler::GetClassList( CC_RUNTIME_CLASS(DialogOp) );
05943 
05944     ERROR3IF( pDlgList == NULL, "Could not find the DialogOp Class List" );
05945     if( NULL != pDlgList )
05946     {
05947         ListItem       *CurrentOp = pDlgList->GetHead();
05948         DialogOp       *pDlgOp;
05949         while( CurrentOp != NULL )
05950         {
05951             if (CurrentOp->IS_KIND_OF(DialogOp)) // They all should be
05952             {
05953                 pDlgOp = (DialogOp*)CurrentOp;
05954                 // Determine if the dialog has an associated window
05955                 if (pDlgOp->HasWindow())
05956                 {
05957                     if (pDlgOp->WindowID != pExceptMe)
05958                     {
05959                         ( (wxWindow *)pDlgOp->WindowID )->Enable( FALSE != Enable );
05960                     }
05961                 }
05962             }
05963             CurrentOp = pDlgList->GetNext(CurrentOp); // Get next operation in the live list
05964         }
05965     }
05966 
05967     // For some reason, the green bit of code below did not disable common dialogs. Therefore
05968     // the semi-bodge below was added to disable the active window.
05969 
05970     wxWindow           *pActiveWindow = wxWindow::FindFocus();
05971     if( NULL != pActiveWindow )
05972     {
05973         if( pActiveWindow != pExceptMe )
05974         {
05975             pActiveWindow->Enable( FALSE != Enable );
05976         }
05977     }
05978 }
05979 
05980 
05981 
05982 // End of Message handler functions
05983 // ----------------------------------------------------------------------------------------
05984 
05985 // Methods for setting the types of edit fields
05986 // ----------------------------------------------------------------------------------------
05987 
05988 /********************************************************************************************
05989 
05990 >   void DialogManager::SetEditGadgetType(CWindowID WindowID,
05991                                     CGadgetID Gadget,
05992                                     EditGadgetType Type)
05993 
05994     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
05995     Created:    20/8/93
05996     Inputs:     WindowID:   Dialog box window identifier
05997                 Gadget:     The edit gagdet identifier
05998                 Type:       The type of the edit gadget
05999 
06000                 UNIT_NUMERIC: Only accept unit chars
06001                 INT_NUMERIC:  Only accept integer chars
06002                 REAL_NUMERIC: Only accept real chars
06003     Outputs:    -
06004     Returns:    -
06005     Purpose:    Subclasses the edit gadget so that it only accepts characters specified by
06006                 the Type parameter.
06007     Errors:     -
06008     SeeAlso:    DialogOp::SetEditGadgetType
06009 
06010 ********************************************************************************************/
06011 
06012 
06013 void DialogManager::SetEditGadgetType(CWindowID Win,
06014                                     CGadgetID Gadget,
06015                                     EditGadgetType Type)
06016 {
06017     UINT32 IDSValidChars=0; // Resource ID of valid input characters
06018     switch (Type)
06019     {
06020         // Obtain the resource of the string containing the set of characters which the
06021         // control should accept.
06022         case UNIT_NUMERIC: IDSValidChars = _R(IDS_UNIT_NUMERIC_CHARS); break;
06023         case INT_NUMERIC: IDSValidChars = _R(IDS_INT_NUMERIC_CHARS);   break;
06024         case REAL_NUMERIC: IDSValidChars = _R(IDS_REAL_NUMERIC_CHARS); break;
06025     };
06026     SetEditGadgetType(Win, Gadget, IDSValidChars);
06027 }
06028 
06029 // A quick subclass hack to fix requirement that wxTextValidator has data storage
06030 class wxTextValidatorFixed : public wxTextValidator
06031 {
06032     DECLARE_DYNAMIC_CLASS(wxTextValidatorFixed);
06033 public:
06034     wxTextValidatorFixed(/*TYPENOTE: Correct*/ long style = wxFILTER_NONE, wxString *val = 0) : wxTextValidator(style, val) {}
06035     wxTextValidatorFixed(const wxTextValidator& val) : wxTextValidator(val) {}
06036     ~wxTextValidatorFixed(){}
06037     virtual wxObject *Clone() const { return new wxTextValidatorFixed(*this); }
06038     virtual bool TransferToWindow(void) /*TYPENOTE: Correct*/
06039     {   
06040         if ( m_stringValue )
06041         {
06042             if( !CheckValidator() ) return false;           /*TYPENOTE: Correct*/
06043             wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow;
06044             control->SetValue(* m_stringValue);
06045         }
06046     return true;                                            /*TYPENOTE: Correct*/
06047     }
06048     virtual bool TransferFromWindow(void)   /*TYPENOTE: Correct*/
06049     {
06050         if ( m_stringValue )
06051         {
06052             if( !CheckValidator() ) return false;           /*TYPENOTE: Correct*/
06053             wxTextCtrl *control = (wxTextCtrl *) m_validatorWindow;
06054             *m_stringValue = control->GetValue();
06055         }
06056         return true;                                        /*TYPENOTE: Correct*/
06057     }
06058 };
06059 IMPLEMENT_DYNAMIC_CLASS(wxTextValidatorFixed, wxTextValidator);
06060 
06061 /********************************************************************************************
06062 
06063 >   void DialogManager::SetEditGadgetType(CWindowID WindowID,
06064                                         CGadgetID Gadget,
06065                                         UINT32 IDSValidChar)
06066 
06067     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06068     Created:    20/8/93
06069     Inputs:     WindowID:       Dialog box window identifier
06070                 Gadget:         The edit gagdet identifier
06071                 IDSValidChar:   Resource ID of the string containing the set of characters
06072                                 that the edit gadget should accept.
06073 
06074     Outputs:    -
06075     Returns:    -
06076     Purpose:    To subclass the edit gadget so that it only accepts characters in the string
06077                 specified by IDSValidChar
06078     Errors:     -
06079     SeeAlso:    DialogOp::SetEditGadgetType
06080 
06081 ********************************************************************************************/
06082 
06083 
06084 void DialogManager::SetEditGadgetType(CWindowID WindowID,
06085                                 CGadgetID Gadget,
06086                                 UINT32 IDSValidChar)
06087 {
06088     wxWindow * pGadget = GetGadget(WindowID, Gadget);
06089     if (!pGadget) return;
06090 
06091     String_256 s;
06092     if (!s.Load(IDSValidChar))
06093     {
06094         ERROR3("Could not load validator string");
06095         return;
06096     }
06097     wxArrayString valstring;
06098     TCHAR * p = (TCHAR *)s;
06099     TCHAR c;
06100     while ((c=*p++)!=0)
06101     {
06102         valstring.Add(wxString(c));
06103     }
06104     wxTextValidatorFixed validator(wxFILTER_INCLUDE_CHAR_LIST);
06105     validator.SetIncludes(valstring);
06106     pGadget->SetValidator(validator);
06107 }
06108 
06109 /********************************************************************************************
06110 
06111 >   void DialogManager::DualFunctionButton(CWindowID DialogWnd,
06112                                     CGadgetID ButtonGadget)
06113 
06114     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06115     Created:    7/9/93
06116     Inputs:     DialogWnd:      Dialog box window identifier
06117                 ButtonGadget:   Button gadget identifier
06118     Outputs:    -
06119     Returns:    -
06120     Purpose:    To subclass the button gadget so that it accepts right mouse button clicks.
06121     Errors:     -
06122     SeeAlso:    DialogOp::DualFunctionButton
06123 
06124 ********************************************************************************************/
06125 
06126 void DialogManager::DualFunctionButton(CWindowID DialogWnd,
06127                                     CGadgetID ButtonGadget)
06128 {
06129     PORTNOTETRACE("dialog","DialogManager::DualFunctionButton - do nothing");
06130 #ifndef EXCLUDE_FROM_XARALX
06131     // This function should only be called for a button control
06132     HWND hGadget = GetDlgItem((HWND)DialogWnd, (INT32)ButtonGadget);
06133     #if _DEBUG
06134     String_256 ClassNameStr;
06135     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
06136 
06137     ENSURE((ClassNameStr == String_8(TEXT("Button"))), "DualFunctionButton function called\n"
06138                                                     "on a gadget which is not a button");
06139     #endif
06140 
06141     ControlInfo* ControlInfoPtr;               // This structure will be passed to the
06142                                             // RgtMOuseButtonProc.
06143 
06144     ControlInfoPtr = new ControlInfo;
06145     ControlInfoPtr->pControlWnd = hGadget;
06146     ControlInfoPtr->lpfnOldProc = (FARPROC) GetWindowLong(hGadget, GWL_WNDPROC);
06147 
06148     // Store the button control info in the dialog's Edit control info list
06149     GetControlList( DialogWnd )->AddHead(ControlInfoPtr);
06150 
06151     FARPROC lpfnDualFn = MakeProcInstance((FARPROC) DialogManager::RgtMouseButtonProc,
06152                                         AfxGetApp()->m_hInstance);
06153 
06154     // Subclass the control so that it calls the new button proc
06155     SetWindowLong(hGadget, GWL_WNDPROC, (INT32) lpfnDualFn );
06156 #endif
06157 }
06158 
06159 /********************************************************************************************
06160 
06161 >   BOOL DialogManager::MakeListBoxDragable(CWindowID DialogWnd,
06162                                             CGadgetID ListGadget)
06163 
06164 
06165     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06166     Created:    16/12/93
06167     Inputs:     DialogWnd:  The dialogbox window identifier
06168                 ListGadget: The Identifier of a listbox gadget
06169     Outputs:    -
06170     Returns:    TRUE if successful, otherwise FALSE
06171     Purpose:
06172     Errors:     An ENSURE failure will occur if ListGadget is not a ListBox control
06173     SeeAlso:    DialogOP::MakeListBoxDragable
06174 
06175 ********************************************************************************************/
06176 
06177 
06178 BOOL DialogManager::MakeListBoxDragable(CWindowID WindowID,
06179                                         CGadgetID Gadget)
06180 {
06181     // This function should only be called for a LISTBOX control
06182     // For the time being, we do this by Hide/Unhide
06183     wxWindow * pGadget = GetGadget(WindowID, Gadget);
06184     if (!pGadget) return FALSE;
06185 #if _DEBUG
06186     ENSURE( pGadget->IsKindOf( CLASSINFO( wxListBox ) ),
06187             "MakeListBoxDragable function called\non a gadget which is not a Listbox" );
06188 #endif
06189 
06190     return TRUE;                                        // pretend worked
06191 }
06192 
06193 
06194 /********************************************************************************************
06195 
06196 >   INT32 FAR PASCAL EXPORT DialogManager::ValidateEditGadgetProc(HWND hwnd,
06197                                                                 UINT32 message,
06198                                                                 UINT32 wParam,
06199                                                                 INT32 lParam)
06200 
06201 
06202     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06203     Created:    24/8/93
06204     Inputs:     hwnd
06205                 message
06206                 wParam
06207                 lParam
06208     Outputs:    -
06209     Returns:    -
06210     Purpose:    subclassed edit control proc
06211     Errors:     -
06212     SeeAlso:    -
06213 
06214 ********************************************************************************************/
06215 
06216 INT32 FAR PASCAL EXPORT DialogManager::ValidateEditGadgetProc( wxWindow *pWnd,
06217                                                             UINT32 message,
06218                                                             UINT32 wParam,
06219                                                             INT32 lParam)
06220 {
06221     PORTNOTETRACE("dialog","DialogManager::DualFunctionButton - do nothing");
06222 #ifndef EXCLUDE_FROM_XARALX
06223     // We need to access the control's dialog window to find the valid characters the control
06224     // should accept.
06225 
06226     HWND DlgWin = GetParent(hwnd);
06227 
06228     // --------------------------------------------------------------------------------------
06229     // Search the dialog's edit control list to find the information about the control
06230     List* ControlInfoList = GetControlList(DlgWin);
06231     ControlInfo* CurrentCntrl = (ControlInfo*)ControlInfoList->GetHead();
06232     // The lookup must be as quick as possible
06233     while (CurrentCntrl != NULL)
06234     {
06235         if (CurrentCntrl->ControlWnd == hwnd)
06236             break;
06237         CurrentCntrl = (ControlInfo*)ControlInfoList->GetNext(CurrentCntrl);
06238     }
06239 
06240     ENSURE(CurrentCntrl != NULL, "Could not find information for a typed edit control");
06241 
06242     // Load in the valid input characters for the edit control
06243     String_256 ValidChars;
06244     ValidChars.Load(CurrentCntrl->IDSValidCh, NULL);
06245 
06246     if (message == WM_CHAR) // Character message
06247     {
06248 
06249         BOOL CharValid = FALSE;
06250 
06251         INT32 LenValidChars = ValidChars.Length();
06252         TCHAR KeyCh = ((TCHAR)wParam);
06253         for (INT32 i=0; ( (i < LenValidChars) && (!CharValid) ); i++)
06254             if (((TCHAR*)ValidChars)[i] == (TCHAR)KeyCh)
06255             {
06256                 CharValid = TRUE;
06257             }
06258         if (!CharValid)
06259         {
06260             // Check if the character is a special control character
06261             if ((KeyCh != (TCHAR)'\b') && // backspace
06262                 (KeyCh != (TCHAR)'\t') && // tab
06263                 (KeyCh != (TCHAR)'\n') && // linefeed
06264                 (KeyCh != (TCHAR)'\r'))   // carriage return
06265 
06266                 return (0);   // An invalid character was input.
06267         }
06268     }
06269     else if (message==WM_DESTROY)
06270         DeleteControlList( hwnd );
06271 
06272     return CallWindowProc((WNDPROC)(CurrentCntrl->lpfnOldProc), hwnd, message, wParam, lParam);
06273 #else
06274     return 0;
06275 #endif
06276 }
06277 
06278 /********************************************************************************************
06279 
06280 >   INT32 FAR PASCAL EXPORT DialogManager::RgtMouseButtonProc(HWND hwnd,
06281                                                         UINT32 message,
06282                                                         UINT32 wParam,
06283                                                         INT32 lParam)
06284 
06285     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06286     Created:    7/9/93
06287     Inputs:     hwnd
06288                 message
06289                 wParam
06290                 lParam
06291     Outputs:    -
06292     Returns:    -
06293     Purpose:    subclassed button control proc
06294     Errors:     -
06295     SeeAlso:    -
06296 
06297 ********************************************************************************************/
06298 INT32 FAR PASCAL EXPORT DialogManager::RgtMouseButtonProc( wxWindow *pWnd,
06299                                                         UINT32 message,
06300                                                         UINT32 wParam,
06301                                                         INT32 lParam)
06302 {
06303     PORTNOTETRACE("dialog","DialogManager::DualFunctionButton - do nothing");
06304 #ifndef EXCLUDE_FROM_XARALX
06305     // We need to access the control's dialog window to find the old proc
06306     HWND DlgWin = GetParent(hwnd);
06307 
06308     // --------------------------------------------------------------------------------------
06309     // Search the dialog's control list to find the information about the control
06310     List* ControlInfoList = GetControlList(DlgWin);
06311     ControlInfo* CurrentCntrl = (ControlInfo*)ControlInfoList->GetHead();
06312     // The lookup must be as quick as possible
06313     while (CurrentCntrl != NULL)
06314     {
06315         if (CurrentCntrl->ControlWnd == hwnd)
06316             break;
06317         CurrentCntrl = (ControlInfo*)ControlInfoList->GetNext(CurrentCntrl);
06318     }
06319 
06320     ENSURE(CurrentCntrl != NULL, "Could not find information for a dual function button");
06321     if ((message == WM_RBUTTONDOWN) || (message == WM_RBUTTONUP))
06322     {
06323 
06324         // Set the state of the button
06325         wParam = (message == WM_RBUTTONDOWN) ? 1:0;
06326         message = BM_SETSTATE;
06327         lParam = 0L;
06328         CallWindowProc((WNDPROC)(CurrentCntrl->lpfnOldProc), hwnd, message, wParam, lParam);
06329 
06330         // Send Command message to the control's parent dialog
06331         if (wParam == 1) // WM_RBUTTONDOWN message
06332         #if WIN32
06333             SendMessage(DlgWin, WM_COMMAND, MAKEINT32(GetWindowLong(hwnd, GWL_ID),BN_RGT_CLICKED), LPARAM(hwnd));
06334         #else
06335             SendMessage(DlgWin, WM_COMMAND, GetWindowWord(hwnd, GWW_ID), MAKEINT32(hwnd,BN_RGT_CLICKED));
06336         #endif
06337     }
06338     else if (message==WM_DESTROY)
06339         DeleteControlList( hwnd );
06340     return CallWindowProc((WNDPROC)(CurrentCntrl->lpfnOldProc), hwnd, message, wParam, lParam);
06341 #else
06342     return 0;
06343 #endif
06344 }
06345 
06346 /********************************************************************************************
06347 
06348 >   static void DialogManager::DeInit()
06349 
06350     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06351     Created:    8/9/93
06352     Inputs:     -
06353     Outputs:    -
06354     Returns:    -
06355     Purpose:    Deinitialise the DialogManager
06356     Errors:     -
06357     SeeAlso:    -
06358 
06359 ********************************************************************************************/
06360 
06361 void DialogManager::DeInit()
06362 {
06363     // Because this function is called from CCamApp::SaveAllModified, of all places,
06364     // it gets called twice on system shutdown (once on receipt of WM_QUERYENDSESSION,
06365     // which itself calls CCamApp::SaveAllModified, and once on receipt of WM_ENDSESSION,
06366     // which performs a SC_CLOSE system command which ultimately also calls SaveAllModified.
06367     // This flags is a bodge for v1.1 to stop this happening, a better solution would be
06368     // to rewrite the dialog manager to be more rational.
06369 
06370     // It's not currently broken this way changed TRACE to ERROR3- Alex
06371 
06372     static BOOL fCalledOnceBodge = FALSE;
06373     if (!fCalledOnceBodge) fCalledOnceBodge = TRUE;
06374     else
06375     {
06376         ERROR3( wxT("DialogManager::DeInit called twice - please fix me properly sometime\n") );
06377         return;
06378     }
06379 
06380     // save current bar state - this should check whether save prefs on exit is set!!!!
06381 PORTNOTE("dialog","Removed IsFullScreenMode usage")
06382 #ifndef EXCLUDE_FROM_XARALX
06383     if( GetMainFrame()->IsFullScreenMode() )
06384         DialogBarOp::WriteNamedBars("clean");
06385     else
06386         DialogBarOp::WriteNamedBars("normal");
06387 #endif
06388 
06389     // Send a CANCEL message to all open dialogs
06390     BROADCAST_TO_CLASS(DialogMsg(NULL, DIM_CANCEL, 0), DialogOp);
06391     // BODGE Special nasty stuff for v1 release.
06392 
06393     // InformationBarOp is completely deaf to the message broadcast above so we must
06394     // make sure their windows are destroyed (manually)
06395     InformationBarOp::SetVisibility(FALSE, TRUE);
06396 
06397     // Delete all Dialog position info
06398     ListItem* DlgPos = DialogPositionList.GetHead();
06399     ListItem* NextPos;
06400     while (DlgPos != NULL)
06401     {
06402         // Make sure that all dialogs have been deleted.
06403         ENSURE( ((DialogPosition*)DlgPos)->DlgWinList.IsEmpty(),
06404             "Live Dialog box found whilst destoying dialog manager");
06405 
06406         NextPos =  DialogPositionList.GetNext(DlgPos);
06407         delete DialogPositionList.RemoveItem(DlgPos);
06408         DlgPos = NextPos;
06409     }
06410     // We do not delete s_pPaneInfoHash here because the preferences have not been written out
06411 }
06412 
06413 /********************************************************************************************
06414 
06415 >   DialogManager::~DialogManager()
06416 
06417     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06418     Created:    8/9/93
06419     Inputs:     -
06420     Outputs:    -
06421     Returns:    -
06422     Purpose:    DialogManager destructor.
06423     Errors:     -
06424     SeeAlso:    DialogManager::DeInit
06425 
06426 ********************************************************************************************/
06427 
06428 DialogManager::~DialogManager()
06429 {
06430 }
06431 
06432 /********************************************************************************************
06433 
06434 >   List* DialogManager::GetControlList(HWND hWnd)
06435 
06436     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06437     Created:    29/4/94
06438     Inputs:     A Window handle
06439     Outputs:    -
06440     Returns:    A pointer to its special list, or NULL if it doesn't have one.
06441     Purpose:    Hide the mechanism we use to attach our lists to various windows. In fact we
06442                 use window properties.
06443     Errors:     -
06444     SeeAlso:    -
06445     Scope:      Private, static
06446 
06447 ********************************************************************************************/
06448 
06449 List *DialogManager::GetControlList( CWindowID hWnd )
06450 {
06451     PORTNOTETRACE("dialog","DialogManager::GetControlList - do nothing");
06452 #ifndef EXCLUDE_FROM_XARALX
06453     HANDLE Prop = GetProp( hWnd, MAKEINTATOM(GetListAtom) );    // Atoms & Properties are fast
06454     if (Prop)
06455     {
06456     #if WIN32
06457         return (List*)(INT32)Prop;
06458     #else
06459         HANDLE Seg = GetProp( hWnd, MAKEINTATOM(GetListAtomSegment) );
06460         INT32 ptr = MAKEINT32( Prop, Seg );
06461         return (List*)ptr;
06462     #endif
06463     }
06464     else
06465 #endif
06466         return NULL;
06467 }
06468 
06469 /********************************************************************************************
06470 
06471 >   void DialogManager::DeleteControlList(HWND hWnd)
06472 
06473     Author:     Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
06474     Created:    14/11/94
06475     Inputs:     A Window handle
06476     Purpose:    Deletes the Properties that are used to store the ControlList. Should be
06477                 called as the very last thing before the Window is vaped e.g. in response
06478                 to a WM_DESTROY message. Destroying it earlier will cause GetControlList
06479                 to return NULL which proves fatal within the various message handlers.
06480     Scope:      Private, static
06481 
06482 ********************************************************************************************/
06483 
06484 void DialogManager::DeleteControlList( CWindowID hWnd )
06485 {
06486     PORTNOTETRACE("dialog","DialogManager::DeleteControlList - do nothing");
06487 #ifndef EXCLUDE_FROM_XARALX
06488     RemoveProp( hWnd, MAKEINTATOM(GetListAtom) );
06489 #ifndef WIN32
06490     RemoveProp( hWnd, MAKEINTATOM(GetListAtomSegment) );
06491 #endif
06492 #endif
06493 }
06494 
06495 
06496 
06497 // This macro aligns a BYTE ptr to a dword boundary
06498 #if WIN32
06499 #define DWORD_ALIGN(x)  if( DWORD_PTR(x) % 4 ) x = ADDR(( DWORD_PTR(x) + 3 ) & ~3);
06500 #else
06501 #define DWORD_ALIGN(x)
06502 #endif
06503 
06504 
06505 /********************************************************************************************
06506 
06507 >   LPWSTR DialogManager::MovePastWideStr(LPWSTR pWideStr)
06508 
06509     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
06510     Created:    11/11/93
06511     Inputs:     pWideStr - the start of the string to skip
06512     Returns:    Address of first byte past the end of the string.
06513     Purpose:    Given a ptr to the first byte in a wide string (or char string if win16)
06514                 return a ptr to the byte past the null.
06515 
06516 ********************************************************************************************/
06517 
06518 LPWSTR DialogManager::MovePastWideStr(LPWSTR pWideStr)
06519 {
06520     // Skip the string
06521     while (*pWideStr++)
06522         ;
06523 
06524     // Return the address of the following character
06525     return pWideStr;
06526 }
06527 
06528 /********************************************************************************************
06529 
06530 >   size_t DialogManager::SizeDlgHeader(DLGTEMPLATE *pHeader)
06531 
06532     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
06533     Created:    11/11/93
06534     Inputs:     pHeader - start of the dialog box header.
06535     Returns:    Size of the dialog box header.
06536     Purpose:    Given a ptr to DIALOGBOXHEADER, return its size.
06537 
06538 ********************************************************************************************/
06539 
06540 
06541 size_t DialogManager::SizeDlgHeader(DLGTEMPLATE *pHeader)
06542 {
06543     // Move past the header
06544     ADDR pResult = (ADDR) (pHeader + 1);
06545 
06546     // skip szMenuName
06547 
06548     #if WIN32
06549 
06550     pResult = (ADDR) MovePastWideStr((LPWSTR) pResult);
06551 
06552     #else
06553 
06554     switch (*pResult++)
06555     {
06556         // See SDK help file (Dialog Box Resource) for details
06557         case 0:
06558             break;
06559 
06560         case 0xFF:
06561             pResult += 2;
06562             break;
06563 
06564         default:
06565             pResult += camStrlen((LPTCHAR) (pResult)) + 1;
06566             break;
06567     }
06568 
06569     #endif
06570 
06571     // then skip szClassName
06572 
06573     pResult = (ADDR) MovePastWideStr((LPWSTR) pResult);
06574 
06575     // then the caption
06576 
06577     pResult = (ADDR) MovePastWideStr((LPWSTR) pResult);
06578 
06579 PORTNOTE("dialog","Removed DLGTEMPLATE usage")
06580 #ifndef EXCLUDE_FROM_XARALX
06581     // then the font stuff
06582     if( (pHeader->style) & DS_SETFONT )
06583         pResult = (ADDR) MovePastWideStr((LPWSTR) (pResult + 2));       // skip font size too
06584 #endif
06585 
06586     DWORD_ALIGN(pResult);
06587 
06588     // Compute the size of the header and return it.
06589     return (size_t) (pResult - ((ADDR) pHeader));
06590 }
06591 
06592 
06593 /********************************************************************************************
06594 
06595 >   size_t DialogManager::SizeCtrlData(DLGITEMTEMPLATE *pData)
06596 
06597     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
06598     Created:    11/11/93
06599     Inputs:     pData - the start of the control structure.
06600     Returns:    Size of the control data.
06601     Purpose:    Given a ptr to a controldata struct, return its length.
06602                 Under Win32, all strings are UniCode (as they are in the res file).
06603 
06604 ********************************************************************************************/
06605 
06606 size_t DialogManager::SizeCtrlData(DLGITEMTEMPLATE *pControl)
06607 {
06608     #if WIN32
06609     // Get pointer to the data after the DLGITEMTEMPLATE structure.
06610     WORD *pData = (WORD *) (pControl + 1);
06611 
06612     // Skip the class
06613     if (*pData == 0xFFFF)
06614         // There is only one more word - the atom of the window class - skip it.
06615         pData += 2;
06616     else
06617         // The class is specified as a string - skip it
06618         pData = (WORD *) MovePastWideStr((LPWSTR) pData);
06619 
06620     // Skip the 'title' array
06621     if (*pData == 0xFFFF)
06622         // There is only one more word - it is a resource ID - skip it.
06623         pData += 2;
06624     else
06625         // The title array is a string - skip it
06626         pData = (WORD *) MovePastWideStr((LPWSTR) pData);
06627 
06628     // Skip the creation data.
06629     UINT32 Extra = (UINT32) *pData;
06630     pData++;
06631 
06632     #else
06633     // Get pointer to the data after the DLGITEMTEMPLATE structure.
06634     ADDR pData = (ADDR) (pControl + 1);
06635 
06636     // Skip the class
06637     if ((*pData) & 0x80)
06638         pData++;
06639     else
06640         pData = (ADDR) MovePastWideStr((LPWSTR) pData);
06641 
06642     // Skip the 'text' array
06643     pData = (ADDR) MovePastWideStr((LPWSTR) pData);
06644 
06645     // Skip the creation data.
06646     BYTE Extra = *pData;
06647     pData++;
06648 
06649     #endif
06650 
06651     // Get end pointer and double-word align it.
06652     ADDR pEnd = (ADDR) pData;
06653     DWORD_ALIGN(pEnd);
06654 
06655     // Compute size of control data and return it.
06656     ADDR pStart = (ADDR) pControl;
06657     pEnd += Extra;
06658     return (size_t) (pEnd - pStart);
06659 }
06660 
06661 /********************************************************************************************
06662 
06663 >   DLGTEMPLATE *DialogManager::MergeDialog(HINSTANCE MainInst,  CDlgResID MainID,
06664                                             HINSTANCE OtherInst, CDlgResID OtherID)
06665 
06666     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
06667     Created:    11/11/93
06668     Inputs:     MainInst - handle of the module containing the 'Main' dialog template.
06669                 MainID - ID of the main dialog resource
06670                 OtherInst - handle of the module containing the 'Other' dialog template.
06671                 OtherID - ID of the other dialog resource
06672     Returns:    Pointer to a block of memory which contains a dialog template which is the
06673                 result of merging the two templates into one.
06674     Purpose:    Merge two dialogs together into one dialog template.
06675                 The return value points to the new merged dialog, which the caller should
06676                 pass to CreateDialogIndirect().  Once the dialog has been created using this
06677                 block, CCFree() should be called on the block to return it to the system
06678                 pool.
06679                 The significance of the 'Main' and 'Other' names is that the dialog style
06680                 (border, menuname, classname, title and font) is taken from 'Main' - the
06681                 header of 'Other' is discarded.
06682     SeeAlso:    CCFree()
06683 
06684 ********************************************************************************************/
06685 
06686 DLGTEMPLATE *DialogManager::MergeDialog( /*HINSTANCE MainInst, */  CDlgResID MainID,
06687                                         /*HINSTANCE OtherInst, */ CDlgResID OtherID)
06688 {
06689     PORTNOTETRACE("dialog","DialogManager::MergeDialog - do nothing");
06690 #ifndef EXCLUDE_FROM_XARALX
06691     HGLOBAL             hGlobal[2];
06692     HRSRC               hRes[2];
06693     DLGTEMPLATE        *pDlg[2];
06694     INT32               HeaderSize[2];
06695     ADDR                pNew,
06696                         pOld;
06697     INT32               Size;
06698     DLGTEMPLATE        *pHeader;
06699 
06700     #if WIN32
06701     WORD                Count, Total;
06702     #else
06703     BYTE                Count, Total;
06704     #endif
06705 
06706     size_t              Len[2],
06707                         ItemSize;
06708     UINT32              xOffset = 0;
06709 
06710     // Find, load and lock the dialog resources
06711     hRes[0] = FindResource(MainInst, MAKEINTRESOURCE(MainID), RT_DIALOG);
06712     hGlobal[0] = LoadResource(MainInst, hRes[0]);
06713     pDlg[0] = (DLGTEMPLATE *) LockResource(hGlobal[0]);
06714 
06715     hRes[1] = FindResource(OtherInst, MAKEINTRESOURCE(OtherID), RT_DIALOG);
06716     hGlobal[1] = LoadResource(OtherInst, hRes[1]);
06717     pDlg[1] = (DLGTEMPLATE *) LockResource(hGlobal[1]);
06718 
06719     // Calculate how big they each are, excluding header.
06720     // We would ideally use GlobalSize to find this, but it doesn't work under NT.
06721 
06722     Total = 0;
06723 
06724     for (UINT32 i = 0; i <= 1; i++)
06725     {
06726         Count = pDlg[i]->cdit;
06727         Total += Count;
06728         HeaderSize[i] = SizeDlgHeader(pDlg[i]);
06729         pOld = ((ADDR) pDlg[i]) + HeaderSize[i];
06730         Len[i] = 0;
06731 
06732         while (Count--)
06733         {
06734             DLGITEMTEMPLATE *pControl = (DLGITEMTEMPLATE *) pOld;
06735 
06736             // Find out how big the control is
06737             ItemSize = SizeCtrlData(pControl);
06738 
06739             // Update the right margin limit if this is the main dialog
06740             if (i == 0)
06741             {
06742                 UINT32 xLimit = pControl->x + pControl->cx;
06743                 xOffset= max(xOffset, xLimit);
06744             }
06745 
06746             // Update the length and move on to the next control
06747             Len[i] += ItemSize;
06748             pOld += ItemSize;
06749         }
06750     }
06751 
06752     // Allocate a new one, using header size + each data size.
06753     // The header of 'Main' is used for the new dialog.
06754     Size = SizeDlgHeader(pDlg[0]);
06755     pNew = (ADDR) CCMalloc(Size + Len[0] + Len[1]);
06756 
06757     // Copy in the header...
06758     memcpy( pNew, pDlg[0], (size_t) Size );
06759 
06760     pHeader = (DLGTEMPLATE *) pNew;     // new header now
06761     pNew += Size;
06762 
06763     // ... then data[0] ...
06764     memcpy(pNew, ((ADDR) pDlg[0]) + HeaderSize[0], Len[0]);
06765     pNew += Len[0];
06766 
06767     // ... and then data[1].
06768     memcpy(pNew, ((ADDR) pDlg[1]) + HeaderSize[1], Len[1]);
06769 
06770     // Fixup count in new header.
06771     pHeader->cdit = Total;
06772 
06773     // Now move all the controls in the sub-dialog to the right so they don't overlap with
06774     // the controls in the main dialog.
06775     Count = pDlg[1]->cdit;
06776 
06777     while (Count--)
06778     {
06779         DLGITEMTEMPLATE *pControl = (DLGITEMTEMPLATE *) pNew;
06780 
06781         // Shift the control to the right
06782         pControl->x += xOffset;
06783 
06784         // Move on to the next control
06785         pNew += SizeCtrlData(pControl);
06786     }
06787 
06788     // now its safe to free up the resource handles
06789     // Note: hRes handles never freed - how can you do this?
06790 
06791     UnlockResource(hGlobal[0]);
06792     FreeResource(hGlobal[0]);
06793 
06794     UnlockResource(hGlobal[1]);
06795     FreeResource(hGlobal[1]);
06796 
06797     return pHeader;
06798 #else
06799     return NULL;
06800 #endif
06801 }
06802 
06803 
06804 /********************************************************************************************
06805 
06806 >   static BOOL DialogManager::IsADialogWindow(HWND hwnd)
06807 
06808 
06809     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06810     Created:    17/3/94
06811     Inputs:     -
06812     Outputs:    -
06813     Returns:    Returns TRUE if hwnd is the window handle of a dialog
06814     Purpose:    To determine if hwnd is the handle of a dialog
06815     Errors:     -
06816     SeeAlso:    -
06817 
06818 ********************************************************************************************/
06819 
06820 BOOL DialogManager::IsADialogWindow( wxWindow *pWnd )
06821 {
06822     return( DialogOp::IsADialogWindow( pWnd ) );
06823 }
06824 
06825 /********************************************************************************************
06826 
06827 >   static BOOL DialogManager::ModalDialogOpen(DialogOp** pModal)
06828 
06829 
06830     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06831     Created:    17/3/94
06832     Inputs:     -
06833     Outputs:    An optional pointer to the modal dialog which is ope
06834     Returns:    Returns TRUE if a modal dialog is open
06835     Purpose:    To determine if there is currently an open modal dialog
06836     Errors:     -
06837     SeeAlso:    -
06838 
06839 ********************************************************************************************/
06840 
06841 BOOL DialogManager::ModalDialogOpen(DialogOp** pModal)
06842 {
06843     // Obtain the list of all Dialogs
06844     List* DialogClassList = MessageHandler::GetClassList(CC_RUNTIME_CLASS(DialogOp));
06845     ENSURE(DialogClassList != NULL, "Could not find DialogOp message handler list");
06846 
06847     // Look for an open modal dialog
06848     for (MessageHandler* pMsgHandler = (MessageHandler*)DialogClassList->GetHead();
06849         pMsgHandler != NULL;
06850         pMsgHandler = (MessageHandler*)DialogClassList->GetNext(pMsgHandler))
06851     {
06852         ENSURE(pMsgHandler->IsKindOf(CC_RUNTIME_CLASS(DialogOp)),
06853             "MessageHandler of DialogOp class list is not a DialogOp");
06854         if (pMsgHandler->IsKindOf(CC_RUNTIME_CLASS(DialogOp)))
06855         {
06856             // Ok we got ourselves a DialogOp
06857             DialogOp* pDlgOp = (DialogOp*)pMsgHandler;
06858             // Is the dialog open ?
06859             if (pDlgOp->WindowID != NULL)
06860             {
06861                 // Is the Dialog modal
06862                 if (pDlgOp->IsModal() )
06863                 {
06864                     if (pModal != NULL)
06865                     {
06866                         *pModal = pDlgOp;
06867                     }
06868                     return TRUE; // found one
06869                 }
06870             }
06871         }
06872     }
06873     return FALSE; // No modal dialog's open
06874 }
06875 
06876 /********************************************************************************************
06877 
06878 >   static BOOL DialogManager::IsWindowVisible(CWindowID Win)
06879 
06880 
06881     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06882     Created:    30/11/94
06883     Inputs:     -
06884     Outputs:    -
06885     Returns:    TRUE if Win is visible
06886     Purpose:    To test the visibility of Win
06887     Errors:     -
06888     SeeAlso:    -
06889 
06890 ********************************************************************************************/
06891 
06892 BOOL DialogManager::IsWindowVisible(CWindowID Win)
06893 {
06894     return ( (wxWindow *)Win )->IsShown();
06895 }
06896 
06897 /********************************************************************************************
06898 
06899 >   BOOL DialogManager::IsCustomComboDropdownVisible(CWindowID WindowID, CGadgetID Gadget)
06900 
06901 
06902     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06903     Created:    21/2/2000
06904     Inputs:     -
06905     Outputs:    -
06906     Returns:    TRUE if WinID's dropdown is visible
06907     Purpose:    To test the visibility of WinID's dropdown
06908     Errors:     -
06909     SeeAlso:    -
06910 
06911 ********************************************************************************************/
06912 
06913 BOOL DialogManager::IsCustomComboDropdownVisible(CWindowID WindowID, CGadgetID Gadget)
06914 {
06915     PORTNOTETRACE("dialog","DialogManager::IsCustomComboDropdownVisible - do nothing");
06916 #ifndef EXCLUDE_FROM_XARALX
06917     String_256 ClassNameStr;  // The control type
06918 
06919     HWND hGadget = GetDlgItem((HWND)WindowID, (INT32)Gadget);
06920     // Find out the class type of the gadget
06921     GetClassName(hGadget, (TCHAR*)ClassNameStr, 255);
06922 
06923     if ((ClassNameStr == String_64(TEXT("cc_1dBitmapComboBoxEdit"))) ||
06924         (ClassNameStr == String_64(TEXT("cc_2dBitmapComboBoxEdit")))   )
06925     {
06926         BOOL RetVal = FALSE;
06927 
06928         RetVal = SendMessage (hGadget, WM_CCQUERYDROPDOWN, (WPARAM) (0), (LPARAM) 0);
06929 
06930         return (RetVal);
06931     }
06932     return (TRUE);
06933     ENSURE(FALSE, "Calling IsCustomComboDropdownVisible for an invalid control");
06934 #endif
06935     return FALSE;
06936 }
06937 
06938 /********************************************************************************************
06939 
06940 >   BOOL DialogManager::CloseDropdown (CWindowID WindowID, CGadgetID Gadget, BOOL CloseVal)
06941 
06942 
06943     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
06944     Created:    21/2/2000
06945     Inputs:     -
06946     Outputs:    -
06947     Returns:    TRUE if things went ok
06948     Purpose:    Used to close the controls dropdown.  This routine was written because of
06949                 the amount of trouble that I was experiencing with my custom controls
06950                 down to escape key processing (which is viewed as a hotkey within camelot).
06951     Errors:     -
06952     SeeAlso:    -
06953 
06954 ********************************************************************************************/
06955 
06956 BOOL DialogManager::CloseDropdown (CWindowID WindowID, CGadgetID Gadget, BOOL CloseVal)
06957 {
06958 PORTNOTE("dialog","Programatic CB drop not supported by wx")
06959     return (TRUE);
06960 }
06961 
06962 /********************************************************************************************
06963 
06964 >   wxPropertySheetDialog* DialogManager::GetPropertySheetFromOp( DialogTabOp* pDialogTabOp )
06965 
06966     Author:     Luke_Hart (xara group ltd) <lukeh@xara.com>
06967     created:    28/04/06
06968     inputs:     pdialogtabop: the operation we wish to find the property sheet for
06969     outputs:    -
06970     returns:    The associated Property sheet (or NULL if none)
06971     purpose:    Find the property sheet associated with the passed DialogTabOp
06972     errors:     -
06973     seealso:    -
06974 
06975 ********************************************************************************************/
06976 
06977 wxPropertySheetDialog* DialogManager::GetPropertySheetFromOp( DialogTabOp* pDialogTabOp )
06978 {
06979     wxWindow * pWindow = pDialogTabOp->WindowID;
06980     return pWindow->IsKindOf(CLASSINFO(wxPropertySheetDialog))?(wxPropertySheetDialog*)pWindow:NULL;
06981 }
06982 
06983 /********************************************************************************************
06984 
06985 >   BOOL DialogManager::AddAPage(DialogTabOp* pDialogTabOp, CDlgResID DialogResID, CGadgetID Gadget=0)
06986 
06987     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
06988     Created:    22/11/94
06989     Inputs:     pDialogTabOp: The operation we wish to add a page too
06990                 DialogResID:  The resource ID of the dialog page we wish to add to the
06991                             DialogTabOp
06992                 Gadget        The gadget of the book control to add the page to (or zero to
06993                             take a good guess)
06994     Outputs:    -
06995     Returns:    TRUE if the page was added successfully.
06996     Purpose:    Adds a page to the tabbed dialog with resource ID DialogResID.
06997     Errors:     -
06998     SeeAlso:    -
06999 
07000 ********************************************************************************************/
07001 
07002 
07003 BOOL DialogManager::AddAPage(DialogTabOp* pDialogTabOp, CDlgResID DialogResID, CGadgetID Gadget)
07004 {
07005     // Try to add the page to the property sheet associated with the DialogTabOp
07006     // let's try and find it
07007     wxBookCtrlBase* pNoteBook = GetBookControl(pDialogTabOp->WindowID, Gadget);
07008 
07009     // We need to create a page object
07010     // Because wxNotebookPage is derived from an MFC object we have to cope with exceptions
07011     wxWindow*   pNewPage;
07012     wxString    ObjectName;
07013     try
07014     {
07015         const TCHAR* pDialogName=CamResource::GetObjectNameFail( DialogResID );
07016         ERROR1IF(pDialogName == NULL, FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
07017         TRACEUSER( "jlh92", _T("Cre tab %s\n"), pDialogName );
07018         ObjectName = pDialogName;
07019 
07020         pNewPage = wxXmlResource::Get()->LoadPanel( pNoteBook, pDialogName );
07021         ERROR1IF(pNewPage == NULL, FALSE, _R(IDE_CANNOT_CREATE_DIALOG));
07022         pNewPage->SetId( DialogResID );
07023 
07024         CamArtProvider::Get()->EnsureChildBitmapsLoaded( pNewPage );
07025     }
07026     catch( CMemoryException )
07027     {
07028         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));
07029     }
07030 
07031     // Just to  be safe
07032     ERROR1IF(pNewPage == NULL, FALSE, _R(IDS_OUT_OF_MEMORY));
07033 
07034     wxString Title = wxEmptyString;
07035     if (pNewPage->IsKindOf(CLASSINFO(wxDialog)))
07036         Title=((wxDialog *)pNewPage)->GetTitle();
07037     if (Title.IsEmpty()) 
07038         Title = pNewPage->GetLabel(); // because wxPanel doesn't seem to support a title
07039     if( Title.IsEmpty() )
07040     {
07041         ResourceID  NameResID = CamResource::GetResourceID( PCTSTR(ObjectName) );
07042         PCTSTR      pszStringLookup = CamResource::GetTextFail( NameResID );
07043         if( NULL != pszStringLookup )
07044         {
07045             Title = pszStringLookup;
07046             TRACEUSER( "jlh92", _T("Page (FST) = \"%s\"\n"), pszStringLookup );
07047         }
07048     }
07049     if( Title.IsEmpty() )
07050     {
07051         // Finally, in desperation, we (mis-)use the tooltip string because now the wx folks have removed
07052         // the label, even though it's needed for accessibility. Aarrghh
07053         wxToolTip* pTip = pNewPage->GetToolTip();
07054         if (pTip) Title=pTip->GetTip();
07055     }
07056 
07057     wxImageList * pImageList = NULL;
07058     wxBitmap b;
07059     // Add images if present
07060     if (pDialogTabOp->HasImages())
07061     {
07062         // Get the image list 
07063         pImageList = pNoteBook->GetImageList();
07064 
07065         wxBitmap * pBitmap = CamArtProvider::Get()->FindBitmap(DialogResID);
07066         if (!pBitmap || (pBitmap==CamArtProvider::Get()->GetMissingBitmap()) || !pBitmap->Ok())
07067         {
07068             TRACEUSER("Phil", _T("Unable to use options tab icon %d\n"), DialogResID);
07069             int /*TYPENOTE: Correct */ w=32;
07070             int /*TYPENOTE: Correct */ h=32;
07071             if (pImageList)
07072                 pImageList->GetSize(0, w, h);
07073             b = wxArtProvider::GetBitmap(wxART_HELP_SETTINGS, wxART_OTHER, wxSize(w, h));
07074         }
07075         else
07076             b= *pBitmap;
07077 
07078         // If there is no image list, create one
07079         if (!pImageList)
07080         {
07081             pImageList = new wxImageList(b.GetWidth(), b.GetHeight());
07082             if (pImageList)
07083                 pNoteBook->AssignImageList(pImageList);
07084         }
07085 
07086     }
07087 
07088     if (pImageList)
07089         pImageList->Add(b);
07090     pNoteBook->AddPage( pNewPage, Title );
07091     if (pImageList)
07092         pNoteBook->SetPageImage(pNoteBook->GetPageCount()-1, pImageList->GetImageCount()-1);
07093 
07094     return true;
07095 }
07096 
07097 /********************************************************************************************
07098 
07099 >   static CWindowID DialogManager::GetPageWindow(CWindowID Win, CDlgResID PageID, INT32* PageIndex = NULL)
07100 
07101     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07102     Created:    28/11/94
07103     Inputs:     Win: The windowID
07104                 PageID: A page resource identifier, If this is not NULL then the WindowID
07105                         must be that of a Property sheet. We ENSURE that this is true.
07106     Outputs:    Optionally returns the page index
07107     Returns:    Window ID of a page within a property sheet
07108     Purpose:    Returns the Window ID of a page within a property sheet. If the page
07109                 is NULL then Win is simply returned, It can be called  on a
07110                 non property sheet dialog. Just pretend that they are property sheets without
07111                 any pages.
07112     Errors:     -
07113     SeeAlso:    -
07114 
07115 ********************************************************************************************/
07116 
07117 CWindowID DialogManager::GetPageWindow(CWindowID Win, CDlgResID PageID, INT32* PageIndex)
07118 {
07119     if (PageID == 0)
07120     {
07121         return Win; // A page is not required
07122     }
07123 
07124     wxBookCtrlBase* pBookCtrl = GetBookControl(Win);
07125     if (!pBookCtrl)
07126     {
07127         ERROR3("No BookControl found");
07128         return Win;
07129     }
07130 
07131     wxNotebookPage* pCurrentPage;
07132 
07133     // Find the window ID of the page
07134     for (UINT32 i = 0; i < pBookCtrl->GetPageCount(); i++)
07135     {
07136         pCurrentPage =  (wxNotebookPage*)(pBookCtrl->GetPage(i));
07137         if (pCurrentPage->GetId() == INT32(PageID) )
07138         {
07139             if (PageIndex != NULL)
07140             {
07141                 *PageIndex = i;
07142             }
07143             // Found page so return window id
07144             return pCurrentPage;
07145         }
07146     }
07147     ERROR3("The page specified does not exist on this tabbed dialog");
07148     return Win; // Probably safer than NULL
07149 }
07150 
07151 /********************************************************************************************
07152 
07153 >   BOOL DialogManager::SetTitlebarName(CWindowID Win, String_256* Name)
07154 
07155     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07156     Created:    1/12/94
07157     Inputs:     Win:  The dialog window
07158                 Name: The titlebar text
07159     Outputs:    -
07160     Returns:    -
07161     Purpose:    Sets the titlebar text of the dialog.
07162     Errors:     -
07163     SeeAlso:    -
07164 
07165 ********************************************************************************************/
07166 
07167 BOOL DialogManager::SetTitlebarName( CWindowID Win, String_256* Name )
07168 {
07169     // iterate to find the TLW
07170     wxWindow * pTLW = (wxWindow *)(Win);
07171     while (pTLW && !pTLW->IsKindOf(CLASSINFO(wxTopLevelWindow)))
07172         pTLW = pTLW->GetParent();
07173 
07174     if (pTLW)
07175         pTLW->SetLabel( (TCHAR *)(*Name) );
07176 
07177     return true;
07178 }
07179 
07180 // -----------------------------------------------------------------------------------------
07181 // Functions to Set and KIll timer events
07182 
07183 /********************************************************************************************
07184 
07185 >   static BOOL DialogManager::SetTimer(DialogOp *pDialogOp, CWindowID WindowID, UINT32 nIDEvent, UINT32 nElapse,
07186                                         void (* lpfnTimer)(void *) = NULL, void * param=NULL, BOOL OneShot =FALSE)
07187 
07188     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07189     Created:    15/4/97
07190     Inputs:     hWnd        Handle of window for timer messages
07191                 nIDEvent    Specifies a nonzero timer identifier.
07192                 nElapse     Specifies the time-out value, in milliseconds.
07193     Returns:    The timer identifier of the new timer if Nonzero, Zero means a problem.
07194     Purpose:    Allows the user access to setting a timer caller back or event for a dialog box.
07195                 The caller can either specify a call back procedure to be called when the timer
07196                 goes off or if null is specified, a DIM_TIMER message will be sent.
07197                 This maps onto the Windows API/CWnd call.
07198                 The return value is effectively the handle onto the timer system. It must be
07199                 passed to the KillTimer member function to kill the timer. A Nonzero value
07200                 indicates successful allocation of the timer; non-zero implies a problem.
07201 
07202     Note:       DIM_TIMER code is not tested.
07203 
07204     SeeAlso:    DialogOp::KillTimer; DialogOp::SetTimer;
07205 
07206 ********************************************************************************************/
07207 
07208 UINT32 DialogManager::SetTimer( DialogOp *pDialogOp, CWindowID WindowID, UINT32 nIDEvent, UINT32 nElapse,
07209                                 void (* lpfnTimer)(void *)/* = NULL*/, void * param/*=NULL*/, BOOL OneShot /*=FALSE*/)
07210 {
07211     if (!pDialogOp || !pDialogOp->pEvtHandler)
07212         return 0;
07213 
07214     return pDialogOp->pEvtHandler->AddTimer(pDialogOp, nIDEvent, nElapse, lpfnTimer, param, OneShot);
07215 }
07216 
07217 /********************************************************************************************
07218 
07219 >   static BOOL DialogOp::KillTimer( INT32 nIDEvent )
07220 
07221     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07222     Created:    15/4/97
07223     Inputs:     hWnd        Handle of window for timer messages
07224                 nIDEvent    Specifies a nonzero timer identifier.
07225     Returns:    True if the event was killed, FALSE if the specified timer event could not be found.
07226     Purpose:    Allows the user access to killing a timer caller back or event that has been
07227                 set up for a dialog box.
07228                 Kills the timer event identified by nIDEvent from the earlier call to SetTimer.
07229                 Any pending WM_TIMER messages associated with the timer are removed from the
07230                 message queue.
07231     SeeAlso:    DialogOp::SetTimer; DialogManager::SetTimer;
07232 
07233 ********************************************************************************************/
07234 
07235 BOOL DialogManager::KillTimer( DialogOp *pDialogOp, CWindowID Wnd, INT32 nIDEvent )
07236 {
07237     if (!pDialogOp || !pDialogOp->pEvtHandler)
07238         return 0;
07239 
07240     return pDialogOp->pEvtHandler->DeleteTimer(nIDEvent);
07241 }
07242 
07243 /********************************************************************************************
07244 
07245 >   static BOOL DialogManager::GetWindowPosition(CWindowID WindowID, RECT * pRect)
07246 
07247     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07248     Created:    12/6/97
07249     Inputs:     WindowID    Handle of window
07250     Outputs:    Rect        pointer to the rectangle to fill in
07251     Returns:    True if the call was successful, FALSE otherwise.
07252     Purpose:    Allows the user to get the current window position.
07253     SeeAlso:    DialogOp::GetWindowPosition; DialogManager::SetWindowPosition;
07254 
07255 ********************************************************************************************/
07256 
07257 BOOL DialogManager::GetWindowPosition( CWindowID WindowID, wxRect *pRect )
07258 {
07259     *pRect = wxRect(WindowID->GetPosition(), WindowID->GetSize());
07260     return TRUE;
07261 }
07262 
07263 BOOL DialogManager::GetWindowPosition( CWindowID WindowID, RECT *pRect )
07264 {
07265     wxRect Rect;
07266     if (!GetWindowPosition(WindowID, &Rect)) return FALSE;
07267     pRect->bottom=Rect.GetBottom();
07268     pRect->top=Rect.GetTop();
07269     pRect->left=Rect.GetLeft();
07270     pRect->right=Rect.GetRight();
07271     return TRUE;
07272 }
07273 
07274 /********************************************************************************************
07275 
07276 >   static BOOL DialogManager::GetGadgetPosition(CWindowID WindowID, CGadgetID Gadget, RECT * pRect)
07277 
07278     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07279     Created:    12/6/97
07280     Inputs:     WindowID    Handle of window
07281                 Gadget      The icon or gadget that we are interested in.
07282     Outputs:    Rect        pointer to the rectangle to fill in
07283     Returns:    True if the call was successful, FALSE otherwise.
07284     Purpose:    Allows the user to get the current position of the specified gadget or icon.
07285     SeeAlso:    DialogOp::GetGadgetPosition; DialogManager::SetGadgetPosition;
07286 
07287 ********************************************************************************************/
07288 
07289 BOOL DialogManager::GetGadgetPosition( CWindowID WindowID, CGadgetID Gadget, wxRect *pRect )
07290 {
07291     wxWindow * pGadget = GetGadget(WindowID, Gadget);
07292     if (!pGadget) return FALSE;
07293 
07294     // We just need to pass back the normal position of the window
07295     if (pRect)
07296         *pRect = pGadget->GetSize();
07297 
07298     return TRUE;
07299 }
07300 
07301 BOOL DialogManager::GetGadgetPosition( CWindowID WindowID, CGadgetID Gadget, RECT *pRect )
07302 {
07303     wxRect Rect;
07304     if (!GetGadgetPosition(WindowID, Gadget, &Rect)) return FALSE;
07305     pRect->bottom=Rect.GetBottom();
07306     pRect->top=Rect.GetTop();
07307     pRect->left=Rect.GetLeft();
07308     pRect->right=Rect.GetRight();
07309     return TRUE;
07310 }
07311 
07312 /********************************************************************************************
07313 
07314 >   static BOOL DialogManager::SetWindowPosition(CWindowID WindowID, const RECT& Rect)
07315 
07316     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07317     Created:    12/6/97
07318     Inputs:     hWnd        Handle of window
07319                 Rect        New rectangle for the window position
07320     Returns:    True if the call was successful, FALSE otherwise.
07321     Purpose:    Allows the user to set the current window position.
07322     SeeAlso:    DialogOp::SetWindowPosition; DialogManager::GetWindowPosition;
07323 
07324 ********************************************************************************************/
07325 // Technical Note:
07326 // Don't even think of using GetWindowRect or GetClientRect as there are not set equivalents.
07327 // MoveWindow is completely spappy and does not use the same coordinates on client items!!!!
07328 // GetWindowPlacement at least has a SetWindowPlacement form which
07329 // uses the same coordinate system.
07330 
07331 BOOL DialogManager::SetWindowPosition(CWindowID WindowID, const wxRect &Rect)
07332 {
07333     WindowID->SetPosition(Rect.GetTopLeft());
07334     WindowID->SetSize(Rect.GetSize());
07335     return TRUE;
07336 }
07337 
07338 BOOL DialogManager::SetWindowPosition( CWindowID WindowID, const RECT &Rect )
07339 {
07340     return SetWindowPosition( WindowID, wxRect(wxPoint(Rect.left, Rect.top), wxPoint(Rect.right, Rect.bottom)));
07341 }
07342 
07343 /********************************************************************************************
07344 
07345 >   static BOOL DialogManager::SetGadgetPosition(CWindowID WindowID, CGadgetID Gadget, const RECT& Rect)
07346 
07347     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07348     Created:    12/6/97
07349     Inputs:     WindowID    Handle of window
07350                 Gadget      The icon or gadget that we are interested in.
07351                 Rect        New rectangle for the window position
07352     Returns:    True if the call was successful, FALSE otherwise.
07353     Purpose:    Allows the user to set the current position of the specified gadget or icon.
07354     SeeAlso:    DialogOp::SetGadgetPosition; DialogManager::GetGadgetPosition;
07355 
07356 ********************************************************************************************/
07357 
07358 BOOL DialogManager::SetGadgetPosition( CWindowID WindowID, CGadgetID Gadget, const wxRect &Rect )
07359 {
07360     wxWindow * pGadget = GetGadget(WindowID, Gadget);
07361     if (!pGadget) return FALSE;
07362 
07363     pGadget->SetSize( Rect );
07364     return TRUE;
07365 }
07366 
07367 BOOL DialogManager::SetGadgetPosition( CWindowID WindowID, CGadgetID Gadget, const RECT &Rect )
07368 {
07369     return SetGadgetPosition( WindowID, Gadget, wxRect(wxPoint(Rect.left, Rect.top), wxPoint(Rect.right, Rect.bottom)));
07370 }
07371 
07372 /********************************************************************************************
07373 
07374 >   static INT32 DialogManager::GetScreenDpi()
07375 
07376     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07377     Created:    12/6/97
07378     Returns:    0 or the dpi of the screen.
07379     Purpose:    Allows the user to find out the screen dpi.
07380     SeeAlso:    DialogOp::GetScreenDpi;
07381 
07382 ********************************************************************************************/
07383 
07384 INT32 DialogManager::GetScreenDpi()
07385 {
07386     // Get the screen DPI
07387     wxScreenDC          ScreenDC;
07388 PORTNOTE("dialog","Can't handle different DPIs, using X")
07389     return OSRenderRegion::GetFixedDCPPI(ScreenDC).x;
07390 }
07391 
07392 /********************************************************************************************
07393 
07394 >   static BOOL DialogManager::GetScreenSize(INT32 * pWidth, INT32 * pHeight)
07395 
07396     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
07397     Created:    12/6/97
07398     Outputs:    pWidth  the screen width in pixels
07399                 pHeight the screen height in pixels
07400     Returns:    True if worked ok, False otherwise.
07401     Purpose:    Allows the user to find out the screen size.
07402     SeeAlso:    DialogOp::GetScreenDpi;
07403 
07404 ********************************************************************************************/
07405 
07406 BOOL DialogManager::GetScreenSize(INT32 * pWidth, INT32 * pHeight)
07407 {
07408     ERROR2IF(pWidth == NULL || pHeight == NULL,FALSE,"GetScreenSize Bad params!");
07409 
07410     // HORZRES  Width, in pixels, of the screen.
07411     // VERTRES  Height, in raster lines, of the screen.
07412     INT32               Width  = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
07413     INT32               Height = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
07414 
07415     // Tell the caller about the new values
07416     *pWidth = Width;
07417     *pHeight = Height;
07418 
07419     return TRUE;
07420 }
07421 
07422 // -----------------------------------------------------------------------------------------
07423 // Functions to Save and restore the active dialog state
07424 
07425 /********************************************************************************************
07426 
07427 >   static BOOL DialogManager::RecordActiveDialogState()
07428 
07429 
07430     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07431     Created:    14/7/95
07432     Returns:    FALSE if we run out of memory
07433     Purpose:    This function will get called before a MODAL dialog is opened. It records
07434                 which window is currently active, and if the window is a MODAL dialog.
07435                 After a MODAL dialog is closed RestoreActiveDialogState is called to
07436                 restore the active window.
07437     Errors:
07438     SeeAlso:    DialogManager::RestoreActiveDialogState
07439     SeeAlso:    DialogManager::ActiveDlgStack
07440 
07441 ********************************************************************************************/
07442 
07443 BOOL DialogManager::RecordActiveDialogState()
07444 {
07445     // The new way of checking if a modal dialog is about is to determine if the
07446     //ActiveDlgStack is empty
07447     BOOL IsModal = !(ActiveDlgStack.GetTop() == NULL);
07448     // Which window is currently active
07449     wxWindow * ActiveWindow = wxWindow::FindFocus();
07450     
07451     // I think we need to look upwards here till we find a TLW
07452     while (ActiveWindow && !ActiveWindow->IsKindOf(CLASSINFO(wxTopLevelWindow)) && ActiveWindow->GetParent())
07453     {
07454         ActiveWindow = ActiveWindow->GetParent();
07455     }
07456 
07457     // Record this information
07458     ActiveDlgStateItem* pActiveDlgItem = new ActiveDlgStateItem;
07459     if (!pActiveDlgItem)
07460         return FALSE; // Out of memory
07461 
07462     pActiveDlgItem->pActiveWindow   = ActiveWindow;
07463     pActiveDlgItem->fIsAModalDialog = IsModal;
07464 
07465     DialogManager::ActiveDlgStack.Push(pActiveDlgItem);
07466     return TRUE;
07467 }
07468 
07469 /********************************************************************************************
07470 
07471 >   static BOOL RestoreActiveDialogState();
07472 
07473 
07474     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07475     Created:    14/7/95
07476     Purpose:    This function is called after a MODAL dialog is closed. it restores the
07477                 Active window.
07478 
07479     SeeAlso:    DialogManager::RecordActiveDialogState
07480 
07481 ********************************************************************************************/
07482 
07483 void DialogManager::RestoreActiveDialogState()
07484 {
07485     ActiveDlgStateItem *pActiveDlgState = (ActiveDlgStateItem *)ActiveDlgStack.Pop();
07486     ERROR3IF(!pActiveDlgState, "RestoreActiveDialogState called when stack was empty");
07487     if (!pActiveDlgState)
07488         return;
07489 
07490     wxFrame            *MainFrame = GetMainFrame();   // Could be NULL (especially during startup)
07491 
07492     if( NULL != pActiveDlgState->pActiveWindow )
07493     {
07494         // Enable/Disable the mainframe
07495         if (MainFrame)
07496         {
07497             MainFrame->Enable( !pActiveDlgState->fIsAModalDialog );
07498         }
07499 
07500         // Enable the active window
07501         pActiveDlgState->pActiveWindow->Enable( true );
07502 
07503         // Restore the active window
07504         pActiveDlgState->pActiveWindow->SetFocus();
07505 
07506         if( pActiveDlgState->fIsAModalDialog )
07507         {
07508             // Disable all dialogs except the active window
07509             EnableAllDialogs( FALSE, pActiveDlgState->pActiveWindow );
07510         }
07511         else
07512         {
07513             // And all other dialogs
07514             EnableAllDialogs(TRUE);
07515         }
07516     }
07517     else
07518     {
07519         TRACE( wxT("There is no active window to restore. This is expected during startup before the MainFrame has been created\n") );
07520         // This could be an error situation. Enable everything, so that the user is not locked out.
07521 
07522         // Enable the mainframe
07523         if( MainFrame )
07524             MainFrame->Enable( true );
07525 
07526         // And all other dialogs
07527         EnableAllDialogs( TRUE );
07528     }
07529     delete pActiveDlgState;
07530     return;
07531 }
07532 
07533 
07534 /********************************************************************************************
07535 
07536 >   static CDlgResID DialogManager::GetActivePage(CWindowID WindowID, CGadgetID Gadget = 0)
07537 
07538     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
07539     Inputs      WindowID    - The window
07540                 GadgetID    - The gadget of the book control, or zero for none
07541     Created:    23/3/2000
07542     Returns:    the pageID of the currently active page in an open tabbed dialog, or -1 if there isn't one
07543     Purpose:    To find out the currently active page in a tabbed dialog
07544 
07545 Alex unbroke this function which used to take no parameters, meaning it would only
07546 work reliably if only one tabbed dialog was up at a time... So if you are trying to
07547 call it, you now know how to fix your parameters...
07548 
07549 For an unknown reason this function returns -1 if the gadget is not found. Which I think
07550 is wxID_OK. Who knows
07551 
07552 DONT USE THIS FUNCTION
07553 
07554 ********************************************************************************************/
07555 
07556 CDlgResID DialogManager::GetActivePage(CWindowID WindowID, CGadgetID Gadget /*=0*/)
07557 {
07558     // first check to see if we have a property sheet object
07559     wxBookCtrlBase * pBookControl = GetBookControl(WindowID, Gadget);
07560     if (pBookControl == NULL)
07561         return CDlgResID(-1);
07562 
07563     wxNotebookPage* pOurPage = pBookControl->GetCurrentPage();
07564     if (pOurPage == NULL)
07565         return CDlgResID(-1);
07566 
07567     return pOurPage->GetId();
07568 }
07569 
07570 
07571 
07572 
07573 /********************************************************************************************
07574 
07575 >   void DialogManager::SetPropertyPageModified(BOOL Modified)
07576 
07577 
07578     Author:     Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com>
07579     Created:    23/3/2000
07580     Inputs:     the modified value to set
07581     Returns:    -
07582     Purpose:    Sets the modified property of the currently active property page of the current
07583                 tabbed dialog (if it exists)
07584 
07585 THIS ROUTINE IS FUNADAMENTALLY BROKEN - IT IS NOT PASSED A WINDOW ID SO CANNOT COPE
07586 WITH MORE THAN ONE OPEN DIALOG
07587 
07588 ********************************************************************************************/
07589 
07590 void DialogManager::SetPropertyPageModified(BOOL Modified)
07591 {
07592 PORTNOTE( "dialog", "Removed RegisterWindowMessage usage" )
07593 #ifndef EXCLUDE_FROM_XARALX
07594     DlgTabOpToPropShtItem* pTabItem = (DlgTabOpToPropShtItem*)DlgTabOpToPropShtList.GetHead();
07595     if (pTabItem->pPropertySheet != NULL)
07596     {
07597         wxNotebookPage* pActivePage = pTabItem->pPropertySheet->GetActivePage();
07598         if (pActivePage != NULL)
07599             pActivePage->SetModified(Modified);
07600     }
07601 #endif
07602 }
07603 
07604 
07605 /********************************************************************************************
07606 
07607 >   ControlInfo::~ControlInfo()
07608 
07609     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07610     Created:    3/9/93
07611     Inputs:     -
07612     Outputs:    -
07613     Returns:    -
07614     Purpose:    ControlInfo destructor
07615     Errors:     -
07616     SeeAlso:    -
07617 
07618 ********************************************************************************************/
07619 
07620 ControlInfo::~ControlInfo()
07621 {
07622 }
07623 
07624 
07625 
07626 /********************************************************************************************
07627 
07628 >   static BOOL DialogManager::CreateBar(DialogBarOp* DlgOp)
07629 
07630     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07631     Created:    5/12/94
07632     Inputs:     DlgOp:  The DialogBarOp to create
07633     Outputs:    -
07634     Returns:    -
07635     Purpose:    Handles the creation of a bar
07636     Scope:      private
07637     Errors:     -
07638     SeeAlso:    DialogManager::Create
07639 
07640 ********************************************************************************************/
07641 
07642 BOOL DialogManager::CreateBar(DialogBarOp* DlgOp)
07643 {
07644     PORTNOTETRACE("dialog","DialogManager::CreateBar - do nothing");
07645 #ifndef EXCLUDE_FROM_XARALX
07646     BaseBar* DBWnd = NULL;
07647     // We need to create a DialogBar object
07648     if ( DlgOp->IsKindOf(CC_RUNTIME_CLASS(SuperGallery)) )
07649     {
07650 #ifdef EXCLUDE_GALS
07651         return FALSE;
07652 #else
07653         DBWnd = new GalleryBar();
07654 #endif
07655     }
07656     else
07657     {
07658         DBWnd = new DialogBar();
07659     }
07660 
07661 
07662     if (DBWnd != NULL)
07663     {
07664         // Attempt to create the window
07665         if(!(DBWnd->Create((DialogBarOp*)DlgOp)))  // Should set the error code
07666         {
07667             delete DBWnd;
07668         }
07669     }
07670     else
07671     {
07672 
07673         ERROR1(FALSE, _R(IDS_OUT_OF_MEMORY));  // Failed to create the DialogBar
07674     }
07675 #endif
07676     return TRUE;
07677 }
07678 
07679 /********************************************************************************************
07680 
07681 >   static BOOL DialogManager::RelayoutDialog(DialogTabOp* DlgOp)
07682 
07683     Author:     Luke_Hart (Xara Group Ltd) <lukeh@xara.com>
07684     Created:    04/05/06
07685     Inputs:     DlgOp:      The DialogTabOp to re-layout
07686     Outputs:    -
07687     Returns:    -
07688     Purpose:    Force the dialog to relayout after control hide\show
07689     Scope:      public
07690     Errors:     -
07691     SeeAlso:    DialogManager::CreateTabbedDialog
07692 
07693 ********************************************************************************************/
07694 
07695 void DialogManager::RelayoutDialog( DialogTabOp* pDlgOp )
07696 {
07697     if (pDlgOp->WindowID->IsKindOf(CLASSINFO(wxPropertySheetDialog)))
07698     {
07699         ((wxPropertySheetDialog*)(pDlgOp->WindowID))->LayoutDialog();
07700     }
07701     else
07702         Layout(pDlgOp->WindowID);
07703 }
07704 
07705 
07706 /********************************************************************************************
07707 
07708 >   static BOOL DialogManager::CreateTabbedDialog(DialogTabOp* pTabDlgOp, CDlgMode Mode, INT32 OpeningPage)
07709 
07710     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07711     Created:    5/12/94
07712     Inputs:     DlgOp:          The DialogTabOp to create
07713                 CDlgMode:       MODAL/MODELESS
07714                 OpeningPage:    Override the page which is active (defaults to -1)
07715     Outputs:    -
07716     Returns:    -
07717     Purpose:    Handles the creation of a tabbed dialog
07718                 Opening page allows a page to be specified that is not the initial page, which
07719                 will be the default if this is the first time the dialog has been opened or if
07720                 it has been opened before then the initial page will be the last one opened.
07721     Scope:      private
07722     Errors:     -
07723     SeeAlso:    DialogManager::Create
07724 
07725 ********************************************************************************************/
07726 
07727 BOOL DialogManager::CreateTabbedDialog(DialogTabOp* pTabDlgOp, CDlgMode Mode, INT32 OpeningPage,
07728     CDlgResID mainDlgID )
07729 {
07730     wxBookCtrlBase * pBook = GetBookControl(pTabDlgOp->WindowID);
07731     if (!pBook)
07732         return TRUE; // nothing to do
07733 
07734     // Before we can create the property sheet we must add pages to it.
07735     // Let's ask the op do do this for us
07736     if (!(pTabDlgOp->RegisterYourPagesInOrderPlease()))
07737     {
07738         // We failed to add pages to the dialog so we must tidy-up and fail
07739         return FALSE;
07740     }
07741 #if 0
07742     // Something very odd happens with the image list so we copy and reset it
07743     if (pBook->GetImageList())
07744     {
07745         wxImageList temp=*pBook->GetImageList();
07746         pBook->SetImageList(&temp);
07747     }
07748 #endif
07749 
07750     // Get the dialog sized to fit
07751     RelayoutDialog(pTabDlgOp);
07752 
07753     // Scroll to start and end after yeild
07754     ::wxYield();
07755     pBook->SetSelection(pBook->GetPageCount()-1);
07756     pBook->SetSelection(0);
07757 
07758     // First check if the OpeningPage parameter is not equal to -1, in which case this
07759     // specifies the active page to be opened.
07760     // Has to be an index as otherwise we have not specified the pages yet and so cannot
07761     // convert the PageID into an index which is what the PropertySheets require.
07762     UINT32 ActivePageIndex = 0;
07763     if (OpeningPage != -1)
07764     {
07765         // Set the index of the page that is to be the active one to the one that has
07766         // been specified.
07767         ActivePageIndex = OpeningPage;
07768     }
07769     else
07770     {
07771         // Determine if this dialog has been created before
07772         DialogPosition* pPosDetails = FindDialogPositionRecord( mainDlgID );
07773         if (pPosDetails != NULL)
07774         {
07775             // The dialog has been created before so find out the index of the active page
07776             ActivePageIndex = pPosDetails->ActivePageIndex;
07777         }
07778     }
07779 
07780     // Now that the pages have been registered, check if the dialog has been opened
07781     // before. If so force the new ActivePage to be specified rather than the old.
07782     if (OpeningPage != -1)
07783     {
07784         // Determine if this dialog has been created before
07785         DialogPosition* pPosDetails = FindDialogPositionRecord( mainDlgID );
07786         if (pPosDetails != NULL)
07787         {
07788             // The dialog has been created before so check if the specified page was the
07789             // last active one. If it was then everything should be ok.
07790 //          if (OpeningPage != pPosDetails->ActivePageIndex)
07791 //          {
07792                 ERROR3IF(pBook == NULL, "There is no current PropertySheet");
07793                 wxNotebookPage* pPage = (wxNotebookPage*)(pBook->GetPage(OpeningPage));
07794                 ERROR3IF(pPage == NULL, "There is no active page");
07795                 pPosDetails->ActivePage = pPage->GetId();
07796 TRACEUSER( "MarkH", _T("CreateTabbedDialog ActivePage = %d\n"),pPosDetails->ActivePage);
07797 //              pPosDetails->ActivePage = 27666;
07798                 pPosDetails->ActivePageIndex = OpeningPage;
07799 //          }
07800         }
07801     }
07802 
07803     return TRUE;
07804 }
07805 
07806 
07807 
07808 /********************************************************************************************
07809 
07810 >   static BOOL DialogManager::GetStatusLineText(String_256* ptext, CWindowID window)
07811 
07812     Author:     Alex Bligh <alex@alex.org.uk>
07813     Created:    15/05/2006
07814     Inputs:     window - the window ID, or NULL for the current mouse position
07815     Outputs:    pText - pointer to the text to fill in
07816     Returns:    TRUE on success else FALSE
07817     Purpose:    Fills in the status line text from the help text if over a control
07818     Scope:      Public
07819     Errors:     -
07820     SeeAlso:    -
07821 
07822 ********************************************************************************************/
07823 
07824 BOOL DialogManager::GetStatusLineText(String_256* ptext, CWindowID window)
07825 {
07826     if (!ptext)
07827         return FALSE;
07828     if (!window)
07829         window=::wxChildWindowFromPoint(wxGetMousePosition(), FALSE, -1);
07830     if (!window)
07831         return FALSE;
07832 
07833     wxHelpProvider * hp = wxHelpProvider::Get();
07834 
07835     // Now some controls contain other controls, so we look down the heirarch if we can't find one
07836     // immediately
07837     wxString help;
07838     do
07839     {
07840         if (!window->IsKindOf(CLASSINFO(wxControl)))
07841             return FALSE;
07842 
07843         if (hp)
07844             help = hp->GetHelp(window);
07845         else
07846             help = ((wxControl *)window)->GetHelpText();
07847 
07848         if (help.IsEmpty())
07849         {
07850             wxToolTip* pTip = window->GetToolTip();
07851             if (pTip) help=pTip->GetTip();
07852         }
07853 
07854         window=window->GetParent();
07855     } while (window && help.IsEmpty());
07856 
07857     if (help.IsEmpty())
07858         return FALSE;
07859 
07860     *ptext = help;
07861     return TRUE;
07862 }
07863 
07864 /********************************************************************************************
07865 
07866 >   static CWindowID DialogManager::GetWindowUnderPointer(WinCoord * wc=NULL)
07867 
07868     Author:     Alex Bligh <alex@alex.org.uk>
07869     Created:    15/05/2006
07870     Inputs:     -
07871     Outputs:    wc - if non-NULL, filled in with the pointer coords
07872     Returns:    the window ID under the pointer or NULL for none
07873     Purpose:    Fills in the status line text from the help text if over a control
07874     Scope:      Public
07875     Errors:     -
07876     SeeAlso:    -
07877 
07878 ********************************************************************************************/
07879 
07880 CWindowID DialogManager::GetWindowUnderPointer(WinCoord * wc /*=NULL*/)
07881 {
07882     wxPoint pt=wxGetMousePosition();
07883     wxWindow * w=::wxChildWindowFromPoint(pt, FALSE, -1);
07884     if (wc && w)
07885     {
07886         pt = w->ScreenToClient(pt);
07887         wc->x=pt.x;
07888         wc->y=pt.y;
07889     }
07890     return w;
07891 }
07892 
07893 // Old windows routine follows
07894 #if 0
07895 /********************************************************************************************
07896 
07897 >   static BOOL CALLBACK EXPORT SendDialogMessage(HWND hDlg,
07898                                                 UINT32 Message,
07899                                                 UINT32 wParam,
07900                                                 INT32 lParam);
07901 
07902     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
07903     Created:    17/8/93
07904 
07905     Inputs:     hDlg:           Dialog window
07906                 UINT32 Message:   Windows message
07907                 UINT32 wParam:    wParam
07908                 INT32 lParam:    lParam
07909     Outputs:    -
07910     Returns:    -
07911     Purpose:    All messages generated by all dialogs in the Windows dialog system will be
07912                 sent to this callback
07913 
07914                 The types of this methods variables will change depending on the platform. It
07915                 receives a platform dependant message, translates it into a DIM and then calls
07916                 the DialogOp's RouteMessage function.
07917     Errors:     -
07918     SeeAlso:    -
07919 
07920 ********************************************************************************************/
07921 
07922 BOOL CALLBACK EXPORT DialogManager::SendDialogMessage( wxWindow *pDlg,
07923                                                 UINT32 Message,
07924                                                 UINT32 wParam,
07925                                                 INT32 lParam )
07926 {
07927     PORTNOTETRACE("dialog","DialogManager::SendDialogMessage - do nothing");
07928 #ifndef EXCLUDE_FROM_XARALX
07929     HandleMessage = FALSE;  // Flag indicating if the message received is handled
07930 
07931     INT32 DlgMsgParam = 0;  // Arbitrary INT32 which has meaning with some messages
07932                             // This gets set by the case statements below and then passed
07933                             // on to Operations by the BROADCAST_TO_CLASS macro at the bottom.
07934     Gadget = 0xFFFFFFF0;
07935 
07936     // ----------------------------------------------------------------------------------
07937     // Determine if the message was broadcast from a page within a Property sheet, if it
07938     // was then set the hDlg to that of the property sheet, and find the PageID
07939     PageID = 0;
07940     HWND BroadcastWindow = hDlg; // The window we should broadcast to.
07941 
07942     wxWindow* pCWnd = CWnd::FromHandlePermanent(hDlg);
07943 
07944     if (pCWnd != NULL)
07945     {
07946         if (pCWnd->IsKindOf(RUNTIME_CLASS(wxNotebookPage)))
07947         {
07948             wxWindow* pPropertySheet = pCWnd->GetParent();
07949             if (pPropertySheet)
07950             {
07951                 ERROR2IF(!(pPropertySheet->IsKindOf(RUNTIME_CLASS(wxPropertySheetDialog))), FALSE,"Property page parent not a property sheet");
07952                 BroadcastWindow = pPropertySheet->GetSafeHwnd(); // The destination of the message
07953                 ERROR2IF(BroadcastWindow == NULL, FALSE, "Property sheet window handle is NULL");
07954                 // We need to find the resource ID of the property sheet page
07955                 PageID = ((wxNotebookPage*)pCWnd)->GetPageID();
07956             }
07957             else
07958             {
07959                 // I'm not sure what this message is,  but we can't do much with it !
07960                 return FALSE;
07961             }
07962         }
07963     }
07964     // ----------------------------------------------------------------------------------
07965 
07966     BOOL RemoveFocus = FALSE;
07967 
07968 //  Removed by Phil on request from Simon, 11/05/94
07969 //  Gadget = 0; // Set to 0 to ensure Info Bar messages are routed ok.
07970 
07971 #if WIN16
07972     WORD Ctl = HIWORD(lParam);
07973 
07974     if (Message == WM_CTLCOLOUR && Ctl == CTLCOLOR_EDIT)
07975         Message = WM_CTLCOLOREDIT;
07976 #endif
07977 
07978     // Set Current properly by setting it to be the same as Selected. Dialogs should only apply
07979     // to the Selected Document/View...
07980     Document::GetSelected()->SetCurrent();
07981     DocView::GetSelected()->SetCurrent();
07982 
07983     switch (Message)
07984     {
07985         case WM_MOVE:
07986         {
07987             //DY 4/5/2000 we need to know about this now to update the screen when drawing brushes
07988             HandleMessage = TRUE;
07989             DIM = DIM_DLG_MOVED;
07990         }
07991         break;
07992 
07993         // This responds to the custom "telephone keypad" message.
07994         case WM_GRIDBN_PRESSED:
07995             DIM = DIM_GRID_BUTTON_DOWN;
07996             HandleMessage = TRUE;
07997             Gadget = LOWORD(lParam);
07998             DlgMsgParam = (INT32) HIWORD(lParam);
07999             break;
08000 
08001         case WM_ACTIVATE:
08002             // The following bit of code is required so that we only need one IsDialogMessage
08003             // for many Modeless dialogs
08004             if (wParam == 0)
08005             {
08006                 // The dialog is becoming inactive
08007                 hDlgCurrent = NULL;
08008             }
08009             else
08010             {
08011                 hDlgCurrent = hDlg;
08012             }
08013             return TRUE;
08014 
08015         case WM_QUERYNEWPALETTE:
08016             // A Window has become the focus and may select a palette if it likes
08017             // We always call the palette manager, which makes sure that Gavin's palette
08018             // is used and GDraw is using the right colours.
08019             PaletteManager::EnsurePalette(BroadcastWindow, FALSE);
08020             return(TRUE);
08021 
08022         case WM_PALETTECHANGED:
08023             // The palette has changed, so ensure we realise our palette in the background
08024             // but only if it wasn't us who caused this to happen!
08025             if (hDlg != (HWND)wParam)
08026                 PaletteManager::EnsurePalette(BroadcastWindow, TRUE);
08027             break;
08028 
08029 
08030         case WM_COMMAND:
08031             Gadget = GET_WM_COMMAND_ID(wParam, lParam);
08032 
08033             // The command ID is only allowed to be a short
08034             // however the _R(ID_APPLY_NOW) control within a property sheet has a value 59910 so
08035             // it gets corrupted. So we need to convert it to are own ID value which can fit
08036             // into a short.
08037             if (Gadget == _R(ID_APPLY_NOW))
08038             {
08039                 Gadget = _R(ID_CC_APPLY_NOW);
08040             }
08041 
08042             // the short casts are here so the sign gets propogated correctly under win32
08043             if (!CustomControlMsg(hDlg, wParam, lParam))
08044             {
08045                 DialogManager::Dlg_OnCommand( hDlg,
08046                                                 (short)Gadget,
08047                                                 GET_WM_COMMAND_HWND(wParam, lParam),
08048                                                 (short)GET_WM_COMMAND_CMD(wParam, lParam)
08049                                             );
08050 
08051                 if (HandleMessage && DIM == DIM_SELECTION_CHANGED)
08052                     RemoveFocus = TRUE;
08053             }
08054             break;
08055 
08056         case CBN_CAM_SELCHANGE:
08057             // Handle a previously sent CBN_SELCHANGE/CBN_DBLCLK on a combo.
08058             DIM = (CDlgMessage) wParam;
08059             Gadget = (CGadgetID) lParam;
08060             HandleMessage = TRUE;
08061             break;
08062 
08063         case WM_CTL_COMMIT:
08064             // Handle subclassed bar Edit and Combo controls, send a selection changed message
08065             Gadget = wParam;
08066             DIM = DIM_SELECTION_CHANGED;
08067 
08068             // The LPARAM component of the message contains the virtual key code that caused the
08069             // commit.
08070             if (lParam == CAMKEY(RETURN)) DlgMsgParam = ENTER_COMMIT;
08071             else if (lParam == CAMKEY(TAB)) DlgMsgParam = TAB_COMMIT;
08072             else DlgMsgParam = NO_COMMIT;
08073 
08074             HandleMessage = TRUE;
08075             RemoveFocus = TRUE;
08076             break;
08077 
08078         case WM_SIZEPARENT:
08079             // This should only be received for the InfoBar, so send it on.
08080             CMainFrame::pInfoBar->OnSizeParent(wParam, lParam);
08081             break;
08082 
08083         case WM_INITDIALOG:
08084             if (!lParam)        // Dialog is modal, we need to call PostCreate
08085             {
08086                 if (!PostCreate(hDlg))
08087                 {
08088                     // We failed to create a modal dialog
08089                     EndDialog(hDlg,FALSE);  // It is ok to call this in WM_INITDIALOG
08090                 }
08091             }
08092             return !FocusSetDuringInit;
08093 
08094         // Win32 and Win16 handle colour messages a bit differently - Win32 has separated them
08095         // out into different messages.
08096         // This code causes our dialogs and static controls to have a grey background.
08097 
08098         // A scrollbar message ?
08099         case WM_VSCROLL:
08100         case WM_HSCROLL:
08101             Gadget = GetDlgCtrlID( GET_WM_HSCROLL_HWND(wParam,lParam) );
08102             HANDLE_WM_VSCROLL(hDlg, wParam, lParam, DialogManager::Dlg_OnScroll);
08103             break;
08104 
08105         // Handle mouse button up/down events
08106         // Gadget IDs will be correct for custom controls but not for normal controls
08107         // So in the left button cases find the control ID from the supplied position
08108         case WM_LBUTTONDOWN:
08109         {
08110             INT32 xPos = LOWORD(lParam);  // horizontal position of cursor
08111             INT32 yPos = HIWORD(lParam);  // vertical position of cursor
08112             POINT point = { xPos, yPos };
08113             HWND HitWnd = ChildWindowFromPoint(hDlg, point);
08114             if (HitWnd != NULL)
08115                 Gadget = GetDlgCtrlID(HitWnd); // handle of control
08116             HandleMessage = TRUE;
08117             DIM = DIM_LFT_BN_DOWN;
08118             break;
08119         }
08120         case WM_LBUTTONUP:
08121         {
08122             INT32 xPos = LOWORD(lParam);  // horizontal position of cursor
08123             INT32 yPos = HIWORD(lParam);  // vertical position of cursor
08124             POINT point = { xPos, yPos };
08125             HWND HitWnd = ChildWindowFromPoint(hDlg, point);
08126             if (HitWnd != NULL)
08127                 Gadget = GetDlgCtrlID(HitWnd); // handle of control
08128             HandleMessage = TRUE;
08129             DIM = DIM_LFT_BN_UP;
08130             //Gadget = GetDlgCtrlID(hDlg); // handle of control
08131             break;
08132         }
08133 
08134         // Gadget IDs will be correct for custom controls but not for normal controls
08135         case WM_RBUTTONDOWN:
08136             HandleMessage = TRUE;
08137             DIM = DIM_RGT_BN_DOWN;
08138             //Gadget = GetDlgCtrlID(hDlg); // handle of control, returns 0
08139             break;
08140         case WM_RBUTTONUP:
08141             HandleMessage = TRUE;
08142             DIM = DIM_RGT_BN_UP;
08143             //Gadget = GetDlgCtrlID(hDlg); // handle of control, returns 0
08144             break;
08145 
08146         case WM_MOUSEWHEEL:
08147         {
08148             INT32 xPos = LOWORD(lParam);  // horizontal position of cursor
08149             INT32 yPos = HIWORD(lParam);  // vertical position of cursor
08150             POINT point = { xPos, yPos };
08151             HWND HitWnd = ChildWindowFromPoint(hDlg, point);
08152             if (HitWnd != NULL)
08153                 Gadget = GetDlgCtrlID(HitWnd); // handle of control
08154             HandleMessage = TRUE;
08155             if ((short)HIWORD(wParam) > 0)
08156             {
08157                 DIM = DIM_MOUSEWHEEL_UP;
08158             }
08159             else
08160             {
08161                 DIM = DIM_MOUSEWHEEL_DOWN;
08162             }
08163             break;
08164         }
08165 
08166 
08167         // Handle Rik's slider notification messages...
08168 
08169         case WMN_POSITION_CHANGING:
08170             Gadget = GetWindowID((HWND)wParam);
08171             HandleMessage = TRUE;
08172             DIM = DIM_SLIDER_POS_CHANGING;
08173             DlgMsgParam = lParam;           // Pass slider pos on to Ops
08174             break;
08175         case WMN_POSITION_IDLE:
08176             Gadget = GetWindowID((HWND)wParam);
08177             HandleMessage = TRUE;
08178             DIM = DIM_SLIDER_POS_IDLE;
08179             DlgMsgParam = lParam;           // Pass slider pos on to Ops
08180             break;
08181         case WMN_POSITION_SET:
08182             Gadget = GetWindowID((HWND)wParam);
08183             HandleMessage = TRUE;
08184             DIM = DIM_SLIDER_POS_SET;
08185             DlgMsgParam = lParam;           // Pass slider pos on to Ops
08186             break;
08187 
08188 
08189         // A Windows font table change has occured.
08190         // Something or somebody has added or removed a font from the windows
08191         // font table.
08192 
08193         case WM_FONTCHANGE:
08194             HandleMessage = TRUE;
08195             DIM = DIM_FONTCHANGE;
08196             break;
08197 
08198         // Somebody has asked for a timer event and here we have recieved one.
08199         case WM_TIMER:
08200             // Parameters are:-
08201             // wTimerID = wParam;            // timer identifier
08202             // tmprc = (TIMERPROC *) lParam; // address of timer callback
08203             DlgMsgParam = wParam;   // pass on the timer id just in case dialog wants it
08204             HandleMessage = TRUE;
08205             DIM = DIM_TIMER;
08206             break;
08207 
08208 //      // Somebody has changed something in the International Section
08209 //      // of the Windows Control Panel. So note the change and force things
08210 //      // to update the current display
08211 //
08212 //      case WM_WININICHANGE:
08213 //      {
08214 //          // Cause the conversion system to reload the values from the system
08215 //          InitConvert();
08216 //          // Now tell people to update themselves
08217 //          Document * pDocument = Document::GetSelected();
08218 //          BROADCAST_TO_ALL(OptionsChangingMsg(pDocument, OptionsChangingMsg::OptionsState::NEWUNITS));
08219 //          break;
08220 //      }
08221 
08222 
08223         // Handle mouse moves/drags
08224 
08225         // These were removed by Simon 25/11 cos they are unlikely to be needed any longer and
08226         // make debugging a pain.
08227 
08228         // MOUSEMOVE was restored, because its needed in the bitmap export options dialog
08229         case WM_MOUSEMOVE:
08230         {
08231             if (!(wParam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)))
08232             {
08233                 HandleMessage = TRUE;
08234                 DIM = DIM_MOUSE_MOVE;
08235             }
08236             break;
08237         }
08238 
08239         case WM_NOTIFY:
08240         {
08241             HWND hChild = GetDlgItem(hDlg, INT32(wParam));
08242             TCHAR buffer[32];
08243             GetClassName(hChild, buffer, sizeof(buffer));
08244             if (String_32(buffer) == String_32(TEXT("SysTreeView32"))) // so the notification comes from a treeview
08245             {
08246                 LPNMHDR pNMHDR = (LPNMHDR) lParam;
08247                 switch (pNMHDR->code)
08248                 {
08249                     // We could handle much more here, but this is rather useful...
08250                     case TVN_SELCHANGED:
08251                     {
08252                         HandleMessage = TRUE;
08253                         Gadget = wParam;
08254                         DIM = DIM_SELECTION_CHANGED;
08255                         DlgMsgParam = lParam;
08256                     }
08257                 }
08258             }
08259 
08260             if (String_32(buffer) == (LPCTSTR)CCustomList::WNDCLASSNAME) // so the notification comes from our customlist
08261             {
08262                 LPNMHDR pNMHDR = (LPNMHDR) lParam;
08263                 CCustomList* pListGadget = CCustomList::GetGadget((CWindowID) hDlg, (CGadgetID) pNMHDR->idFrom);
08264                 BOOL DoubleClick = FALSE;   // Flag to allow sharing of click/double-click code
08265 
08266                 if (pListGadget)
08267                 {
08268                     // the gadget is notifying us that something happened
08269                     HandleMessage = TRUE;
08270                     Gadget = wParam;
08271                     if(pNMHDR->code == NM_DBLCLK)
08272                     {
08273                         DIM = DIM_SELECTION_CHANGED_COMMIT;
08274 
08275                     }
08276                     else
08277                     {
08278                         DIM = DIM_SELECTION_CHANGED;
08279                     }
08280                 }
08281                 else
08282                 {
08283                     ERROR3("Failed to find list gadget");
08284                 }
08285             }
08286 
08287             if (String_32(buffer) == String_32(TEXT("msctls_updown32"))) // so the notification comes from an updown control
08288             {
08289                 NM_UPDOWN* pnmud = (NM_UPDOWN FAR *) lParam;
08290 
08291                 if (pnmud->iDelta > 0)
08292                 {
08293                     SpinControlMessageUp = TRUE;
08294                     HandleMessage = FALSE;
08295                 }
08296                 else if (pnmud->iDelta < 0)
08297                 {
08298                     SpinControlMessageDown = TRUE;
08299                     HandleMessage = FALSE;
08300                 }
08301                 else
08302                 {
08303                     ERROR3 ("A Fatal error has occured within the OS!");
08304                 }
08305             }
08306         }
08307         break;
08308 
08309 
08310 
08311 
08312 //      case WM_DESTROY:
08313 //          // Call CCListGadget::OnDialogClose() so that it destroys any list controls there may be on the form
08314 //          CCustomList::OnDialogClose((CWindowID) hDlg);
08315 //          break;
08316 
08317 
08318         // sent when a change is made to a system color setting - forward message to controls
08319         case WM_SYSCOLORCHANGE:
08320         {
08321             HWND hChild = GetDlgItem(hDlg, INT32(wParam));
08322             if(hChild)
08323             {
08324                 ::SendMessage(hChild, WM_SYSCOLORCHANGE, 0, 0);
08325             }
08326             return TRUE;
08327             break;
08328         }
08329 
08330         case WM_DLGDRAWEVENT:   // (Mouse) event from a cc_DialogDraw custom control [Jason: 2/12/94]
08331         {
08332             DlgDrawEventInfo *Info = (DlgDrawEventInfo *) lParam;
08333             ERROR3IF(Info == NULL, "NULL DilaogDraw EventInfo passed to DialogMgr?!");
08334 
08335             switch(Info->msg)
08336             {
08337                 case WM_LBUTTONDOWN:
08338                     DIM = DIM_LFT_BN_DOWN;
08339                     break;
08340 
08341                 case WM_LBUTTONUP:
08342                     DIM = DIM_LFT_BN_UP;
08343                     break;
08344 
08345                 case WM_RBUTTONDOWN:
08346                     DIM = DIM_RGT_BN_DOWN;
08347                     break;
08348 
08349                 case WM_RBUTTONUP:
08350                     DIM = DIM_RGT_BN_UP;
08351                     break;
08352 
08353                 case WM_MOUSEMOVE:
08354                     if (Info->wParam & MK_LBUTTON)
08355                         DIM = DIM_MOUSE_DRAG;
08356                     else
08357                         DIM = DIM_MOUSE_MOVE;
08358                     break;
08359 
08360                 case WM_MOUSEWHEEL:
08361                     if ((short) HIWORD(Info->wParam) > 0)
08362                     {
08363                         //MouseWheel scrolled upwards
08364                         DIM = DIM_MOUSEWHEEL_UP;
08365                     }
08366                     else
08367                     {
08368                         //MouseWheel scrolled downwards...
08369                         DIM = DIM_MOUSEWHEEL_DOWN;
08370                     }
08371                     break;
08372 
08373                 default:
08374                     ERROR3("Unknown Event type passed in WM_DLGDRAWEVENT message");
08375                     break;
08376             }
08377 
08378             // Set up a MousePosInfoType containing the click position info, and information
08379             // that will come in handy (size of the gadget, and screen DPI)
08380             ReDrawInfoType ExtraInfo;
08381 
08382             ExtraInfo.pDC = NULL;       // No redraw info for mouse events
08383             ExtraInfo.pClipRect = NULL;
08384 
08385             // Get the screen DPI
08386             HDC ScreenDC = CreateCompatibleDC(NULL);
08387             if (ScreenDC == NULL)
08388             {
08389                 ERROR2RAW("DialogManager::SendDialogMessage: Unable to create screen DC");
08390                 break;
08391             }
08392             ExtraInfo.Dpi = GetDeviceCaps(ScreenDC, LOGPIXELSY);
08393             DeleteDC(ScreenDC);
08394 
08395             // Calculate how big the window is, in MILLIPOINTS
08396             RECT WindowSize;
08397             if (!GetClientRect(Info->hwnd, &WindowSize))
08398             {
08399                 ERROR2RAW("GetClientRect failed in DialogManager::SendDialogMessage");
08400                 break;
08401             }
08402 
08403             ExtraInfo.dx = (((INT32)WindowSize.right)*72000) / ExtraInfo.Dpi;
08404             ExtraInfo.dy = (((INT32)WindowSize.bottom)*72000) / ExtraInfo.Dpi;
08405 
08406             // Work out the MILLIPOINT coordinates of the mouse position
08407             // Note that the Y value is flipped, as the kernel-origin is at the bottom left
08408             INT32 XPos = (INT32) MAKEPOINTS(Info->lParam).x;
08409             INT32 YPos = (INT32) MAKEPOINTS(Info->lParam).y;
08410 
08411             DocCoord MousePos;
08412             MousePos.x = (XPos * 72000) / ExtraInfo.Dpi;
08413             MousePos.y = ExtraInfo.dy - ((YPos * 72000) / ExtraInfo.Dpi);
08414             ExtraInfo.pMousePos = &MousePos;
08415 
08416             // Now, send the message to the DialogOp to be handled.
08417             // Note that we leave HandleMessage == FALSE so the caller doesn't send the
08418             // message a second time!
08419 
08420             BROADCAST_TO_CLASS(DialogMsg(BroadcastWindow, DIM, Info->ControlID, (INT32)&ExtraInfo, PageID), DialogOp);
08421             break;
08422         }
08423 
08424 
08425         case WM_REDRAW :
08426         {
08427             if (CCamApp::IsDisabled())
08428             {
08429                 TRACE( _T("kernel-rendered gadget repaint has been aborted: the system is disabled (due to an error/ensure?)\n"));
08430                 HandleMessage = FALSE;
08431                 break;
08432             }
08433 
08434             // Find out about the paint message and fill in the details in the kernel message
08435             RedrawInfo* pInfo = (RedrawInfo*) lParam;
08436 
08437             HDC hDC = pInfo->PaintInfo.hdc;
08438             HPALETTE OldPalette = PaletteManager::StartPaintPalette(hDC);
08439 
08440             ReDrawInfoType ExtraInfo;
08441 
08442             ExtraInfo.pMousePos = NULL;     // No mouse position info for redraw events
08443 
08444             // Build a CC dc out of it for rendering to the screen
08445             // Get a MFC CDC to put the DC in
08446             CCDC MyDc(RENDERTYPE_SCREEN);
08447             MyDc.Attach(pInfo->PaintInfo.hdc);
08448             ExtraInfo.pDC = &MyDc;
08449 
08450             // The devices DPI
08451             ExtraInfo.Dpi = MyDc.GetDeviceCaps(LOGPIXELSY);
08452 
08453             // How big the window is
08454             RECT WindowSize;
08455             if (GetClientRect((HWND)wParam, &WindowSize))
08456             {
08457                 ExtraInfo.dx = (((INT32)WindowSize.right)*72000) / ExtraInfo.Dpi;
08458                 ExtraInfo.dy = (((INT32)WindowSize.bottom)*72000) / ExtraInfo.Dpi;
08459             }
08460 
08461             // Work out the size of the invalidated region
08462             RECT* ClipRect = &pInfo->PaintInfo.rcPaint;
08463             DocRect DocClipRect;
08464 
08465             // Convert to millipoints, Also need to flip the y coords to get a
08466             // rectangle in with the origin in the bottom left.
08467             DocClipRect.lo.x = (ClipRect->left * 72000) / ExtraInfo.Dpi;
08468             DocClipRect.lo.y = ExtraInfo.dy - ((ClipRect->bottom * 72000) / ExtraInfo.Dpi);
08469 
08470             DocClipRect.hi.x = (ClipRect->right * 72000) / ExtraInfo.Dpi;
08471             DocClipRect.hi.y = ExtraInfo.dy - ((ClipRect->top * 72000) / ExtraInfo.Dpi);
08472 
08473             // Set the pointer in the extra info structure
08474             ExtraInfo.pClipRect = &DocClipRect;
08475 
08476             // Build the message and send it to the dialog op
08477             // It is up to the dialog op to build a render region etc and attach the CCDC to it
08478             // and to tidy the region up after it has finished drawing in it CDlgMessage
08479             BROADCAST_TO_CLASS(DialogMsg(BroadcastWindow, DIM_REDRAW, pInfo->ControlID, (INT32) &ExtraInfo, PageID), DialogOp);
08480 
08481             // Give back the dc
08482             MyDc.Detach();
08483 
08484             if (OldPalette)
08485                 PaletteManager::StopPaintPalette(hDC, OldPalette);
08486             break;
08487         }
08488 
08489         case WM_DRAWITEM:
08490             {
08491                 // First, check if this is for a (Colour/Font) DropDown combobox, and return TRUE if it handles it
08492                 if (DropDown::HandleDrawItem(hDlg, wParam, lParam))
08493                     return(TRUE);
08494                 // Nope - it must be a custom control, so pass the message on to it
08495                 LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lParam;
08496 
08497                 // If the custom control redraws this, we return TRUE so that the OS/MFC
08498                 // does not go rampantly drawing selection rects around the item or anything
08499                 if (SendMessage( lpdis->hwndItem,
08500                                 DialogManager::MsgSlaveDrawItem, wParam, lParam ))
08501                     return(TRUE);
08502             }
08503             break;
08504 
08505         case WM_MEASUREITEM:
08506             {
08507                 // Get the colour drop-down list to handle this. Note that it currently always handles
08508                 // this case - if you need to pass it to another control, check first and drop through
08509                 // to this code if you don't handle it.
08510 
08511                 if (DropDown::HandleMeasureItem(hDlg, wParam, lParam))
08512                     return(TRUE);
08513             }
08514             break;
08515 
08516         //case WM_WINDOWPOSCHANGING:
08517         //  static Bodge=0;
08518         //  if (Bodge >= 1)
08519         //  {
08520         //      // If the dialog is modal then do not let the windows Z order change
08521         //          WINDOWPOS FAR* pwp = (WINDOWPOS FAR*) lParam;  // address of WINDOWPOS structure
08522         //      pwp->flags = SWP_NOOWNERZORDER;
08523         //  }
08524         //  Bodge++;
08525         //  break;
08526 
08527 
08528         // --- Bodge handlers for input focus handling in the colour editor
08529         // Thanks to the sheer marvellousness of Windows disloague handling, we can't stop the focus
08530         // going into our dialogue on MouseActivate (normally, we'd just return MA_NOACTIVATE and be
08531         // happy without the focus). The 17th and final solution (the only one that works) is that
08532         // when a click occurs on the window titlebar, or when the window has been moved, we warn the
08533         // dialogue about it, and the colour dialogue schedules an idle-event processor, which pushes
08534         // the focus back to the document. This has to be done on idles so that the focus is pushed
08535         // back immediately after the move occurs (if we change the focus immediately, it goes away
08536         // until the mouse button is released, at which point Windows kindly gives us the focus again!)
08537 
08538         // Actually (25/2/2000) there is a much more suitable (and easier) way of getting our
08539         // colour editor dialog to do this - we simply process the WM_EXITSIZEMOVE mesage!
08540         // The message is common to Windows 96/98 and NT (CGS) ....  I discovered this when I
08541         // made the profile dialog behave in a similiar fashion.
08542 
08543         case WM_MOUSEACTIVATE:      // Look out for clicks on the title bar
08544             if (((INT32) LOWORD(lParam)) != HTCAPTION)
08545                 return(FALSE);
08546             else
08547                 return (MA_NOACTIVATE);     // return this - even if windows don't want to listen
08548                                             // to us; cause afterall, its what we want ....
08549 
08550         case WM_EXITSIZEMOVE:
08551             DIM = DIM_TITLEFOCUSWARN;       // throw that focus baby!
08552             BROADCAST_TO_CLASS( DialogMsg(BroadcastWindow, DIM, Gadget, DlgMsgParam, PageID), DialogOp );
08553             // yo buddy, I've handled the message !
08554             return (TRUE);
08555 
08556 
08557 
08558         break;
08559         // added by Karim 30/9/99 to catch text typed into the font combo-box and change the
08560         // selection within the combo-box to match whatever the user typed as closely as possible.
08561         case WM_KEYDOWN:
08562             {
08563                 // check whether we want this message - ie is the font
08564                 // combo-box a child of the message'd window.
08565                 if (::GetDlgItem(hDlg, _R(IDC_FONT_COMBO)) != NULL &&
08566                                             (TCHAR)wParam >= 'A' &&
08567                                             (TCHAR)wParam <= 'Z')
08568                 {
08569                     // if the character just typed was entered within a specified
08570                     // timeframe, 'cat it to the end of a comparison string.
08571                     static DWORD dwTime = 0;
08572                     static String_256 strCharsTyped = "";
08573 
08574                     DWORD dwNow = ::GetTickCount();
08575                     if ((dwNow - dwTime)  > 1000 || strCharsTyped.Length() > 255)
08576                         strCharsTyped.Empty();
08577 
08578                     strCharsTyped += (TCHAR)wParam;
08579 
08580                     // look for the first font whose description starts with
08581                     // the comparison string.
08582                     BOOL bMatch = FALSE;
08583                     FontDropItem* fontItem = NULL;
08584                     HWND hwndCombo = ::GetDlgItem(hDlg, _R(IDC_FONT_COMBO));
08585                     INT32 numItems = ComboBox_GetCount(hwndCombo);
08586                     for (INT32 i = 0; !bMatch && i < numItems; i ++)
08587                     {
08588                         fontItem = (FontDropItem*)ComboBox_GetItemData(hwndCombo, i);
08589                         if (fontItem != NULL)
08590                         {
08591                             bMatch = (camStrnicmp(fontItem->GetFontName(),
08592                                 strCharsTyped,
08593                                 camStrlen(strCharsTyped)) == 0);
08594                         }
08595                     }
08596 
08597                     // if we found the font, lets go to it
08598                     if (bMatch)
08599                         ::SendMessage(hwndCombo, CB_SETCURSEL, i - 1, 0);
08600                     else
08601                         strCharsTyped.Empty();
08602 
08603                     // set our timer to the current time.
08604                     dwTime = ::GetTickCount();
08605 
08606                     return TRUE;    // this message has been processed.
08607                 }
08608             }
08609         break;
08610     }
08611 
08612     // Handle messages from draggable list boxes...
08613     static LPDRAGLISTINFO lpdli;
08614     static UINT32 iItemToMove, iItem;
08615 
08616     if (Message == DialogManager::MsgDragList)
08617     {
08618     #if USE_COMMON_CONTROLS
08619         lpdli = (LPDRAGLISTINFO)lParam;
08620         switch (lpdli->uNotification)
08621         {
08622             case DL_BEGINDRAG:
08623                 iItemToMove = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
08624                 return DL_MOVECURSOR;
08625             case DL_DRAGGING:
08626                 iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
08627                 DrawInsert(hDlg, lpdli->hWnd, iItem);
08628                 if (iItem!=-1)
08629                     return DL_MOVECURSOR;
08630                 return DL_STOPCURSOR;
08631             case DL_DROPPED:
08632                 iItem = LBItemFromPt(lpdli->hWnd, lpdli->ptCursor, TRUE);
08633                 //if (iItem!=-1)
08634                 //{
08635                     //SetStringGadgetValue(
08636                     //ListBox_InsertString(hGadget, iItem, (INT32)(TCHAR*)(*StrVal))
08637                     //Use list box messages to insert item at new location
08638                 //}
08639                 DrawInsert(hDlg, lpdli->hWnd, -1);
08640                 return DL_CURSORSET;
08641             default:
08642                 if (IsUserName("Simon"))
08643                     TRACE( _T("Unknown draglist message 0x%x\n"), lpdli->uNotification);
08644 
08645         }
08646     #endif
08647     }
08648 
08649     // If the message should be handled then Route it to the appropriate DialogOp
08650     if (HandleMessage)
08651     {
08652         BROADCAST_TO_CLASS( DialogMsg(BroadcastWindow, DIM, Gadget, DlgMsgParam, PageID), DialogOp );
08653     }
08654 #endif
08655     return HandleMessage;
08656 }
08657 
08658 
08659 /********************************************************************************************
08660 
08661 >   void DialogManager::Dlg_OnCommand(HWND hwnd, INT32 id, HWND hwndCtl, UINT32 codeNotify)
08662 
08663     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
08664     Created:    16/9/93
08665     Purpose:    OnCommand message handler. Translates a windows Command message into a DIM
08666     Errors:     -
08667     SeeAlso:    -
08668 
08669 ********************************************************************************************/
08670 
08671 void DialogManager::Dlg_OnCommand( wxWindow *pWnd, INT32 id, wxWindow *pWndCtl, INT32 codeNotify )
08672 {
08673     PORTNOTETRACE("dialog","DialogManager::Dlg_OnCommand - do nothing");
08674 #ifndef EXCLUDE_FROM_XARALX
08675     String_256 ClassNameStr;
08676     GetClassName(hwndCtl, (TCHAR*)ClassNameStr, 255);
08677 
08678     // -------------------------------------------------------------------------------------
08679     // Special processing
08680 
08681     // Commit processing
08682     if (id == IDOK)
08683     {
08684         if (codeNotify == BN_RGT_CLICKED)
08685         {
08686             DialogManager::DIM = DIM_SOFT_COMMIT;
08687             DialogManager::HandleMessage = TRUE;
08688             return;
08689         }
08690         else
08691         {
08692             // Either left button clicked or ENTER was pressed in a control.
08693             DialogManager::DIM = DIM_COMMIT;
08694             DialogManager::HandleMessage = TRUE;
08695             SetGadgetIDToFocus(hwnd);
08696             //Move focus to the next control in the dialog.
08697             PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0L) ;
08698             return;
08699         }
08700     }
08701     else if (id == _R(ID_CC_APPLY_NOW))
08702     {
08703         // Clicking on the apply now button is the same as a soft commit
08704         DialogManager::DIM = DIM_SOFT_COMMIT;
08705         DialogManager::HandleMessage = TRUE;
08706         return;
08707 
08708     }
08709     else if (id == IDCANCEL)
08710     {
08711         DialogManager::DIM = DIM_CANCEL;
08712         DialogManager::HandleMessage = TRUE;
08713         SetGadgetIDToFocus(hwnd);
08714         return;
08715     }
08716 
08717     // -------------------------------------------------------------------------------------
08718     // Button control messages
08719     if ((ClassNameStr == String_8(TEXT("Button"))))
08720     {
08721         switch (codeNotify)
08722         {
08723             case BN_RGT_CLICKED:
08724                 DialogManager::DIM = DIM_RGT_BN_CLICKED;
08725                 DialogManager::HandleMessage = TRUE;
08726                 break;
08727 
08728             case BN_CLICKED:
08729                 DialogManager::DIM = DIM_LFT_BN_CLICKED;
08730                 DialogManager::HandleMessage = TRUE;
08731                 break;
08732         }
08733     }
08734     else if ( (ClassNameStr == String_8(TEXT("ListBox"))) ||  // ListBox control messages
08735             (ClassNameStr == String_16(TEXT("cc_CheckList")))
08736             )
08737     {
08738         switch (codeNotify)
08739         {
08740             case LBN_ERRSPACE:
08741                 DialogManager::DIM = DIM_OUT_OF_SPACE;
08742                 DialogManager::HandleMessage = TRUE;
08743                 break;
08744             case LBN_SELCHANGE:
08745                 DialogManager::DIM = DIM_SELECTION_CHANGED;
08746                 DialogManager::HandleMessage = TRUE;
08747 //              ::SetFocus(NULL);       // This is done for us by SendDialogMessage
08748                                         // If we do it here, DIM_SEL_CHANGED is NOT broadcast!
08749                 break;
08750             case LBN_DBLCLK:
08751                 DialogManager::DIM = DIM_SELECTION_CHANGED_COMMIT;
08752                 DialogManager::HandleMessage = TRUE;
08753                 break;
08754             case LBN_SELCANCEL:
08755                 DialogManager::DIM = DIM_SELECTION_CANCELED;
08756                 DialogManager::HandleMessage = TRUE;
08757                 break;
08758         }
08759     }
08760     else if ( (ClassNameStr == String_8(TEXT("ComboBox"))) || // ComboBox control messages
08761             (ClassNameStr == String_64(TEXT("cc_1dBitmapComboBoxEdit"))) ||
08762             (ClassNameStr == String_64(TEXT("cc_2dBitmapComboBoxEdit")))
08763             )
08764     {
08765 //      BOOL SetComboText = FALSE;
08766         switch (codeNotify)
08767         {
08768             case CBN_KILLFOCUS:
08769                 // If a combo box loses the input focus, broadcast this fact. It can be
08770                 // used as a 'confirm' message for the contents of the combo box editable
08771                 // field which will work under all circumstances (pressing return or tab,
08772                 // Alt-tabbing to another application, closing the window, clicking on
08773                 // another control/window/application, etc etc), as opposed to other
08774                 // 'confirm' information which you only get *sometimes*.
08775                 DialogManager::DIM = DIM_FOCUS_LOST;
08776                 DialogManager::HandleMessage = TRUE;
08777                 break;
08778             case CBN_DROPDOWN:
08779                 // If a combo box loses the input focus, broadcast this fact. It can be
08780                 // used as a 'confirm' message for the contents of the combo box editable
08781                 // field which will work under all circumstances (pressing return or tab,
08782                 // Alt-tabbing to another application, closing the window, clicking on
08783                 // another control/window/application, etc etc), as opposed to other
08784                 // 'confirm' information which you only get *sometimes*.
08785                 DialogManager::DIM = DIM_LISTDROPPED;
08786                 DialogManager::HandleMessage = TRUE;
08787                 break;
08788             case CBN_ERRSPACE:
08789                 DialogManager::DIM = DIM_OUT_OF_SPACE;
08790                 DialogManager::HandleMessage = TRUE;
08791                 break;
08792             case CBN_SELCHANGE:
08793                 ::PostMessage(hwnd, CBN_CAM_SELCHANGE,
08794                             (WPARAM) DIM_SELECTION_CHANGED,
08795                             (LPARAM) Gadget);
08796                 // Removed by Chris 22 March 95
08797                 // fixes can't cursor through combo's bug
08798                 //::SetFocus(NULL);                     // don't do this - it's senseless
08799                 break;
08800 
08801             case CBN_DBLCLK:        // A "Simple" listbox item has been double-clicked
08802             case CBN_SELENDOK:      // The user has confirmed their choice (seems to miss kbd input!)
08803             case CBN_CLOSEUP:       // The control's dropdown is being closed
08804                 ::PostMessage(hwnd, CBN_CAM_SELCHANGE,
08805                             (WPARAM) DIM_SELECTION_CHANGED_COMMIT,
08806                             (LPARAM) Gadget);
08807                 break;
08808 
08809             case CBN_EDITCHANGE:                           // Text in edit portion of combo has changed
08810                 DialogManager::DIM = DIM_TEXT_CHANGED;
08811                 DialogManager::HandleMessage = TRUE;
08812                 break;
08813         }
08814     }
08815 
08816     else if (ClassNameStr == String_8(TEXT("Edit"))) // ComboBox control messages
08817     {
08818         switch (codeNotify)
08819         {
08820             case EN_CHANGE:                        // Text in edit control has changed
08821                 DialogManager::DIM = DIM_TEXT_CHANGED;
08822                 DialogManager::HandleMessage = TRUE;
08823                 break;
08824 
08825             case EN_SETFOCUS:                       // Edit control has focus (i.e. been clicked on, tabbed to, etc)
08826                 DialogManager::DIM = DIM_SET_FOCUS;
08827                 DialogManager::HandleMessage = TRUE;
08828                 break;
08829 
08830             case EN_KILLFOCUS:                      // Edit control looses focus (i.e. another field's been clicked on, tabbed to, etc)
08831                 DialogManager::DIM = DIM_KILL_FOCUS;
08832                 DialogManager::HandleMessage = TRUE;
08833                 break;
08834         }
08835     }
08836 #endif
08837 }
08838 
08839 /********************************************************************************************
08840 
08841 >   void DialogManager::Dlg_OnScroll(HWND hwnd, HWND hwndCtl, UINT32 code, INT32 pos)
08842 
08843     Author:     Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com>
08844     Created:    16/9/93
08845     Purpose:    OnHScroll and OnVScroll message handler. Translates a windows scroll message
08846                 into a DIM. This routine is used for Scroll bars and Trackbars
08847     Errors:     -
08848     SeeAlso:    -
08849 
08850 ********************************************************************************************/
08851 
08852 void DialogManager::Dlg_OnScroll( wxWindow *pWnd, wxWindow *pWndCtl, UINT32 code, INT32 pos )
08853 {
08854     PORTNOTETRACE("dialog","DialogManager::Dlg_OnScroll - do nothing");
08855 #ifndef EXCLUDE_FROM_XARALX
08856     // Determine if the control is a scroll bar or track bar
08857     String_256 ClassNameStr;
08858     GetClassName(hwndCtl, (TCHAR*)ClassNameStr, 255);
08859     BOOL ScrollControl = (ClassNameStr == String_16(TEXT("ScrollBar")));
08860     BOOL SpinControl = (ClassNameStr == String_32(TEXT("msctls_updown32")));
08861 
08862     INT32 Page; // Number of units to move for a PAGE event
08863 
08864     if (!SpinControl)
08865     {
08866         // Obtain Page increment information
08867         ScrollPageInc* PgInc = (ScrollPageInc*)(ScrollPageIncList.GetHead());
08868         BOOL FoundPageIncDetails = FALSE;
08869         while (PgInc != NULL)
08870         {
08871             if (PgInc->ScrollBarWnd == hwndCtl) // Found details
08872             {
08873                 FoundPageIncDetails = TRUE;
08874                 Page = PgInc->PageInc;
08875             }
08876             PgInc = (ScrollPageInc*)ScrollPageIncList.GetNext((ListItem*)PgInc);
08877         }
08878         ENSURE(FoundPageIncDetails, "Scroll bar has not has its range of values set");
08879     }
08880 
08881     // Obtain scroll bars range and current thumb position
08882     INT32 ScrollMin;
08883     INT32 ScrollMax;
08884 
08885     WORD CurrentThumbPos;
08886 
08887     if (ScrollControl)
08888     {
08889         GetScrollRange(hwndCtl, SB_CTL, &ScrollMin, &ScrollMax);
08890         CurrentThumbPos = (WORD)GetScrollPos(hwndCtl, SB_CTL);
08891     }
08892     else if (SpinControl)
08893     {
08894         DWORD ScrollRange = SendMessage (hwndCtl, UDM_GETRANGE, 0, 0);
08895         ScrollMin = HIWORD (ScrollRange);
08896         ScrollMax = LOWORD (ScrollRange);
08897         CurrentThumbPos = (INT32) SendMessage(hwndCtl, UDM_GETPOS, 0, 0);
08898 
08899         if (SpinControlMessageUp)
08900         {
08901             code = SB_LINEUP;
08902         }
08903         else if (SpinControlMessageDown)
08904         {
08905             code = SB_LINEDOWN;
08906         }
08907         else
08908         {
08909             return;
08910         }
08911 //      else
08912 //      {
08913 //          ERROR3 ("A serious error has occured!");
08914 //      }
08915     }
08916     else // Trackbar
08917     {
08918         ScrollMin = (INT32) SendMessage(hwndCtl, TBM_GETRANGEMIN, 0, 0);
08919         ScrollMax = (INT32) SendMessage(hwndCtl, TBM_GETRANGEMAX, 0, 0);
08920         CurrentThumbPos = (WORD) SendMessage(hwndCtl, TBM_GETPOS, 0, 0);
08921     }
08922 
08923     INT32 ScrollBarInc = 0;
08924     INT32 NewPos;
08925 
08926     switch (code)
08927     {
08928         case SB_TOP:     // Same as SB_LEFT TB_TOP
08929             ScrollBarInc = -(INT32)(CurrentThumbPos - ScrollMin);
08930             break;
08931         case SB_BOTTOM: // Same as SB_RIGHT, TB_BOTTOM
08932             ScrollBarInc = ScrollMax - CurrentThumbPos;
08933             break;
08934         case SB_LINEUP:  // Same as SB_LINELEFT, TB_LINEUP
08935             ScrollBarInc = -1;
08936             break;
08937         case SB_LINEDOWN: // Same as SB_LINERIGHT, TB_LINEDOWN
08938             ScrollBarInc = 1;
08939             break;
08940         case SB_PAGEUP:   // Same as SB_PAGELEFT, TB_PAGEUP
08941             ScrollBarInc = -Page;
08942             break;
08943         case SB_PAGEDOWN:  // Same as SB_PAGERIGHT, TB_PAGERIGHT
08944             ScrollBarInc = Page;
08945             break;
08946         case SB_THUMBTRACK: // Same as TB_THUMBTRACK
08947             ScrollBarInc = pos - CurrentThumbPos;
08948             break;
08949         case SB_THUMBPOSITION:
08950 
08951             break;
08952     }
08953 
08954     NewPos = CurrentThumbPos + ScrollBarInc;
08955     NewPos = max(ScrollMin, min(NewPos, ScrollMax));
08956 
08957     if (ScrollBarInc != 0)
08958     {
08959         if (ScrollControl)
08960         {
08961             SetScrollPos(hwndCtl, SB_CTL, NewPos, TRUE);
08962         }
08963         else if (!SpinControl)
08964         {
08965             SendMessage(hwndCtl, TBM_SETPOS,1,(INT32)NewPos );
08966         }
08967 
08968         // converting all scrollbar messages to DIM_SELECTION_CHANGED seems extremely
08969         // stupid to me, and in the case of the spin controls this creates a new problem:
08970 
08971         // in dialogs that respond to DIM_SELECTION_CHANGED for the correct purpose, spin
08972         // controls also enter into this logic - which causes/is extremely undesired behaviour!
08973 
08974         // SOLUTION - I'm adding some new DIM's which will allow me to differentiate ....
08975 
08976         if (ScrollControl)
08977         {
08978             DIM = DIM_SELECTION_CHANGED;
08979         }
08980         else if (SpinControl)
08981         {
08982             if (SpinControlMessageUp)
08983             {
08984                 DIM = DIM_SPINCONTROLUP;
08985                 SpinControlMessageUp = FALSE;
08986             }
08987             else    // MUST be SpinControlMessageDown - otherwise we would have retuned by now!
08988             {
08989                 SpinControlMessageDown = FALSE;
08990                 DIM = DIM_SPINCONTROLDOWN;
08991             }
08992         }
08993         else
08994         {
08995             DIM = DIM_SELECTION_CHANGED;
08996         }
08997 
08998         HandleMessage = TRUE;
08999     }
09000 #endif
09001 }
09002 
09003 
09004 #endif
09005 
09006 
09007 
09008 
09009 /********************************************************************************************
09010 
09011 >   static CTreeItemID DialogManager::SetTreeGadgetItem(CWindowID wnd,
09012                                                         CGadgetID Gadget,
09013                                                         CTreeItemID hParent,
09014                                                         const StringBase& str,
09015                                                         CTreeItemID hInsAfter,
09016                                                         INT32 iImage,
09017                                                         CCObject* pObj = NULL)
09018 
09019     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09020     Created:    08/Feb/2006
09021     Inputs:     WindowID: Dialog box window identifier
09022                 Gadget: Gadget identifier
09023                 StrID:    Resource ID of string
09024     Outputs:    -
09025     Returns:    TRUE if the gadgets value could be set
09026                 FALSE if it could not
09027     Purpose:    To insert an item into a tree control
09028 
09029     Errors:     If the function is called on an invalid control then an ENSURE failure will
09030                 occur in a DEBUG build. In a retail build FALSE is returned.
09031 
09032     SeeAlso:    DialogOp::SetStringGadgetValue
09033 
09034 ********************************************************************************************/
09035 
09036 CTreeItemID DialogManager::SetTreeGadgetItem(CWindowID wnd,
09037                                             CGadgetID Gadget,
09038                                             CTreeItemID hParent,
09039                                             const StringBase& str,
09040                                             CTreeItemID hInsAfter,
09041                                             INT32 iImage,
09042                                             CCObject* pObj)
09043 {
09044     wxWindow * pGadget = GetGadget(wnd, Gadget);
09045     if (!pGadget) return CTreeItemID();
09046 
09047     wxString String = str;
09048 
09049     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09050         )
09051     {
09052         CamelotTreeItemData* pData = NULL;
09053         if (pObj)
09054             pData = new CamelotTreeItemData(pObj);
09055 
09056         return ((wxTreeCtrl*)pGadget)->InsertItem(hParent, hInsAfter, String, iImage, -1, pData);
09057     }
09058 
09059     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09060 
09061     return CTreeItemID();
09062 }
09063 
09064 
09065 
09066 
09067 /********************************************************************************************
09068 
09069 >   static CCObject* DialogManager::GetTreeGadgetItemData(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09070 
09071     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09072     Created:    08/Feb/2006
09073     Inputs:     WindowID: Dialog box window identifier
09074                 Gadget: Gadget identifier
09075     Outputs:    -
09076     Returns:    TRUE if the gadgets value could be set
09077                 FALSE if it could not
09078     Purpose:    To insert an item into a tree control
09079 
09080     Errors:     If the function is called on an invalid control then an ENSURE failure will
09081                 occur in a DEBUG build. In a retail build FALSE is returned.
09082 
09083     SeeAlso:    DialogOp::SetStringGadgetValue
09084 
09085 ********************************************************************************************/
09086 
09087 CCObject* DialogManager::GetTreeGadgetItemData(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09088 {
09089     wxWindow* pGadget = GetGadget(wnd, Gadget);
09090     if (!pGadget) return NULL;
09091 
09092     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09093         )
09094     {
09095         wxTreeItemData* pData = ((wxTreeCtrl*)pGadget)->GetItemData(hItem);
09096         if (pData) // && pData->IsKindOf(CLASSINFO(CamelotTreeItemData)))
09097             return ((CamelotTreeItemData*)pData)->GetObject();
09098 
09099         return NULL;
09100     }
09101 
09102     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09103 
09104     return NULL;
09105 }
09106 
09107 
09108 
09109 
09110 /********************************************************************************************
09111 
09112 >   BOOL DialogManager::SelectTreeGadgetItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem, BOOL bNewState)
09113 
09114     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09115     Created:    08/Feb/2006
09116     Inputs:     WindowID    - Dialog box window identifier
09117                 Gadget      - Gadget identifier
09118                 hItem       - ID of item
09119                 bNewState   - Selection state to set
09120     Outputs:    -
09121     Returns:    TRUE if the gadget item was selected
09122                 FALSE if it could not
09123     Purpose:    To select an item in a tree control
09124 
09125 ********************************************************************************************/
09126 
09127 BOOL DialogManager::SelectTreeGadgetItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem, BOOL bNewState)
09128 {
09129     wxWindow* pGadget = GetGadget(wnd, Gadget);
09130     if (!pGadget) return FALSE;
09131 
09132     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09133         )
09134     {
09135         ((wxTreeCtrl*)pGadget)->SelectItem(hItem, FALSE != bNewState);
09136         return TRUE;
09137     }
09138 
09139     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09140     return FALSE;
09141 }
09142 
09143 
09144 
09145 
09146 /********************************************************************************************
09147 
09148 >   CTreeItemID DialogManager::GetTreeGadgetRootItem(CWindowID wnd, CGadgetID Gadget)
09149 
09150     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09151     Created:    08/Feb/2006
09152     Inputs:     WindowID    - Dialog box window identifier
09153                 Gadget      - Gadget identifier
09154     Outputs:    -
09155     Returns:    ID of item
09156     Purpose:    To get the ID of the root item in the tree control
09157 
09158 ********************************************************************************************/
09159 
09160 CTreeItemID DialogManager::GetTreeGadgetRootItem(CWindowID wnd, CGadgetID Gadget)
09161 {
09162     wxWindow* pGadget = GetGadget(wnd, Gadget);
09163     if (!pGadget) return CTreeItemID();
09164 
09165     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09166         )
09167     {
09168         return ((wxTreeCtrl*)pGadget)->GetRootItem();
09169 
09170         return CTreeItemID();
09171     }
09172 
09173     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09174     return CTreeItemID();
09175 }
09176 
09177 
09178 
09179 
09180 /********************************************************************************************
09181 
09182 >   CTreeItemID DialogManager::GetTreeGadgetFirstSelectedItem(CWindowID wnd, CGadgetID Gadget)
09183 
09184     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09185     Created:    08/Feb/2006
09186     Inputs:     WindowID    - Dialog box window identifier
09187                 Gadget      - Gadget identifier
09188                 hItem       - ID of item
09189     Outputs:    -
09190     Returns:    ID of item
09191     Purpose:    To get the ID of the first selected item in the tree control
09192 
09193 ********************************************************************************************/
09194 
09195 CTreeItemID DialogManager::GetTreeGadgetFirstSelectedItem(CWindowID wnd, CGadgetID Gadget)
09196 {
09197     wxWindow* pGadget = GetGadget(wnd, Gadget);
09198     if (!pGadget) return CTreeItemID();
09199 
09200     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09201         )
09202     {
09203         return ((wxTreeCtrl*)pGadget)->GetSelection();
09204     }
09205 
09206     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09207     return CTreeItemID();
09208 }
09209 
09210 
09211 
09212 
09213 /********************************************************************************************
09214 
09215 >   BOOL DialogManager::TreeGadgetExpandItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09216 
09217     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09218     Created:    08/Feb/2006
09219     Inputs:     WindowID    - Dialog box window identifier
09220                 Gadget      - Gadget identifier
09221                 hItem       - ID of item
09222                 bNewState   - Selection state to set
09223     Outputs:    -
09224     Returns:    TRUE if the gadget item was expanded
09225                 FALSE if it could not
09226     Purpose:    To expand an item in the tree control
09227 
09228 ********************************************************************************************/
09229 
09230 BOOL DialogManager::TreeGadgetExpandItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09231 {
09232     wxWindow* pGadget = GetGadget(wnd, Gadget);
09233     if (!pGadget) return FALSE;
09234 
09235     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09236         )
09237     {
09238         ((wxTreeCtrl*)pGadget)->Expand(hItem);
09239         return TRUE;
09240     }
09241 
09242     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09243     return FALSE;
09244 }
09245 
09246 
09247 
09248 
09249 /********************************************************************************************
09250 
09251 >   CTreeItemID DialogManager::GetTreeGadgetNextVisItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09252 
09253     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09254     Created:    08/Feb/2006
09255     Inputs:     WindowID    - Dialog box window identifier
09256                 Gadget      - Gadget identifier
09257                 hItem       - ID of item
09258     Outputs:    -
09259     Returns:    ID of item
09260     Purpose:    To get the ID of the next visible item in the tree control after a specified item
09261 
09262 ********************************************************************************************/
09263 
09264 CTreeItemID DialogManager::GetTreeGadgetNextVisItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09265 {
09266     wxWindow* pGadget = GetGadget(wnd, Gadget);
09267     if (!pGadget) return CTreeItemID();
09268 
09269     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09270         )
09271     {
09272         return ((wxTreeCtrl*)pGadget)->GetNextVisible(hItem);
09273     }
09274 
09275     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09276     return CTreeItemID();
09277 }
09278 
09279 
09280 
09281 
09282 /********************************************************************************************
09283 
09284 >   CTreeItemID DialogManager::GetTreeGadgetFirstChildItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09285 
09286     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09287     Created:    08/Feb/2006
09288     Inputs:     WindowID    - Dialog box window identifier
09289                 Gadget      - Gadget identifier
09290                 hItem       - ID of item
09291     Outputs:    -
09292     Returns:    ID of item
09293     Purpose:    To get the ID of the first child item of the specified in the tree control
09294 
09295 ********************************************************************************************/
09296 
09297 CTreeItemID DialogManager::GetTreeGadgetFirstChildItem(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem)
09298 {
09299     wxWindow* pGadget = GetGadget(wnd, Gadget);
09300     if (!pGadget) return CTreeItemID();
09301 
09302     if ( pGadget->IsKindOf(CLASSINFO(wxTreeCtrl))
09303         )
09304     {
09305         wxTreeItemIdValue sessioncookie;
09306         return ((wxTreeCtrl*)pGadget)->GetFirstChild(hItem, sessioncookie);
09307     }
09308 
09309     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09310     return CTreeItemID();
09311 }
09312 
09313 
09314 
09315 
09316 /********************************************************************************************
09317 
09318 >   size_t DialogManager::GetTreeGadgetChildrenCount(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem, BOOL bRecursive)
09319 
09320     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09321     Created:    08/Feb/2006
09322     Inputs:     WindowID    - Dialog box window identifier
09323                 Gadget      - Gadget identifier
09324                 hItem       - ID of item
09325                 bRecursive  - TRUE if should count children recursively
09326     Outputs:    -
09327     Returns:    number of children
09328     Purpose:    To get the number of children of an item in a tree control
09329 
09330 ********************************************************************************************/
09331 
09332 UINT32 DialogManager::GetTreeGadgetChildrenCount(CWindowID wnd, CGadgetID Gadget, CTreeItemID hItem, BOOL bRecursive)
09333 {
09334     wxWindow* pGadget = GetGadget(wnd, Gadget);
09335     if (!pGadget) return 0;
09336 
09337     if( pGadget->IsKindOf( CLASSINFO(wxTreeCtrl) ) )
09338     {
09339         return UINT32( ((wxTreeCtrl*)pGadget)->GetChildrenCount( hItem, FALSE != bRecursive ) );
09340     }
09341 
09342     ERROR3("SetTreeGadgetItem called on non-tree gadget");
09343     return 0;
09344 }
09345 
09346 
09347 
09348 
09349 /********************************************************************************************
09350 
09351 >   UINT32 DialogManager::GetGadgetImageCount(CWindowID wnd, CGadgetID Gadget)
09352 
09353     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09354     Created:    08/Feb/2006
09355     Inputs:     WindowID    - Dialog box window identifier
09356                 Gadget      - Gadget identifier
09357     Outputs:    -
09358     Returns:    Number of images in tree control
09359     Purpose:    To get the number of images set in the trree control
09360 
09361 ********************************************************************************************/
09362 
09363 UINT32 DialogManager::GetGadgetImageCount(CWindowID wnd, CGadgetID Gadget)
09364 {
09365     ERROR3("Unimplemented!");
09366     return 0;
09367 }
09368 
09369 
09370 /********************************************************************************************
09371 
09372 >   CGadgetImageList::~CGadgetImageList()
09373 
09374     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
09375     Created:    08/Feb/2006
09376     Purpose:    Destructor
09377 
09378 ********************************************************************************************/
09379 
09380 CGadgetImageList::~CGadgetImageList()
09381 {
09382     m_BitmapIDList.DeleteAll();
09383 }
09384 
09385 /********************************************************************************************
09386 
09387 >   UINT32 CGadgetImageList::Add(CDlgResID resID)
09388 
09389     Author:     Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
09390     Created:    08/Feb/2006
09391     Inputs:     resID - resource ID of the image
09392     Returns:    The index of the image
09393     Purpose:    Adds an image to the list
09394 
09395 ********************************************************************************************/
09396 
09397 UINT32 CGadgetImageList::Add(CDlgResID resID)
09398 {
09399     m_BitmapIDList.AddTail(new ResIDListItem(resID));
09400     return m_BitmapIDList.GetCount()-1;
09401 }
09402 
09403 
09404 /********************************************************************************************
09405 
09406 >   ListItem* CGadgetImageList::FindFirstBitmap(ResourceID* presID) const
09407 
09408     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09409     Created:    08/Feb/2006
09410     Inputs:     -
09411     Outputs:    presID  - ResourceID of first tiem in list
09412     Returns:    Pointer to context list item for iteration or NULL
09413     Purpose:    To get the first resourceID stored in this image list object
09414 
09415 ********************************************************************************************/
09416 
09417 ListItem* CGadgetImageList::FindFirstBitmap(ResourceID* presID) const
09418 {
09419     ResIDListItem* pItem = (ResIDListItem*)m_BitmapIDList.GetHead();
09420     if (presID && pItem)
09421         *presID = pItem->m_ResID;
09422 
09423     return (ListItem*)pItem;
09424 }
09425 
09426 
09427 
09428 
09429 /********************************************************************************************
09430 
09431 >   ListItem* CGadgetImageList::FindNextBitmap(ListItem* pContextItem, ResourceID* presID) const
09432 
09433     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
09434     Created:    08/Feb/2006
09435     Inputs:     pContextItem - pointer to current context
09436     Outputs:    ResourceID - resource ID from list item
09437     Returns:    Pointer to context list item for iteration or NULL
09438     Purpose:    To get the next resourceID stored in this image list object after the specified item
09439 
09440 ********************************************************************************************/
09441 
09442 ListItem* CGadgetImageList::FindNextBitmap(ListItem* pContextItem, ResourceID* presID) const
09443 {
09444     ResIDListItem* pItem = (ResIDListItem*)m_BitmapIDList.GetNext(pContextItem);        // (Ahem! Maybe there's a better way to do this...)
09445     if (presID && pItem)
09446         *presID = pItem->m_ResID;
09447 
09448     return (ListItem*)pItem;
09449 }
09450 
09451 

Generated on Sat Nov 10 03:48:22 2007 for Camelot by  doxygen 1.4.4