selinfo.cpp

Go to the documentation of this file.
00001 // $Id: selinfo.cpp 1282 2006-06-09 09:46:49Z 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 // Selector Tool info-bar operations
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 //#include "dlgtypes.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 #include "selector.h"
00106 #include "selinfo.h"
00107 //#include "selmsg.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00110 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "opnudge.h"
00113 //#include "justin.h"
00114 //#include "fillattr.h" // For CC_RUNTIME_CLASS(AttrFillChanged) - in camtypes.h [AUTOMATICALLY REMOVED]
00115 #include "optsmsgs.h"
00116 #include "userrect.h"
00117 //#include "barsdlgs.h"
00118 
00119 
00120 //Matt 11/11/00 - I only wanted a function from the next line...
00121 #include "slicehelper.h"    //For helper functions
00122 
00123 //But I had to include all of these to get it to work!!...
00124 //#include "cxfrech.h"      //For CamelotRecordHandler - in camtypes.h [AUTOMATICALLY REMOVED]
00125 #include "userattr.h"       //For UserAttr
00126 #include "tmpltatr.h"       //For TemplateAttribute
00127 
00128 
00129 DECLARE_SOURCE( "$Revision: 1282 $" );
00130 CC_IMPLEMENT_DYNCREATE(SelectorInfoBarOp, InformationBarOp)
00131 
00132 #define new CAM_DEBUG_NEW
00133 
00134 
00135 // This defines a pointer to a SelectorTool member function that takes two INT32s and
00136 // returns nothing.  It is used to present a uniform interface to the DoXXXXImmediate
00137 // functions, which respond to changes in the info-bar edit-fields.
00138 typedef void (SelectorTool::*SELTOOLFUNC)(INT32, INT32);
00139 
00140 
00141 // These maintain the state of the info-bar's buttons.
00142 BOOL SelectorInfoBarOp::fLockAspect = TRUE;
00143 BOOL SelectorInfoBarOp::fRotateMode = FALSE;
00144 BOOL SelectorInfoBarOp::fScaleLines = TRUE;
00145 // BOOL SelectorInfoBarOp::fLeaveCopy = FALSE;
00146 // BOOL SelectorInfoBarOp::fTransFills = TRUE;
00147 
00148 
00149 
00150 /********************************************************************************************
00151 >   SelectorInfoBarOp::SelectorInfoBarOp()
00152 
00153     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00154     Created:    11/7/94
00155     Purpose:    Default constructor for a SelectorInfoBarOp.
00156     SeeAlso:    class InformationBarOp
00157 ********************************************************************************************/
00158 
00159 SelectorInfoBarOp::SelectorInfoBarOp()
00160   : pSelectorTool(NULL)
00161 {
00162     DlgResID = _R(IDD_SELECTORINFO);
00163 }
00164 
00165 
00166 
00167 /********************************************************************************************
00168 >   virtual MsgResult SelectorInfoBarOp::Message(Msg* pMessage) 
00169 
00170     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00171     Created:    11/7/94
00172     Inputs:     pMessage - A pointer to a dialog message.
00173     Returns:    The result of the message.
00174     Purpose:    Takes a look at the message and if it is for for selector tool info-bar
00175                 then respond to it.
00176     Errors:     -
00177     SeeAlso:    SelectorInfoBarOp::HandleCreate; SelectorInfoBarOp::HandleButtonDown;
00178                 SelectorInfoBarOp::HandleSelChange; SelectorTool::SelectionHasChanged
00179 ********************************************************************************************/
00180 
00181 MsgResult SelectorInfoBarOp::Message(Msg* pMessage) 
00182 {
00183     // If we aren't the current tool then pass to the base class.
00184     if (((SelectorTool*) Tool::GetCurrent()) != pSelectorTool /* || !HasWindow() */)
00185     {
00186         return InformationBarOp::Message(pMessage);
00187     }
00188 
00189     // Does this message mean that the selected object has changed, or its attributes (bounds)?
00190     if (pMessage->IsKindOf(CC_RUNTIME_CLASS(SelChangingMsg)))
00191     {   
00192         if (pSelectorTool != NULL)
00193         {
00194             switch (((SelChangingMsg*) pMessage)->State)
00195             {
00196             case SelChangingMsg::SELECTIONCHANGED:
00197                 if (!pSelectorTool->fIgnoreSelChange) pSelectorTool->SelectionHasChanged();
00198                 break;
00199             
00200             case SelChangingMsg::NONCOLOURATTCHANGED:
00201                 pSelectorTool->AttributeHasChanged();
00202                 break;
00203             
00204             default:
00205                 break;
00206             }
00207         }
00208     }
00209 
00210     // How about a view changing message?
00211     else if (MESSAGE_IS_A(pMessage, DocViewMsg))
00212     {
00213         // Yes, tell the selector tool to sort its blobs out.
00214         if (pSelectorTool != NULL)
00215         {
00216             pSelectorTool->ViewChanged(*((DocViewMsg*) pMessage));
00217         }
00218     }
00219 
00220     // Or an options-changing message?
00221     else if (MESSAGE_IS_A(pMessage, OptionsChangingMsg))
00222     {
00223         // Yes, so force the edit-fields to reconvert themselves to the new settings.
00224         TRACEUSER( "JustinF", _T("Updating on options-change in selector tool info-bar\n"));
00225         SetEdit_OnSelectionChange();
00226     }
00227 
00228     // Otherwise, is this a dialog message for us?
00229     else if (IS_OUR_DIALOG_MSG(pMessage))
00230     {
00231         // Yes.  Act on the dialog message.
00232         DialogMsg* pDlgMsg = (DialogMsg*) pMessage;
00233         switch (pDlgMsg->DlgMsg)
00234         {           
00235             // Initialise the bar's controls.
00236             case DIM_CREATE:
00237                 HandleCreate(pDlgMsg);
00238                 break;
00239                 
00240             // "Close" the bar.
00241             case DIM_CANCEL:
00242                 SelectorTool::UnCacheInfoBar(TRUE);
00243                 break;
00244 
00245             // Handle a button being clicked.
00246             case DIM_LFT_BN_CLICKED:
00247                 if (!HandleButtonDown(pDlgMsg)) return DialogBarOp::Message(pMessage);
00248                 break;
00249 
00250             // Handle a button being released.
00251             case DIM_LFT_BN_UP:
00252                 HandleButtonUp(pDlgMsg);
00253                 break;
00254 
00255             // Handle ENTER being typed in an edit field.
00256             case DIM_SELECTION_CHANGED:
00257                 HandleEditCommit(pDlgMsg);
00258                 break;
00259 
00260             // Handle a "telephone keypad" button message.
00261             case DIM_GRID_BUTTON_DOWN:
00262                 HandleGridButton(pDlgMsg);
00263                 break;
00264 
00265             // Some other message irrelevant to us.
00266             default:
00267                 break;
00268         }
00269     }
00270 
00271     // Pass message on to base class.
00272     return InformationBarOp::Message(pMessage); 
00273 }
00274 
00275 
00276 
00277 /********************************************************************************************
00278 >   BOOL SelectorInfoBarOp::IsAspectLocked() const
00279 
00280     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00281     Created:    31/8/94
00282     Inputs:     -
00283     Outputs:    -
00284     Returns:    TRUE if the "Lock Aspect Ratio" button is down.
00285     Purpose:    Enquires of the state of the "Lock Aspect Ratio" button.
00286     Errors:     -
00287     SeeAlso:    -
00288 ********************************************************************************************/
00289 
00290 BOOL SelectorInfoBarOp::IsAspectLocked() const
00291 {
00292     return fLockAspect;
00293 }
00294 
00295 
00296 
00297 /********************************************************************************************
00298 >   BOOL SelectorInfoBarOp::InRotateMode() const
00299 
00300     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00301     Created:    31/8/94
00302     Inputs:     -
00303     Outputs:    -
00304     Returns:    TRUE if the "Rotate/Bounds blobs" button is down.
00305     Purpose:    Checks the state of the "Rotate/Bounds blobs" button.
00306     Errors:     -
00307     SeeAlso:    -
00308 ********************************************************************************************/
00309 
00310 BOOL SelectorInfoBarOp::InRotateMode() const
00311 {
00312     return fRotateMode;
00313 }
00314 
00315 
00316 
00317 /********************************************************************************************
00318 >   BOOL SelectorInfoBarOp::ShouldLeaveCopy() const
00319 
00320     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00321     Created:    31/8/94
00322     Inputs:     -
00323     Outputs:    -
00324     Returns:    TRUE if the "Leave Copy" button is down.
00325     Purpose:    Checks the state of the "Leave Copy" button.
00326     Errors:     -
00327     SeeAlso:    -
00328 ********************************************************************************************/
00329 /*
00330 BOOL SelectorInfoBarOp::ShouldLeaveCopy() const
00331 {
00332     return fLeaveCopy;
00333 }
00334 */
00335 
00336 
00337 /********************************************************************************************
00338 >   BOOL SelectorInfoBarOp::ShouldScaleLines() const
00339 
00340     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00341     Created:    31/8/94
00342     Inputs:     -
00343     Outputs:    -
00344     Returns:    TRUE if the "Scale Lines" button is down.
00345     Purpose:    Checks the state of the "Scale Lines" button.
00346     Errors:     -
00347     SeeAlso:    -
00348 ********************************************************************************************/
00349 
00350 BOOL SelectorInfoBarOp::ShouldScaleLines() const
00351 {
00352     return fScaleLines;
00353 }
00354 
00355 
00356 
00357 /********************************************************************************************
00358 
00359 >   BOOL SelectorInfoBarOp::DontConsiderAttrs(void) const
00360 
00361     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00362     Created:    26/2/96
00363     Returns:    TRUE if attributes should NOT be considered in width/height displays
00364 
00365     Purpose:    Checks the "DontConsiderAttrs" state.
00366                 This is used to determine if displays and editing of widths and heights
00367                 of objects should include the effect of attributes - for example, line
00368                 widths can significantly affect the size of an object.
00369 
00370     Notes:      Depending on the user preferences, this option is either slaved off the
00371                 "Scale Line Widths" option, or is forced on/off permanently.
00372 
00373                 The preferences controlling this behaviour are held in the SelectorTool
00374 
00375 ********************************************************************************************/
00376 
00377 BOOL SelectorInfoBarOp::DontConsiderAttrs(void) const
00378 {
00379     // If "SlaveLineWidthToButton" preference is TRUE, then we use the Scale Line Widths
00380     // button state to determine the return value
00381     if (SelectorTool::fSlaveLineWidthToButton)
00382         return(!ShouldScaleLines());
00383 
00384     // Otherwise, we take the setting from the "ConsiderLineWidths" preference
00385     return(!SelectorTool::fConsiderLineWidths);
00386 }
00387 
00388 
00389 
00390 /********************************************************************************************
00391 >   BOOL SelectorInfoBarOp::ShouldTransFills() const
00392 
00393     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00394     Created:    31/8/94
00395     Inputs:     -
00396     Outputs:    -
00397     Returns:    TRUE if the "Transform Fills" button is down.
00398     Purpose:    Checks the state of the "Scale Lines" button.  NB. FEATURE REMOVED FOR
00399                 THIS RELEASE.
00400     Errors:     -
00401     SeeAlso:    -
00402 ********************************************************************************************/
00403 /*
00404 BOOL SelectorInfoBarOp::ShouldTransFills() const
00405 {
00406     return fTransFills;
00407 }
00408 */
00409 
00410 
00411 /********************************************************************************************
00412 >   void SelectorInfoBarOp::SetAspectLock(BOOL fState)
00413 
00414     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00415     Created:    31/8/94
00416     Inputs:     fState      the new state of the "Lock Aspect Ratio" button (TRUE = down)
00417     Outputs:    -
00418     Returns:    -
00419     Purpose:    Sets the state of the "Lock Aspect Ratio" button.
00420     Errors:     -
00421     SeeAlso:    -
00422 ********************************************************************************************/
00423 
00424 void SelectorInfoBarOp::SetAspectLock(BOOL fState)
00425 {
00426     if(HasWindow())
00427         SetLongGadgetValue(_R(IDC_SEL_PADLOCK), (fLockAspect = fState), FALSE);
00428 }
00429 
00430 
00431 
00432 /********************************************************************************************
00433 >   void SelectorInfoBarOp::SetRotateMode(BOOL fState)
00434 
00435     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00436     Created:    31/8/94
00437     Inputs:     fState          TRUE if the button should be down
00438     Outputs:    -
00439     Returns:    -
00440     Purpose:    Sets the state of the "Rotate/Bounds blobs" button.
00441     Errors:     -
00442     SeeAlso:    -
00443 ********************************************************************************************/
00444 
00445 void SelectorInfoBarOp::SetRotateMode(BOOL fState)
00446 {
00447     fRotateMode = fState;
00448     if (HasWindow()) SetLongGadgetValue(_R(IDC_SEL_ROTATEBUTTON), fState, FALSE);
00449 }
00450 
00451 
00452 
00453 /********************************************************************************************
00454 >   void SelectorInfoBarOp::SetLeaveCopy(BOOL fState)
00455 
00456     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00457     Created:    31/8/94
00458     Inputs:     fState          TRUE if the button should be down
00459     Outputs:    -
00460     Returns:    -
00461     Purpose:    Sets the state of the "Leave Copy" button.
00462     Errors:     -
00463     SeeAlso:    -
00464 ********************************************************************************************/
00465 /*
00466 void SelectorInfoBarOp::SetLeaveCopy(BOOL fState)
00467 {
00468     fLeaveCopy = fState;
00469     if (HasWindow()) SetLongGadgetValue(_R(IDC_SEL_LEAVECOPY), fLeaveCopy, FALSE);
00470 }
00471 */
00472 
00473 
00474 /********************************************************************************************
00475 >   void SelectorInfoBarOp::SetScaleLines(BOOL fState)
00476 
00477     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00478     Created:    31/8/94
00479     Inputs:     fState          TRUE if the button should be down
00480     Outputs:    -
00481     Returns:    -
00482     Purpose:    Sets the state of the "Scale Lines" button.
00483     Errors:     -
00484     SeeAlso:    -
00485 ********************************************************************************************/
00486 
00487 void SelectorInfoBarOp::SetScaleLines(BOOL fState)
00488 {
00489     if (HasWindow())
00490     {
00491         SetLongGadgetValue(_R(IDC_SEL_SCALELINES), (fScaleLines = fState), FALSE);
00492 
00493         // Make sure that the selector tool is displaying the correct information for
00494         // the new button state (which can affect the displayed size of the selection)
00495         if (pSelectorTool)
00496             pSelectorTool->SelectionHasChanged();
00497     }
00498 
00499 }
00500 
00501 
00502 
00503 /********************************************************************************************
00504 >   void SelectorInfoBarOp::SetTransFills(BOOL fState)
00505 
00506     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00507     Created:    31/8/94
00508     Inputs:     fState          TRUE if the button should be down
00509     Outputs:    -
00510     Returns:    -
00511     Purpose:    Sets the state of the "Transform Fills" button.  NB. FEATURE REMOVED FOR
00512                 THIS RELEASE.
00513     Errors:     -
00514     SeeAlso:    -
00515 ********************************************************************************************/
00516 /*
00517 void SelectorInfoBarOp::SetTransFills(BOOL fState)
00518 {
00519     SetLongGadgetValue(_R(IDC_SEL_TRANSFILL), (fTransFills = fState), FALSE);
00520 }
00521 */
00522 
00523 
00524 /********************************************************************************************
00525 >   SelEditRecord* SelectorInfoBarOp::GetRecord(UINT32 nEditControlID)
00526 
00527     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00528     Created:    4/11/94
00529     Inputs:     -
00530     Outputs:    -
00531     Returns:    -
00532     Purpose:    
00533     Errors:     -
00534     SeeAlso:    -
00535 ********************************************************************************************/
00536 
00537 SelEditRecord* SelectorInfoBarOp::GetRecord(UINT32 nEditControlID)
00538 {
00539     if (!HasWindow()) return NULL;
00540 
00541     // Search through the array of edit-records lloking for the given ID.
00542     for (SelEditRecord* per = aerEdits; per < &aerEdits[8]; per++)
00543     {
00544         if (per->nControlID == nEditControlID) return per;
00545     }
00546     
00547     // Couldn't find the corresponding edit-field (big problem!)
00548     ERROR3("Couldn't find edit-field record in SelectorInfoBarOp::GetRecord!");
00549     return NULL;
00550 }
00551 
00552 
00553 
00554 /********************************************************************************************
00555 >   void SelectorInfoBarOp::UpdateRecord(SelEditRecord* pefr)
00556 
00557     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00558     Created:    4/11/94
00559     Inputs:     pefr        ---         pointer to the edit-field record to be updated
00560     Outputs:    -
00561     Returns:    -
00562     Purpose:    Called when an edit-field is initialised or changed by the user.
00563     Errors:     -
00564     SeeAlso:    -
00565 ********************************************************************************************/
00566 
00567 void SelectorInfoBarOp::UpdateRecord(SelEditRecord* per)
00568 {
00569     if (per)
00570     {
00571         // Copy the text in the edit field.
00572         BOOL fOk = TRUE;
00573         if (HasWindow())
00574         {
00575             per->strText = GetStringGadgetValue(per->nControlID, &fOk);
00576             if (!fOk)
00577             {
00578                 TRACEUSER( "JustinF", _T("Couldn't update edit-field %u\n"), per->nControlID);
00579                 per->strText = TEXT("");
00580             }
00581         }
00582         else
00583         {
00584             per->strText = TEXT("");
00585         }
00586     }
00587 }
00588 
00589 
00590 
00591 /********************************************************************************************
00592 >   void SelectorInfoBarOp::UpdateRecord(UINT32 nControlID)
00593 
00594     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00595     Created:    16/11/94
00596     Inputs:     nControlID      resource ID the edit-control
00597     Outputs:    -
00598     Returns:    -
00599     Purpose:    Updates internal records of the given edit-control
00600     Errors:     -
00601     SeeAlso:    -
00602 ********************************************************************************************/
00603 
00604 void SelectorInfoBarOp::UpdateRecord(UINT32 nControlID)
00605 {
00606     UpdateRecord(GetRecord(nControlID));
00607 }
00608 
00609 
00610 
00611 /********************************************************************************************
00612 >   void SelectorInfoBarOp::UpdateAllRecords()
00613 
00614     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00615     Created:    16/11/94
00616     Inputs:     -
00617     Outputs:    -
00618     Returns:    -
00619     Purpose:    Updates internal records of all edit-controls.
00620     Errors:     -
00621     SeeAlso:    -
00622 ********************************************************************************************/
00623 
00624 void SelectorInfoBarOp::UpdateAllRecords()
00625 {
00626     for (SelEditRecord* per = aerEdits; per < &aerEdits[8]; per++)
00627     {
00628         UpdateRecord(per);
00629     }
00630 }
00631 
00632 
00633 
00634 /********************************************************************************************
00635 >   BOOL SelectorInfoBarOp::HasChangedRecord(INT32 i)
00636 
00637     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00638     Created:    16/11/94
00639     Inputs:     i           0 - 7, identifying which edit-control to report on.
00640     Outputs:    -
00641     Returns:    TRUE if edit-control [i] has been changed recently by the user
00642     Purpose:    Reports on whether the given edit-control has new info in it.
00643     Errors:     -
00644     SeeAlso:    -
00645 ********************************************************************************************/
00646 
00647 BOOL SelectorInfoBarOp::HasChangedRecord(INT32 i)
00648 {
00649     // Copy the text in the edit field.
00650     SelEditRecord* per = &aerEdits[i];
00651     BOOL fOk;
00652     String_256 str;
00653     if(HasWindow())
00654         str = GetStringGadgetValue(per->nControlID, &fOk);
00655     else
00656         fOk = FALSE;
00657 
00658     if (!fOk)
00659     {
00660         TRACEUSER( "JustinF", _T("Couldn't test edit-field %u\n"), per->nControlID );
00661         return per->fIsDirty = FALSE;
00662     }
00663 
00664     // Compare the existing text with the old record.
00665     return per->fIsDirty = (str != per->strText);
00666 }
00667 
00668 
00669 
00670 /********************************************************************************************
00671 >   double SelectorInfoBarOp::ConvertRecord(INT32 i)
00672 
00673     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00674     Created:    16/11/94
00675     Inputs:     i               identifier of an edit-control, 0-7
00676     Outputs:    -
00677     Returns:    The numeric value of the contents of the edit-control.
00678     Purpose:    Reads the text in the given edit-control record and converts it to a INT32.
00679     Errors:     -
00680     SeeAlso:    -
00681 ********************************************************************************************/
00682 
00683 double SelectorInfoBarOp::ConvertRecord(INT32 i)
00684 {
00685     double n;
00686     fConvertedOK = fConvertedOK && Convert::StringToDouble( aerEdits[i].strText, &n );
00687     return n;
00688 }
00689 
00690 
00691 
00692 /********************************************************************************************
00693 >   MILLIPOINT SelectorInfoBarOp::ConvertMillipointRecord(INT32 i)
00694 
00695     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00696     Created:    16/11/94
00697     Inputs:     i           identifier of an edit-control, 0-7
00698     Outputs:    -
00699     Returns:    The contents of the given edit-control as a millipoint value.
00700     Purpose:    Converts an edit-control to a millipoint value, allowing for unit conversions.
00701     Errors:     -
00702     SeeAlso:    -
00703 ********************************************************************************************/
00704 
00705 MILLIPOINT SelectorInfoBarOp::ConvertMillipointRecord(INT32 i)
00706 {
00707     MILLIPOINT n;
00708     DimScale* pDimScale = DimScale::GetPtrDimScale(pSelectorTool->GetSelectionSpread());
00709     ERROR2IF (pDimScale == NULL, 1,
00710                 "Null DimScale* in SelectorInfoBarOp::ConvertMillipointRecord");
00711     fConvertedOK = fConvertedOK && pDimScale->ConvertToMillipoints( aerEdits[i].strText, &n );
00712     return n;
00713 }
00714 
00715 
00716 
00717 /********************************************************************************************
00718 >   FIXED16 SelectorInfoBarOp::ConvertFixedpointRecord(INT32 i)
00719 
00720     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00721     Created:    16/11/94
00722     Inputs:     i           edit-control identifier, 0-7
00723     Outputs:    -
00724     Returns:    Contents of the edit-control as a fixed-point number
00725     Purpose:    Converts the given edit-control to a fixed-point number
00726     Errors:     -
00727     SeeAlso:    -
00728 ********************************************************************************************/
00729 
00730 FIXED16 SelectorInfoBarOp::ConvertFixedpointRecord(INT32 i)
00731 {
00732     BOOL fOk;
00733     double n = Convert::StringToDouble( aerEdits[i].strText, MILLIPOINTS, &fOk );       // NB. not really
00734     fConvertedOK = fConvertedOK && fOk;
00735     return (FIXED16) n;
00736 }
00737 
00738 
00739 
00740 /********************************************************************************************
00741 >   void SelectorInfoBarOp::SetEdit(CGadgetID gid, INT32 nValue, Spread* pUnitSpread,
00742                                     BOOL fUpdate = TRUE)
00743 
00744     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00745     Created:    31/8/94
00746     Inputs:     gid             gadget identifier
00747                 nValue          the value to set in the edit field (INT32 integer)
00748                 pUnitSpread     the spread containing the object (so its units can be
00749                                 extracted).  If this parameter is NULL then no unit
00750                                 conversion is performed.
00751                 fUpdate         update the internal records of the field's contents if
00752                                 TRUE (the default).
00753     Outputs:    -
00754     Returns:    -
00755     Purpose:    Converts the given value to the appropriate units, as contained in the
00756                 spread, converts it to text and writes in into the edit-field.
00757     Errors:     -
00758     SeeAlso:    SelectorInfoBarOp::SetEdit_OnDrag;
00759                 SelectorInfoBarOp::SetEdit_OnSelectionChange
00760 ********************************************************************************************/
00761 
00762 void SelectorInfoBarOp::SetEdit(CGadgetID gid, INT32 nValue, Spread* pUnitSpread, BOOL fUpdate)
00763 {
00764     if (pUnitSpread != NULL)
00765     {
00766         // Get the dimension scaling object (units) associated with the given spread
00767         // and convert to its units.
00768         DimScale* pDimScale = DimScale::GetPtrDimScale((Node*) pUnitSpread);
00769         ENSURE(pDimScale != NULL, "Null DimScale* in SelectorInfoBarOp::SetEdit");
00770     
00771         // Convert to units & text and display.
00772         String_256 str;
00773         pDimScale->ConvertToUnits((INT32) nValue, &str);
00774         if (HasWindow()) SetStringGadgetValue(gid, str);
00775     }
00776     else
00777     {
00778         // No unit conversion necessary, just convert to text.
00779         if (HasWindow()) SetLongGadgetValue(gid, nValue);
00780     }     
00781 
00782     // Grab the text for our records, if required.
00783     if (fUpdate) UpdateRecord((UINT32) gid);
00784 }
00785 
00786 
00787 
00788 /********************************************************************************************
00789 >   void SelectorInfoBarOp::SetDoubleEdit(CGadgetID gid, double nValue, BOOL fUpdate = TRUE)
00790 
00791     Author:     Phil_Martin (Xara Group Ltd) <camelotdev@xara.com>
00792     Created:    23/2/95
00793     Inputs:     gid             gadget identifier
00794                 nValue          the value to set in the edit field (INT32 integer)
00795                 fUpdate         update the internal records of the field's contents if
00796                                 TRUE (the default).
00797     Outputs:    -
00798     Returns:    -
00799     Purpose:    Converts the given double value to text and writes in into the edit-field.
00800     Errors:     -
00801     SeeAlso:    SelectorInfoBarOp::SetEdit;
00802                 SelectorInfoBarOp::SetEdit_OnDrag;
00803                 SelectorInfoBarOp::SetEdit_OnSelectionChange
00804 ********************************************************************************************/
00805 
00806 void SelectorInfoBarOp::SetDoubleEdit(CGadgetID gid, double nValue, BOOL fUpdate)
00807 {
00808     // No unit conversion necessary, just convert to text.
00809     if (HasWindow()) SetDoubleGadgetValue(gid, nValue);
00810 
00811     // Grab the text for our records, if required.
00812     if (fUpdate) UpdateRecord((UINT32) gid);
00813 }
00814 
00815 
00816 
00817 /********************************************************************************************
00818 >   void SelectorInfoBarOp::SetEdit(CGadgetID gid, FIXED16 fxValue, Spread* pUnitSpread,
00819                                     BOOL fUpdate = TRUE)
00820 
00821     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00822     Created:    5/9/94
00823     Inputs:     gid             the edit-field gadget (control) identifier that is to be set
00824                 fxValue         the fixed-point value to set in the field
00825                 pUnitSpread     the spread that is used for unit conversions.  If null then
00826                                 no unit conversion will occur (CURRENTLY NOT SUPPORTED).
00827     Outputs:    -
00828     Returns:    -
00829     Purpose:    Sets an edit-field in the selector info-bar to the given fixed-point
00830                 value.  If a spread is passed then the value will be converted to the
00831                 appropriate units for the spread.  Currently ANGLEs are always in degrees
00832                 so this is not yet implemented.
00833     Errors:     -
00834     SeeAlso:    -
00835 ********************************************************************************************/
00836 
00837 void SelectorInfoBarOp::SetEdit(CGadgetID gid, FIXED16 fxValue, Spread* pUnitSpread,
00838                                 BOOL fUpdate)
00839 {
00840 /*  if (pUnitSpread != NULL && IsUserName("JustinF"))
00841     {
00842         TRACE( _T("Warning - non-null pUnitSpread in SelectorInfoBarOp::SetEdit\n"));
00843     }
00844 */
00845     String str;
00846     fxValue.ToString(&str);
00847     if (HasWindow()) SetStringGadgetValue(gid, str, FALSE);
00848     if (fUpdate) UpdateRecord((UINT32) gid);
00849 }
00850 
00851 
00852 
00853 /********************************************************************************************
00854 >   void SelectorInfoBarOp::ClearEdit(CGadgetID gid)
00855 
00856     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00857     Created:    5/9/94
00858     Inputs:     gid         the gadget ID of the edit-field to clear
00859     Outputs:    -
00860     Returns:    -
00861     Purpose:    Blanks the given edit-field.
00862     Errors:     -
00863     SeeAlso:    -
00864 ********************************************************************************************/
00865 
00866 void SelectorInfoBarOp::ClearEdit(CGadgetID gid)
00867 {
00868     String_256 str;
00869     str.Empty();
00870     if(HasWindow())
00871         SetStringGadgetValue(gid, str, FALSE);
00872     UpdateRecord((UINT32) gid);
00873 }
00874 
00875 
00876 
00877 /********************************************************************************************
00878 >   void SelectorInfoBarOp::EnableAllEdits(BOOL fEnabled)
00879 
00880     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00881     Created:    31/8/94
00882     Inputs:     fEnabled        TRUE if the gadgets should be enabled, FALSE if they
00883                                 should be disabled.
00884     Outputs:    -
00885     Returns:    -
00886     Purpose:    Enables or disables the edit-fields in the info-bar,
00887                 clearing them to blank if they are being disabled.
00888     Errors:     -
00889     SeeAlso:    -
00890 ********************************************************************************************/
00891 
00892 void SelectorInfoBarOp::EnableAllEdits(BOOL fEnabled)
00893 {
00894     if (!HasWindow())
00895     {
00896         TRACEUSER( "JustinF", _T("Tried to enable edit controls but they don't exist?!?\n"));
00897         return;
00898     }
00899 
00900     // Clear the edit fields if being disabled.
00901     if (!fEnabled)
00902     {
00903         ClearEdit(_R(IDC_SEL_EDIT_X));
00904         ClearEdit(_R(IDC_SEL_EDIT_Y));
00905         ClearEdit(_R(IDC_SEL_EDIT_W));
00906         ClearEdit(_R(IDC_SEL_EDIT_H));
00907         ClearEdit(_R(IDC_SEL_EDIT_XSCALE));
00908         ClearEdit(_R(IDC_SEL_EDIT_YSCALE));
00909         ClearEdit(_R(IDC_SEL_EDIT_ANGLE));
00910         ClearEdit(_R(IDC_SEL_EDIT_SHEAR));
00911     }
00912     
00913     // Enable/disable the controls.
00914     EnableGadget(_R(IDC_SEL_EDIT_X),      fEnabled);
00915     EnableGadget(_R(IDC_SEL_EDIT_Y),      fEnabled);
00916     EnableGadget(_R(IDC_SEL_EDIT_W),      fEnabled);
00917     EnableGadget(_R(IDC_SEL_EDIT_H),      fEnabled);
00918     EnableGadget(_R(IDC_SEL_EDIT_XSCALE), fEnabled);
00919     EnableGadget(_R(IDC_SEL_EDIT_YSCALE), fEnabled);
00920     EnableGadget(_R(IDC_SEL_EDIT_ANGLE),  fEnabled);
00921     EnableGadget(_R(IDC_SEL_EDIT_SHEAR),  fEnabled);
00922 }
00923 
00924 /********************************************************************************************
00925 >   void SelectorInfoBarOp::EnableGrid(BOOL fEnabled)
00926 
00927     Author:     Alex Bligh <alex@alex.org.uk>
00928     Created:    03-Feb-2005
00929     Inputs:     fEnabled        TRUE if the gadgets should be enabled, FALSE if they
00930                                 should be disabled.
00931     Outputs:    -
00932     Returns:    -
00933     Purpose:    Enables or disables the rotate grid control
00934     Errors:     -
00935     SeeAlso:    -
00936 ********************************************************************************************/
00937 
00938 void SelectorInfoBarOp::EnableGrid(BOOL fEnabled)
00939 {
00940     EnableGadget(_R(IDC_SEL_GRID_NW), fEnabled);
00941     EnableGadget(_R(IDC_SEL_GRID_N) , fEnabled);
00942     EnableGadget(_R(IDC_SEL_GRID_NE), fEnabled);
00943     EnableGadget(_R(IDC_SEL_GRID_W) , fEnabled);
00944     EnableGadget(_R(IDC_SEL_GRID_CENTRE), fEnabled);
00945     EnableGadget(_R(IDC_SEL_GRID_E) , fEnabled);
00946     EnableGadget(_R(IDC_SEL_GRID_SW), fEnabled);
00947     EnableGadget(_R(IDC_SEL_GRID_S) , fEnabled);
00948     EnableGadget(_R(IDC_SEL_GRID_SE), fEnabled);
00949 }
00950 
00951 /********************************************************************************************
00952 >   void SelectorInfoBarOp::PaintAllEditsNow()
00953 
00954     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00955     Created:    5/9/94
00956     Inputs:     -
00957     Outputs:    -
00958     Returns:    -
00959     Purpose:    Forces an immediate repaint of any edit field that has had its contents
00960                 changed.
00961     Errors:     -
00962     SeeAlso:    -
00963 ********************************************************************************************/
00964 
00965 void SelectorInfoBarOp::PaintAllEditsNow()
00966 {
00967     if (!HasWindow()) return;
00968     PaintGadgetNow(_R(IDC_SEL_EDIT_X));
00969     PaintGadgetNow(_R(IDC_SEL_EDIT_Y));
00970     PaintGadgetNow(_R(IDC_SEL_EDIT_W));
00971     PaintGadgetNow(_R(IDC_SEL_EDIT_H));
00972     PaintGadgetNow(_R(IDC_SEL_EDIT_XSCALE));
00973     PaintGadgetNow(_R(IDC_SEL_EDIT_YSCALE));
00974     PaintGadgetNow(_R(IDC_SEL_EDIT_ANGLE));
00975     PaintGadgetNow(_R(IDC_SEL_EDIT_SHEAR));
00976 }
00977 
00978 
00979 
00980 /********************************************************************************************
00981 >   void SelectorInfoBarOp::SetEdit_OnSelectionChange()
00982 
00983     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00984     Created:    31/8/94
00985     Inputs:     -
00986     Outputs:    -
00987     Returns:    -
00988     Purpose:    Updates the X, Y, W, H edit fields of the info-bar with the position and
00989                 extent of the currently selected object(s), if any.  If there is no
00990                 selection then it clears and disables the edit-fields until there is.
00991                 Called by the selector tool when it is notified that the selection has
00992                 changed.
00993 
00994                 Now also greys/ungreys info-bar buttons, as appropriate.
00995     Errors:     -
00996     SeeAlso:    -
00997 ********************************************************************************************/
00998 
00999 void SelectorInfoBarOp::SetEdit_OnSelectionChange()
01000 {
01001     if (!HasWindow())
01002     {
01003 //      TRACEUSER( "JustinF", _T("Tried to set edits on selection change but they don't exist?!?\n"));
01004         return;
01005     }
01006 
01007     Spread* pSpread = pSelectorTool->GetSelectionSpread();
01008     if (pSpread != NULL)
01009     {
01010         // Get extent of new selection in user coords, and Update all the numeric gadgets.
01011         DocRect  DRSelExtent = pSelectorTool->GetSelectionBounds(DontConsiderAttrs());
01012         UserRect   SelExtent = DRSelExtent.ToUser(pSpread);
01013         SetEdit(_R(IDC_SEL_EDIT_X), SelExtent.lo.x, pSpread);
01014         SetEdit(_R(IDC_SEL_EDIT_Y), SelExtent.lo.y, pSpread);
01015         SetEdit(_R(IDC_SEL_EDIT_W), SelExtent.Width(), pSpread);
01016         SetEdit(_R(IDC_SEL_EDIT_H), SelExtent.Height(), pSpread);
01017         SetEdit(_R(IDC_SEL_EDIT_XSCALE), (FIXED16) 100, NULL);
01018         SetEdit(_R(IDC_SEL_EDIT_YSCALE), (FIXED16) 100, NULL);
01019         SetEdit(_R(IDC_SEL_EDIT_ANGLE), (FIXED16) 0, NULL);
01020         SetEdit(_R(IDC_SEL_EDIT_SHEAR), (FIXED16) 0, NULL);
01021 
01022         // Ungrey the buttons that are now available.
01023         EnableGadget(_R(IDC_SEL_BUMP_X_LESS), TRUE);
01024         EnableGadget(_R(IDC_SEL_BUMP_X_MORE), TRUE);
01025         EnableGadget(_R(IDC_SEL_BUMP_Y_LESS), TRUE);
01026         EnableGadget(_R(IDC_SEL_BUMP_Y_MORE), TRUE);
01027         EnableGadget(_R(IDC_SEL_BUMP_W_LESS), TRUE);
01028         EnableGadget(_R(IDC_SEL_BUMP_W_MORE), TRUE);
01029         EnableGadget(_R(IDC_SEL_BUMP_H_LESS), TRUE);
01030         EnableGadget(_R(IDC_SEL_BUMP_H_MORE), TRUE);
01031         EnableGadget(_R(IDC_SEL_BUMP_ANGLE_LESS), TRUE);
01032         EnableGadget(_R(IDC_SEL_BUMP_ANGLE_MORE), TRUE);
01033         EnableGadget(_R(IDC_SEL_BUMP_SHEAR_LESS), TRUE);
01034         EnableGadget(_R(IDC_SEL_BUMP_SHEAR_MORE), TRUE);
01035         EnableGadget(_R(IDC_SEL_FLIPHORZ), TRUE);
01036         EnableGadget(_R(IDC_SEL_FLIPVERT), TRUE);
01037 //      EnableGadget(_R(IDC_SEL_ROTATE_GRID), TRUE);
01038         EnableGrid(TRUE);
01039 
01040         // Reenable the edit-controls.
01041         EnableAllEdits(TRUE);
01042     }
01043     else
01044     {
01045         // Disable all the edit-controls and blank them.
01046         EnableAllEdits(FALSE);
01047 
01048         // Grey the buttons that are now unavailable.
01049         EnableGadget(_R(IDC_SEL_BUMP_X_LESS), FALSE);
01050         EnableGadget(_R(IDC_SEL_BUMP_X_MORE), FALSE);
01051         EnableGadget(_R(IDC_SEL_BUMP_Y_LESS), FALSE);
01052         EnableGadget(_R(IDC_SEL_BUMP_Y_MORE), FALSE);
01053         EnableGadget(_R(IDC_SEL_BUMP_W_LESS), FALSE);
01054         EnableGadget(_R(IDC_SEL_BUMP_W_MORE), FALSE);
01055         EnableGadget(_R(IDC_SEL_BUMP_H_LESS), FALSE);
01056         EnableGadget(_R(IDC_SEL_BUMP_H_MORE), FALSE);
01057         EnableGadget(_R(IDC_SEL_BUMP_ANGLE_LESS), FALSE);
01058         EnableGadget(_R(IDC_SEL_BUMP_ANGLE_MORE), FALSE);
01059         EnableGadget(_R(IDC_SEL_BUMP_SHEAR_LESS), FALSE);
01060         EnableGadget(_R(IDC_SEL_BUMP_SHEAR_MORE), FALSE);
01061         EnableGadget(_R(IDC_SEL_FLIPHORZ), FALSE);
01062         EnableGadget(_R(IDC_SEL_FLIPVERT), FALSE);
01063 //      EnableGadget(_R(IDC_SEL_ROTATE_GRID), FALSE);
01064         EnableGrid(FALSE);
01065     }
01066 }
01067 
01068 
01069 
01070 /********************************************************************************************
01071 >   void SelectorInfoBarOp::SetEdit_OnDrag(TransformBoundingData* pData, Spread* pSpread)
01072 
01073     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01074     Created:    31/8/94
01075     Inputs:     pData       pointer to the "callback" data generated by mouse-drags,
01076                             containing a description of the dragged object's extent etc.
01077     Outputs:    -
01078     Returns:    -
01079     Purpose:    Dynamically updates the text in the edit-fields as an object is being
01080                 dragged.  Works out what needs doing from the pData argument.
01081     Errors:     -
01082     SeeAlso:    SelectorTool::DragMove
01083 ********************************************************************************************/
01084 
01085 void SelectorInfoBarOp::SetEdit_OnDrag(TransformBoundingData* pData, Spread* pSpread)
01086 {
01087     // Make sure the info-bar hasn't been hidden.
01088     if (!HasWindow()) return;
01089     
01090     if (pData->XYChanged)
01091     {
01092         // Convert the spread coords to user coords, and update gadgets
01093         UserCoord UserPos = DocCoord(pData->x, pData->y).ToUser(pSpread);
01094         SetEdit(_R(IDC_SEL_EDIT_X), UserPos.x, pSpread);
01095         SetEdit(_R(IDC_SEL_EDIT_Y), UserPos.y, pSpread);
01096         PaintGadgetNow(_R(IDC_SEL_EDIT_X));
01097         PaintGadgetNow(_R(IDC_SEL_EDIT_Y));
01098         pData->XYChanged = FALSE;
01099     }
01100 
01101     if (pData->WHChanged)
01102     {
01103         SetEdit(_R(IDC_SEL_EDIT_W), pData->Width, pSpread);
01104         SetEdit(_R(IDC_SEL_EDIT_H), pData->Height, pSpread);
01105         PaintGadgetNow(_R(IDC_SEL_EDIT_W));
01106         PaintGadgetNow(_R(IDC_SEL_EDIT_H));
01107         pData->WHChanged = FALSE;
01108     }
01109 
01110     if (pData->ScaleChanged)
01111     {
01112         // Take the absolute value and round to the nearest percent.
01113         FIXED16 xfx = (pData->XScale < 0) ? -pData->XScale : pData->XScale;
01114         FIXED16 yfx = (pData->YScale < 0) ? -pData->YScale : pData->YScale;
01115         INT32 xs = (xfx * 100 + FIXED16(0.5)).MakeLong();
01116         INT32 ys = (yfx * 100 + FIXED16(0.5)).MakeLong();
01117         SetEdit(_R(IDC_SEL_EDIT_XSCALE), xs, NULL);
01118         SetEdit(_R(IDC_SEL_EDIT_YSCALE), ys, NULL);
01119         PaintGadgetNow(_R(IDC_SEL_EDIT_XSCALE));
01120         PaintGadgetNow(_R(IDC_SEL_EDIT_YSCALE));
01121         pData->ScaleChanged = FALSE;
01122     }
01123 
01124     if (pData->RotateChanged)
01125     {
01126         SetEdit(_R(IDC_SEL_EDIT_ANGLE), pData->Rotation, pSpread);
01127         PaintGadgetNow(_R(IDC_SEL_EDIT_ANGLE));
01128         pData->RotateChanged = FALSE;
01129     }
01130 
01131     if (pData->ShearChanged)
01132     {
01133         double ShearAngle = pData->Shear.MakeDouble();
01134 
01135         // First we muct ensure that the displayed angle is in the -90..+90 range -
01136         // The angles coming in will either be centered around 0 or 180 degrees.
01137         // We therefore move them all to the 0 origin, so that they are displayed correctly
01138         if (ShearAngle >= 90.0)
01139             ShearAngle = -180.0 + ShearAngle;
01140 
01141         if (ShearAngle <= -90.0)
01142             ShearAngle = 180.0 + ShearAngle;
01143 
01144         // And ensure they lie in a sensible range
01145         if (ShearAngle < -89.0)
01146             ShearAngle = -89.0;
01147 
01148         if (ShearAngle > 89.0)
01149             ShearAngle = 89.0;
01150 
01151         SetEdit(_R(IDC_SEL_EDIT_SHEAR), (ANGLE) ShearAngle, pSpread);
01152         PaintGadgetNow(_R(IDC_SEL_EDIT_SHEAR));
01153         pData->ShearChanged = FALSE;
01154     }
01155 
01156     if (pData->ScaleLinesChanged)
01157     {
01158         SetScaleLines(pData->ScaleLines);
01159         PaintGadgetNow(_R(IDC_SEL_SCALELINES));
01160         pData->ScaleLinesChanged = FALSE;
01161     }
01162 
01163     // Make sure all changes are immediately visible.
01164 //  PaintAllEditsNow();
01165 }
01166 
01167 
01168 
01169 /********************************************************************************************
01170 >   void SelectorInfoBarOp::HandleCreate(DialogMsg* pDlgMsg)
01171 
01172     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01173     Created:    13/7/94
01174     Inputs:     A pointer to the DIM_CREATE dialog message to handle (not used)
01175     Purpose:    Sets the initial state of the controls in the info-bar.
01176     SeeAlso:    SelectorInfoBarOp::Message
01177 ********************************************************************************************/
01178 
01179 void SelectorInfoBarOp::HandleCreate(DialogMsg* /* pDlgMsg */)
01180 {
01181 //  TRACEUSER( "JustinF", _T("In SelectorInfoBarOp::HandleCreate\n"));
01182 
01183     // Get an empty list of the blob types.
01184     ENSURE(pSelectorTool != NULL, "No selector tool in SelectorInfoBarOp::HandleCreate");
01185     BlobStyle SelectorBlobs = pSelectorTool->GetBlobStyle();
01186     if (HasWindow())
01187     {
01188         // Set all the blob buttons in the info bar according to the information.
01189         SetLongGadgetValue(_R(IDC_SEL_SHOWBOUNDSBLOBS),  pSelectorTool->fShowToolBlobs, FALSE);
01190         SetLongGadgetValue(_R(IDC_SEL_SHOWOBJECTBLOBS),  SelectorBlobs.Object,          FALSE);
01191         SetLongGadgetValue(_R(IDC_SEL_SHOWFILLBLOBS),    SelectorBlobs.Fill,            FALSE);
01192 //      SetLongGadgetValue(_R(IDC_SEL_SHOWARTLINEBLOBS), SelectorBlobs.Artistic,        FALSE);
01193 
01194         // Set all the option buttons.
01195         SetLongGadgetValue(_R(IDC_SEL_ROTATEBUTTON),     fRotateMode,                   FALSE);
01196         SetLongGadgetValue(_R(IDC_SEL_SCALELINES),       fScaleLines,                   FALSE);
01197         SetLongGadgetValue(_R(IDC_SEL_PADLOCK),          fLockAspect,                   FALSE);
01198 //      SetLongGadgetValue(_R(IDC_SEL_LEAVECOPY),        fLeaveCopy,                    FALSE);
01199 //      SetLongGadgetValue(_R(IDC_SEL_TRANSFILL),        fTransFills,                   FALSE);
01200     }
01201     
01202     // Initialise the edit-field records.
01203     aerEdits[0].nControlID = _R(IDC_SEL_EDIT_X);
01204     aerEdits[1].nControlID = _R(IDC_SEL_EDIT_Y);
01205     aerEdits[2].nControlID = _R(IDC_SEL_EDIT_W);
01206     aerEdits[3].nControlID = _R(IDC_SEL_EDIT_H);
01207     aerEdits[4].nControlID = _R(IDC_SEL_EDIT_XSCALE);
01208     aerEdits[5].nControlID = _R(IDC_SEL_EDIT_YSCALE);
01209     aerEdits[6].nControlID = _R(IDC_SEL_EDIT_ANGLE);
01210     aerEdits[7].nControlID = _R(IDC_SEL_EDIT_SHEAR);
01211 
01212     // Now set the edit controls.
01213     SetEdit_OnSelectionChange();
01214 
01215     // Make sure their current values are recorded.
01216     UpdateAllRecords();
01217 }    
01218 
01219 
01220 
01221 /********************************************************************************************
01222 >   BOOL SelectorInfoBarOp::HandleButtonDown(DialogMsg* pDlgMsg)
01223 
01224     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> / Rik
01225     Created:    12/7/94
01226     Inputs:     A pointer to a "dialogue box" message about a button click.
01227     Returns:    TRUE if message handled and should be passd to the InformationBarOp,
01228                 FALSE if not handled and should be passed toDialogBarOp (which doesn't
01229                 eat messages and can properly invoked operations).
01230     Purpose:    For the given button calls the appropriate functions that update the
01231                 blob manager.
01232     SeeAlso:    SelectorInfoBarOp::Message; SelectorInfoBarOp::UpdateBlobManager
01233 ********************************************************************************************/
01234 
01235 BOOL SelectorInfoBarOp::HandleButtonDown(DialogMsg* pDlgMsg)
01236 {
01237     // Get ourselves an empty blob style (ie all entries set to FALSE)
01238     BlobStyle ChangingBlob;
01239 
01240     // Have a look at which button was pressed and deal with it
01241     // switch (pDlgMsg->GadgetID)
01242     
01243     // "Show Bounds Blobs"
01244     if (pDlgMsg->GadgetID == _R(IDC_SEL_SHOWBOUNDSBLOBS))
01245     {
01246         pSelectorTool->BoundsButtonChange();
01247     }
01248     // "Show Objects".
01249     else if (pDlgMsg->GadgetID == _R(IDC_SEL_SHOWOBJECTBLOBS))
01250     {   // We want to toggle the state of the Object blobs
01251         ChangingBlob.Object = TRUE;
01252     }
01253     // "Show Fills".
01254     else if (pDlgMsg->GadgetID == _R(IDC_SEL_SHOWFILLBLOBS))
01255     {   // We want to toggle the state of the Object blobs
01256         ChangingBlob.Fill = TRUE;
01257     }
01258     else if (pDlgMsg->GadgetID == _R(IDC_SEL_PADLOCK))
01259     {   // Toggle the state of the padlock button.
01260         fLockAspect = !fLockAspect;
01261     }
01262     // "Rotate mode".  Will immediately notify the tool, so it can display new blobs.
01263     else if (pDlgMsg->GadgetID == _R(IDC_SEL_ROTATEBUTTON))
01264     {
01265         pSelectorTool->RotateButtonChange(fRotateMode = !fRotateMode);
01266     }
01267     // "Scale lines when scaling an object".
01268     else if (pDlgMsg->GadgetID == _R(IDC_SEL_SCALELINES))
01269     {
01270         fScaleLines = !fScaleLines;
01271 
01272         // Because the "consider attributes" state (which affects the displayed width/height
01273         // of the selection) can be slaved off this button, we must also ensure that the
01274         // selector tool has cached and is displaying correct info.
01275         if (pSelectorTool)
01276             pSelectorTool->SelectionHasChanged();
01277     }
01278     // "Flip horizontally".
01279     else if (pDlgMsg->GadgetID == _R(IDC_SEL_FLIPHORZ))
01280     {
01281         pSelectorTool->FlipButtonChange(FALSE);
01282     }
01283     // "Flip vertically".
01284     else if (pDlgMsg->GadgetID == _R(IDC_SEL_FLIPVERT))
01285     {
01286         pSelectorTool->FlipButtonChange(TRUE);
01287     }
01288     // "Decrease X a bit".
01289     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_X_LESS))
01290     {
01291         HandleBumpClickLinear(_R(IDC_SEL_EDIT_X), -1);
01292     }
01293     // "Increase X a bit".
01294     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_X_MORE))
01295     {
01296         HandleBumpClickLinear(_R(IDC_SEL_EDIT_X), 1);
01297     }
01298     // "Decrease Y a bit".
01299     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_Y_LESS))
01300     {
01301         HandleBumpClickLinear(_R(IDC_SEL_EDIT_Y), -1);
01302     }
01303     // "Increase Y a bit".
01304     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_Y_MORE))
01305     {
01306         HandleBumpClickLinear(_R(IDC_SEL_EDIT_Y), 1);
01307     }
01308     // "Decrease W a bit".
01309     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_W_LESS))
01310     {
01311         HandleBumpClickLinear(_R(IDC_SEL_EDIT_W), -1);
01312     }
01313     // "Increase W a bit".
01314     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_W_MORE))
01315     {
01316         HandleBumpClickLinear(_R(IDC_SEL_EDIT_W), 1);
01317     }
01318     // "Decrease H a bit".
01319     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_H_LESS))
01320     {
01321         HandleBumpClickLinear(_R(IDC_SEL_EDIT_H), -1);
01322     }
01323     // "Increase H a bit".
01324     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_H_MORE))
01325     {
01326         HandleBumpClickLinear(_R(IDC_SEL_EDIT_H), 1);
01327     }
01328     // "Decrease angle a bit".
01329     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_ANGLE_LESS))
01330     {
01331         HandleBumpClickAngle(_R(IDC_SEL_EDIT_ANGLE), -1, -360.0, +360.0);
01332     }
01333     // "Increase angle a bit".
01334     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_ANGLE_MORE))
01335     {
01336         HandleBumpClickAngle(_R(IDC_SEL_EDIT_ANGLE), 1, -360.0, +360.0);
01337     }
01338     // "Decrease shear-angle a bit".
01339     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_SHEAR_LESS))
01340     {
01341         HandleBumpClickAngle(_R(IDC_SEL_EDIT_SHEAR), -1, -89.0, +89.0);
01342     }
01343     // "Increase shear-angle a bit".
01344     else if (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_SHEAR_MORE))
01345     {       
01346         HandleBumpClickAngle(_R(IDC_SEL_EDIT_SHEAR), 1, -89.0, +89.0);
01347     }
01348     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_NW))
01349     {       
01350         pSelectorTool->SetRotateCentre(1);
01351     }
01352     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_N))
01353     {       
01354         pSelectorTool->SetRotateCentre(2);
01355     }
01356     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_NE))
01357     {       
01358         pSelectorTool->SetRotateCentre(3);
01359     }
01360     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_W))
01361     {       
01362         pSelectorTool->SetRotateCentre(4);
01363     }
01364     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_CENTRE))
01365     {       
01366         pSelectorTool->SetRotateCentre(0);
01367     }
01368     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_E))
01369     {       
01370         pSelectorTool->SetRotateCentre(5);
01371     }
01372     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_SW))
01373     {       
01374         pSelectorTool->SetRotateCentre(6);
01375     }
01376     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_S))
01377     {       
01378         pSelectorTool->SetRotateCentre(7);
01379     }
01380     else if (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_SE))
01381     {       
01382         pSelectorTool->SetRotateCentre(8);
01383     }
01384     // Other gadgets, pass to _DialogBarOp_ base class which can properly invoke
01385     // ops attached to gadgets, unlike InformationBarOp which just eats everything.
01386     else
01387     {
01388     //  TRACEUSER( "JustinF", _T("SelectorInfoBarOp::HandleButtonDown: passing to DialogBarOp\n"));
01389         return FALSE;
01390     }
01391 
01392     // Ask the tool to deal with the blob manager as well as its tool blobs if needed.
01393     if (pSelectorTool != NULL) pSelectorTool->SelectionBlobChange(ChangingBlob);
01394     return TRUE;    // handled
01395 
01396 }
01397 
01398 
01399 
01400 /********************************************************************************************
01401 >   void SelectorInfoBarOp::HandleButtonUp(DialogMsg* pDlgMsg)
01402 
01403     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01404     Created:    1/12/94
01405     Inputs:     pDlgMsg             pointer to a dialogue message from a button.
01406     Outputs:    -
01407     Returns:    -
01408     Purpose:    For "nudge-buttons", responds to them being released by calling the
01409                 HandleEditCommit function, ie. acting as if the user hit the ENTER key
01410                 within an edit-field meaning that the program should act on any changes
01411                 made.  For all other buttons, does nothing.
01412     Errors:     -
01413     SeeAlso:    -
01414 ********************************************************************************************/
01415 
01416 void SelectorInfoBarOp::HandleButtonUp(DialogMsg* pDlgMsg)
01417 {
01418     if (
01419         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_X_LESS)) ||
01420         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_X_MORE)) ||
01421         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_Y_LESS)) ||
01422         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_Y_MORE)) ||
01423         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_W_LESS)) ||
01424         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_W_MORE)) ||
01425         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_H_LESS)) ||
01426         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_H_MORE)) ||
01427         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_ANGLE_LESS)) ||
01428         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_ANGLE_MORE)) ||
01429         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_SHEAR_LESS)) ||
01430         (pDlgMsg->GadgetID == _R(IDC_SEL_BUMP_SHEAR_MORE))
01431         )
01432     {
01433         HandleEditCommit(NULL);
01434     }
01435     else if (
01436         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_NW)) ||
01437         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_N) ) ||
01438         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_NE)) ||
01439         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_W) ) ||
01440         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_CENTRE)) ||
01441         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_E)) ||
01442         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_SW)) ||
01443         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_S) ) ||
01444         (pDlgMsg->GadgetID == _R(IDC_SEL_GRID_SE))
01445         )
01446     {
01447         CGadgetID clicked = pDlgMsg->GadgetID;
01448         clicked = (CGadgetID)0; // Right now remove ALL selected ones to remove toggle functionality. 
01449         if (clicked != _R(IDC_SEL_GRID_NW) ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_NW), FALSE);
01450         if (clicked != _R(IDC_SEL_GRID_N)  ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_N),  FALSE);
01451         if (clicked != _R(IDC_SEL_GRID_NE) ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_NE), FALSE);
01452         if (clicked != _R(IDC_SEL_GRID_W)  ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_W),  FALSE);
01453         if (clicked != _R(IDC_SEL_GRID_CENTRE) ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_CENTRE), FALSE);
01454         if (clicked != _R(IDC_SEL_GRID_E)  ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_E) , FALSE);
01455         if (clicked != _R(IDC_SEL_GRID_SW) ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_SW), FALSE);
01456         if (clicked != _R(IDC_SEL_GRID_S)  ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_S) , FALSE);
01457         if (clicked != _R(IDC_SEL_GRID_SE) ) SetBoolGadgetSelected(_R(IDC_SEL_GRID_SE), FALSE);
01458     }
01459 
01460     return;
01461 }
01462 
01463 
01464 
01465 
01466 /********************************************************************************************
01467 >   void SelectorInfoBarOp::HandleBumpClickLinear(UINT32 nEditControlID, INT32 nSign)
01468 
01469     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01470     Created:    3/11/94
01471     Inputs:     nEditControlID  ---     the identifier of the (EDIT) control associated
01472                                         with the clicked bump button
01473                 nSign           ---     either -1 or 1, depending on which of the bumps
01474                                         was clicked (eg. less, more)
01475     Outputs:    -
01476     Returns:    -
01477     Purpose:    Responds to a click on a bump button ("nudge") for a "linear" control, ie.
01478                 an X, Y, width or height field, not an angle. The value will be nudged in
01479                 the direction indicated by nSign, by the (user preference) nudge distance.
01480     Errors:     -
01481     SeeAlso:    SelectorInfoBarOp::HandleBumpClickAngle
01482 ********************************************************************************************/
01483 
01484 void SelectorInfoBarOp::HandleBumpClickLinear(UINT32 nEditControlID, INT32 nSign)
01485 {
01486     // If there's no selection then ignore the clicks.
01487     Spread* pUnitSpread = pSelectorTool->GetSelectionSpread();
01488     if (pUnitSpread == NULL) return;
01489 
01490     // Get the dimension units object for the spread containing the selection.
01491     DimScale* pDimScale = DimScale::GetPtrDimScale((Node*) pUnitSpread);
01492     ERROR3IF(pDimScale == NULL, "Null DimScale* in SelectorInfoBarOp::HandleBumpClick");
01493 
01494     // Read the edit field and convert to millipoints.
01495     BOOL fOk;
01496     INT32 nMilli;
01497     String_256 str = GetStringGadgetValue(nEditControlID, &fOk);
01498     if (!fOk || !pDimScale->ConvertToMillipoints( str, &nMilli ))
01499     {
01500         TRACEUSER( "JustinF", _T("Couldn't convert edit control\n") );
01501         return;
01502     }
01503 
01504     // Write the new value to the edit-field.
01505     SetEdit(nEditControlID, nMilli + (nSign * OpNudge::GetNudgeStep()), pUnitSpread, FALSE);
01506 
01507     // Set the input focus to the associated edit-field.  NB. we don't do this anymore
01508     // because Charles doesn't like it.
01509 //  SetKeyboardFocus(nEditControlID);
01510 //  HighlightText(nEditControlID);
01511 }
01512 
01513 
01514 
01515 /********************************************************************************************
01516 >   void SelectorInfoBarOp::HandleBumpClickAngle(UINT32 nEditControlID, INT32 nSign,
01517                                                     double Min, double Max)
01518 
01519     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01520     Created:    16/11/94
01521     Inputs:     nEditControlID      identifier of the edit-control
01522                 nSign               whether to increase (+1) or decrease (-1) the field
01523                 Min                 The minimum allowed value in this field (inclusive)
01524                 Max                 The maximum allowed angle in this field (inclusive)
01525     Outputs:    -
01526     Returns:    -
01527     Purpose:    Responds to a click on a bump button for angles, ie unitless numeric data.
01528 
01529     Notes:      The value in the icon is incremented by the value in nSign. If this value
01530                 is less than the minimum or greater than the maximum, the value will be
01531                 clipped to the appropriate limit.
01532 
01533     Errors:     -
01534     SeeAlso:    -
01535 ********************************************************************************************/
01536 
01537 void SelectorInfoBarOp::HandleBumpClickAngle(UINT32 nEditControlID, INT32 nSign, double Min, double Max)
01538 {
01539     // If there's nothing selected then ignore the clicks.
01540     if (pSelectorTool->GetSelectionSpread() == NULL) return;
01541 
01542     // Try to read the edit-field.
01543     BOOL fOk;
01544     String_256 str = GetStringGadgetValue(nEditControlID, &fOk);
01545     if (!fOk)
01546     {
01547         TRACEUSER( "JustinF", _T("Couldn't read edit control\n") );
01548         return;
01549     }
01550 
01551     // Convert from text to a number.
01552     double nAngle = Convert::StringToDouble( str, MILLIPOINTS, &fOk);
01553     if (!fOk)
01554     {
01555         TRACEUSER( "JustinF", _T("Couldn't convert edit control\n") );
01556         return;
01557     }
01558 
01559     // Increment as required
01560     nAngle += nSign;
01561 
01562     // And clip to allowable range
01563     if (nAngle < Min)
01564         nAngle = Min;
01565 
01566     if (nAngle > Max)
01567         nAngle = Max;
01568 
01569     // Adjust it by nSign and write the new value to the edit-field.
01570     SetEdit(nEditControlID, (ANGLE) nAngle, NULL, FALSE);
01571 
01572     // Set the input focus to the associated edit-field.  NB. we don't do this anymore
01573     // because Charles doesn't like it.
01574 //  SetKeyboardFocus(nEditControlID);
01575 //  HighlightText(nEditControlID);
01576 }
01577 
01578 
01579 
01580 /********************************************************************************************
01581 >   void SelectorInfoBarOp::HandleEditCommit(DialogMsg* pDlgMsg)
01582 
01583     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01584     Created:    31/8/94
01585     Inputs:     pDlgMsg         the "commit" dialogue message sent when the user hits ENTER
01586                                 within an edit-field.
01587     Outputs:    -
01588     Returns:    -
01589     Purpose:    Reads the text from the edit-fields, converts it to millipoints, informs the
01590                 selector tool that the user has changed the selection's position and/or
01591                 extent.
01592     Errors:     -
01593     SeeAlso:    -
01594 ********************************************************************************************/
01595 
01596 void SelectorInfoBarOp::HandleEditCommit(DialogMsg* pDlgMsg)
01597 {
01598     // If there's nothing selected then ignore the clicks.
01599     if (pSelectorTool->GetSelectionSpread() == NULL) return;
01600 
01601     // Ignore all but "hard-commits" in proper dialogue messages (not "faked" ones).
01602     if (pDlgMsg != NULL && ((SelChangeMsgSubType) pDlgMsg->DlgMsgParam) != ENTER_COMMIT)
01603         return;
01604 
01605 
01606     // Tell the selector tool to ignore selection change messages until further notice.
01607     pSelectorTool->fIgnoreSelChange = TRUE;
01608 
01609     // Compare the current contents of the edit-fields against their recorded values, to
01610     // see if any have been modified.
01611     BOOL fMustTransform = FALSE;
01612     for (INT32 i = 0; i < 8; i++)
01613     {
01614         if (HasChangedRecord(i))
01615         {
01616             UpdateRecord(&aerEdits[i]);
01617             fMustTransform = TRUE;
01618         }
01619     }
01620 
01621     // After checking and updating our records, do we have to run a transform?  Note that
01622     // we check these as they appear on the bar from left to right.
01623     UINT32 nErrorMsg=0;
01624     fConvertedOK = TRUE;
01625 
01626     if (fMustTransform)
01627     {
01628 
01629         TRACEUSER( "Matt", _T("HandleEditCommit()\n"));
01630         Range* Selection = GetApplication()->FindSelection();
01631         RangeControl TransFlags = Selection->GetRangeControlFlags();
01632         TransFlags.IgnoreNoneRenderable=TRUE;
01633         TransFlags.IgnoreInvisibleLayers = TRUE;
01634         Selection->SetRangeControl(TransFlags);
01635         SliceHelper::ModifySelectionToContainWholeButtonElements();
01636 
01637 
01638         if (aerEdits[0].fIsDirty || aerEdits[1].fIsDirty)
01639         {
01640             // X or Y has been changed - run a translate.
01641             INT32 x = ConvertMillipointRecord(0);
01642             INT32 y = ConvertMillipointRecord(1);
01643 
01644             // Convert the entered pages coordinates to spread-relative coordinates.
01645             Spread* pSpread = pSelectorTool->GetSelectionSpread();
01646             ERROR3IF(pSpread == NULL,"No selected Spread* in SelectorInfoBarOp::HandleEditCommit");
01647             DocCoord dc = UserCoord(x,y).ToSpread(pSpread);
01648 
01649             if (!fConvertedOK)
01650             {
01651                 nErrorMsg = _R(IDS_SEL_ERROR_XY);
01652                 goto AfterXform;
01653             }
01654 
01655             pSelectorTool->DoTranslateImmediate(dc.x, dc.y);
01656         }
01657 
01658         if (aerEdits[2].fIsDirty || aerEdits[3].fIsDirty)
01659         {
01660             // W or H has been changed - run a scale.
01661             INT32 w = ConvertMillipointRecord(2);
01662             INT32 h = ConvertMillipointRecord(3);
01663             if (!fConvertedOK || w == 0 || h == 0)
01664             {
01665                 fConvertedOK = FALSE;
01666                 nErrorMsg = _R(IDS_SEL_ERROR_WH);
01667                 goto AfterXform;
01668             }
01669             
01670             if (fLockAspect)
01671             {
01672                 // The aspect ratio is locked, which means we must scale either the width or
01673                 // height accordingly, whichever was not changed.  If both were changed then
01674                 // we have a little problem.
01675                 DocRect oldrect = pSelectorTool->GetSelectionBounds(DontConsiderAttrs());
01676                 if (!aerEdits[2].fIsDirty)
01677                 {
01678                     w = MulDiv32By32(oldrect.Width(), h, oldrect.Height());
01679                 }
01680                 else
01681                 {
01682                     h = MulDiv32By32(w, oldrect.Height(), oldrect.Width());
01683                 }
01684             }
01685 
01687 //          if( !DontConsiderAttrs()  &&  SelectorTool::fUseScalingFix )
01688 //              pSelectorTool->DoScaleImmediate(w, h, TRUE );   // special fix
01689 //          else
01690                 pSelectorTool->DoScaleImmediate(w, h);          // normal
01691         }
01692 
01693         if (aerEdits[4].fIsDirty || aerEdits[5].fIsDirty)
01694         {
01695             // X-scale or Y-scale has been changed - run a scale.
01696             double w = ConvertRecord(4);
01697             double h = ConvertRecord(5);
01698 
01699             // Ensure that the entered value is valid. Note that values near to zero are
01700             // actually illegal (they'd cause a divide by zero), but these are properly handled
01701             // by DoScalePercentImmediate, below.
01702             if (!fConvertedOK)
01703             {
01704                 fConvertedOK = FALSE;
01705                 nErrorMsg = _R(IDS_SEL_ERROR_XYSCALE);
01706                 goto AfterXform;
01707             }
01708 
01709             // Quietly limit the maximum scaling to 200 times (20,000%). This should allow more
01710             // than enough scaling, especially while our zoom limits are 26000%
01711             if (w > 19999.0)    w = 19999.0;
01712             if (w < -19999.0)   w = -19999.0;
01713             if (h > 19999.0)    h = 19999.0;
01714             if (h < -19999.0)   h = -19999.0;
01715 
01716             // Check for the "Lock Aspect" button.
01717             if (fLockAspect)
01718             {
01719                 // If only one edit has been changed then set the other to be equal.
01720                 if (!aerEdits[4].fIsDirty)
01721                 {
01722                     w = h;
01723                     SetDoubleEdit(_R(IDC_SEL_EDIT_XSCALE), w, FALSE);
01724                 }
01725                 else
01726                 {
01727                     // One or both have been changed but "lock aspect" is set, which presents a
01728                     // problem.  For now take the x-scale as overriding.
01729                     h = w;
01730                     SetDoubleEdit(_R(IDC_SEL_EDIT_YSCALE), h, FALSE);
01731                 }
01732             }
01733 
01734             pSelectorTool->DoScalePercentImmediate(w, h);
01735         }
01736 
01737         if (aerEdits[6].fIsDirty)
01738         {
01739             // Angle has been changed - run a rotate.
01740             double Angle = ConvertRecord(6);
01741             if (!fConvertedOK)
01742             {
01743                 nErrorMsg = _R(IDS_SEL_ERROR_ANGLE);
01744                 goto AfterXform;
01745             }
01746 
01747             // Ensure the angle is between -360 and +360. We use an integer modulus to get
01748             // the angle back under control.
01749             if (fabs(Angle) >= 360.0)
01750             {
01751                 // The angle is out of range, so we need to make it sensible
01752                 BOOL Negative = (Angle < 0.0);
01753 
01754                 Angle = ((INT32)floor(fabs(Angle))) % 360;
01755 
01756                 if (Negative)
01757                     Angle = -Angle;
01758             }
01759 
01760             pSelectorTool->DoRotateImmediate((FIXED16) Angle);
01761         }
01762 
01763         if (aerEdits[7].fIsDirty)
01764         {
01765             // Shear-angle has been changed - run a shear.
01766             double Angle = ConvertRecord(7);
01767             if (!fConvertedOK)
01768             {
01769                 nErrorMsg = _R(IDS_SEL_ERROR_SHEAR);
01770                 goto AfterXform;
01771             }
01772 
01773             // Clip the angle to lie between +/- 89.0 degrees
01774             if (fabs(Angle) > 89.0)
01775                 Angle = (Angle < 0.0) ? -89.0 : 89.0;
01776 
01777             pSelectorTool->DoShearImmediate((FIXED16) Angle);
01778         }
01779 
01780         SliceHelper::RestoreSelection();
01781     }
01782 
01783 AfterXform:
01784     // Check if we got here because an edit conversion failed.
01785     if (!fConvertedOK) ReportEditError(nErrorMsg);
01786 
01787     // Reset the selection-change handler flag.  If we ran a transform then manually
01788     // update the selection.
01789     pSelectorTool->fIgnoreSelChange = FALSE;
01790 
01791     if (fMustTransform && fConvertedOK)
01792     {
01793         pSelectorTool->SelectionHasChanged();
01794     }
01795 }
01796 
01797 
01798 
01799 
01800 /********************************************************************************************
01801 >   void SelectorInfoBarOp::ReportEditError(UINT32 nErrorMsgID)
01802 
01803     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01804     Created:    24/2/95
01805     Inputs:     nErrorMsgID         the string resource ID of the error message to
01806                                     display in the error dialogue.
01807     Outputs:    -
01808     Returns:    -
01809     Purpose:    Reports errors the user makes when typing in the selector tool-bar
01810                 edit fields.
01811     Errors:     -
01812     SeeAlso:    SelectorInfoBarOp::HandleEditCommit
01813 ********************************************************************************************/
01814 
01815 void SelectorInfoBarOp::ReportEditError(UINT32 nErrorMsgID)
01816 {
01817     // Report the error with a message box.
01818     ToolInformError(TOOLID_SELECTOR, nErrorMsgID);
01819 
01820     // Reset the edit fields to correct values.
01821     SetEdit_OnSelectionChange();
01822 }
01823 
01824 
01825 
01826 /********************************************************************************************
01827 >   void SelectorInfoBarOp::HandleGridButton(DialogMsg* pDlgMsg)
01828 
01829     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01830     Created:    16/11/94
01831     Inputs:     pDlgMsg         pointer to a dialogue message.
01832     Outputs:    -
01833     Returns:    -
01834     Purpose:    Responds to a click on the "telephone keypad", passing the event on to
01835                 the selector tool.
01836     Errors:     -
01837     SeeAlso:    SelectorTool::SetRotateCentre
01838 ********************************************************************************************/
01839 
01840 void SelectorInfoBarOp::HandleGridButton(DialogMsg* pDlgMsg)
01841 {
01842     pSelectorTool->SetRotateCentre((INT32) pDlgMsg->DlgMsgParam);
01843 }
01844  
01845 
01846 
01847 /********************************************************************************************
01848 >   virtual DialogBarOp* SelectorInfoBarOpCreate::Create()
01849 
01850     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01851     Created:    11/7/94
01852     Inputs:     -
01853     Outputs:    -
01854     Returns:    A pointer to a SelectorBarOp object allocated on the heap.
01855     Purpose:    Used by the bar code to create an appropriate InformationBarOp.
01856     Errors:     -
01857     SeeAlso:    class SelectorInfoBarOp; class BarCreate
01858 ********************************************************************************************/
01859 
01860 DialogBarOp* SelectorInfoBarOpCreate::Create()
01861 {
01862     return new SelectorInfoBarOp;
01863 }

Generated on Sat Nov 10 03:47:55 2007 for Camelot by  doxygen 1.4.4