zoomops.cpp

Go to the documentation of this file.
00001 // $Id: zoomops.cpp 1771 2007-06-17 20:14:43Z 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     
00100     zoomops.cpp
00101 
00102     Zoom tool operations.
00103 
00104 */
00105 
00106 #include "camtypes.h"
00107 #include "zoomops.h"
00108 #include "zoomtool.h"
00109 
00110 //#include "xlong.h"
00111 //#include "wrkcoord.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "wrkrect.h"
00113 //#include "doccoord.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00114 
00115 //#include "app.h"
00116 #include "csrstack.h"
00117 //#include "document.h"
00118 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00119 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00120 //#include "progress.h"
00121 #include "selector.h"       // for static InflateByBlobBorder function
00122 
00123 //#include "ngcore.h"
00124 //#include "ngitem.h"
00125 
00126 //#include "zoomres.h"
00127 //#include "justin.h"
00128 //#include "justin3.h"
00129 //#include "mario.h"            // for _R(IDE_NOMORE_MEMORY)
00130 #include "bubbleid.h"
00131 
00132 #if !defined(EXCLUDE_FROM_RALPH)
00133 #include "rulers.h"
00134 #endif
00135 
00136 #ifdef _BATCHING   
00137 //#include "sglcart.h"
00138 //#include "camdoc.h"
00139 #endif
00140 
00141 #include "brushmsg.h"
00142 //#include "ngscan.h" // For CreateDisplayScan()
00143 
00144 
00145 // Revision information.
00146 DECLARE_SOURCE("$Revision: 1771 $");
00147 
00148 // Standard preliminaries.
00149 CC_IMPLEMENT_DYNCREATE(OpZoom, OpCentredDragBox)
00150 CC_IMPLEMENT_DYNCREATE(OpZoomIn, OpZoom)
00151 CC_IMPLEMENT_DYNCREATE(OpZoomOut, OpZoom)
00152 CC_IMPLEMENT_DYNCREATE(OpZoomTo100, OpZoom)
00153 CC_IMPLEMENT_DYNCREATE(OpZoomTo200, OpZoom)
00154 CC_IMPLEMENT_DYNCREATE(OpZoomTo300, OpZoom)
00155 CC_IMPLEMENT_DYNCREATE(OpZoomTo400, OpZoom)
00156 
00157 #if !defined(EXCLUDE_FROM_RALPH)
00158 CC_IMPLEMENT_DYNCREATE(ZoomInfoBarOp, InformationBarOp)
00159 #endif
00160 
00161 #define new CAM_DEBUG_NEW
00162 
00163 
00164 // This makes the computer go "beep!".
00165 //extern void Beep();
00166 
00167 
00169 // class OpZoom
00170 
00171 /*********************************************************************************************
00172     Preference: FixZoomClickPoint
00173     Section:    Zoom Tool
00174     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00175     Range:      FALSE or TRUE
00176     Purpose:    When zooming in or out with a mouse click, this determines whether to fix
00177                 the clicked point in the resulting zoomed view at the same screen-relative
00178                 position, or to centre the zoomed view on the clicked point.  By default
00179                 this is FALSE (don't fix, do centre).
00180 **********************************************************************************************/
00181 
00182 BOOL OpZoom::m_fFixZoomClickPoint = FALSE;
00183 
00184 
00185 
00186 /**************************************************************************************
00187     Preference: RadialZoomDragBox
00188     Section:    Zoom Tool
00189     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00190     Range:      FALSE or TRUE
00191     Purpose:    Determines how the zoom drag operation invokes by the zoom tool will
00192                 draw its drag box.  If FALSE (the default) then the tool will draw the
00193                 box from one corner to its opposite.  This is similar to the selector's
00194                 drag box.  If TRUE then the tool will draw its centre box centred on
00195                 the point where the drag started and extending to the current mouse
00196                 position.  The effect is to centre the zoom on the first clicked point.
00197 ***************************************************************************************/
00198 
00199 BOOL OpZoom::m_fRadialZoomDragBox = FALSE;
00200 
00201 
00202 
00203 /**************************************************************************************
00204     Preference: ShowZoomInOutCursors
00205     Section:    Zoom Tool
00206     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00207     Range:      0 ... 1
00208     Purpose:    Determines whether to flash a "zooming-in" or "zooming-out" cursor
00209                 when a zoom is being calculated, and a special drag cursor when dragging
00210                 in the zoom tool.
00211                 
00212                 Some people think this adds a groovy, polished feel to the program.
00213                 Others don't, which is why this preference is 0 by default (ie. no
00214                 special zoom cursors).
00215 ***************************************************************************************/
00216 
00217 UINT32 OpZoom::m_nfShowZoomCursors = 0;
00218 
00219 
00220 // The zoom array holds the 'prefered' scale factors. As we zoom in and out we will
00221 // try and zoom to one of these values first and then step along the table.
00222 INT32 OpZoom::ZoomTable[cZoomTableSize] =
00223 {
00224     25601,                  // probably the highest zoom factor in the world . . .
00225     16000,
00226     8000,
00227     4000,                   // these are PERCENTAGES of a view's normal size.
00228     2000,
00229     1000,
00230     500,
00231     200,
00232     100,                    // the default, 100%, at position cDefaultZoomIndex
00233     75,
00234     50,
00235     25,
00236     10,
00237 };
00238 
00239                                       
00240 
00241 /********************************************************************************************
00242 >   OpZoom::OpZoom()
00243 
00244     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00245     Created:    23/4/95
00246     Purpose:    Default constructor.  To run a zoom drag, call the DoDrag() function.
00247 ********************************************************************************************/
00248 
00249 OpZoom::OpZoom()
00250       : m_csrZoomIn((Tool_v1*)NULL, _R(IDCSR_ZOOM_IN)),             // we only need these cursors when an OpZoom
00251         m_csrZoomOut((Tool_v1*)NULL, _R(IDCSR_ZOOM_OUT)),           
00252         m_csrZoomDrag((Tool_v1*)NULL, _R(IDCSR_ZOOM_DRAG))          // is going to be run
00253 {
00254 //  ERROR3IF(!m_csrZoomIn.IsValid() || !m_csrZoomOut.IsValid() || !m_csrZoomDrag.IsValid(),
00255 //              "Failed to load cursor(s) in OpZoom::OpZoom");
00256 }
00257 
00258 /********************************************************************************************
00259 
00260 >   virtual void OpZoom::Do(OpDescriptor* pZoomOpDesc)
00261 
00262     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
00263     Created:    20/9/95
00264     Inputs:     pointer to the OpZoomDescriptor being invoked
00265     Purpose:    Performs the zoom operation
00266     SeeAlso:    OpZoomDescriptor::FakeInvoke;
00267 
00268 ********************************************************************************************/
00269             
00270 void OpZoom::Do(OpDescriptor *pOpDesc)
00271 {
00272     // Do what FakeInvoke does but call the DoZoom function instead of HandleButtonMsg for
00273     // the zoom descriptor.
00274     OpZoomDescriptor* pZoomOpDesc = (OpZoomDescriptor*) pOpDesc;
00275     if (pZoomOpDesc != 0 && pZoomOpDesc->IsAvailable())
00276     {
00277         // DoZoom function must End the operation.
00278         pZoomOpDesc->DoZoom(this);
00279     }
00280 }
00281 
00282 
00283 /********************************************************************************************
00284 >   static void OpZoom::SpreadToWork(Spread* pspdIn, const DocCoord& dcIn,
00285                                      WorkCoord* pwcOut)
00286     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00287     Created:    24/4/95
00288     Inputs:     pspdIn      the spread containing the document coordinate
00289                 dcIn        the position within the spread
00290     Outputs:    pwcOut      the equivalent work coordinate in the current view
00291     Returns:    -
00292     Purpose:    Converts a document spread coordinate into a work coordinate in the
00293                 current view.
00294     SeeAlso:    OpZoom::WorkToSpread
00295 ********************************************************************************************/
00296 
00297 void OpZoom::SpreadToWork(Spread* pspdIn, const DocCoord& dcIn, WorkCoord* pwcOut)
00298 {
00299     // Caller must provide a location to store the converted coordinate.
00300     ERROR3IF(pwcOut == 0, "No output in OpZoom::SpreadToWork");
00301 
00302     // Find the current DocView.
00303     DocView* pDocView = DocView::GetCurrent();
00304     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::SpreadToWork");
00305 
00306     // Convert.
00307     if (pDocView && pwcOut)
00308         *pwcOut = ((DocCoord&) dcIn).ToWork(pspdIn, pDocView);
00309 }
00310 
00311 
00312 
00313 /********************************************************************************************
00314 >   static void OpZoom::SpreadToWork(Spread* pspdIn, const DocRect& drIn,
00315                                      WorkRect* pwrOut)
00316     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00317     Created:    24/4/95
00318     Inputs:     pspdIn      the spread containing the document rectangle
00319                 dcIn        the rectangle within the spread
00320     Outputs:    pwcOut      the equivalent work rectangle in the current view
00321     Returns:    -
00322     Purpose:    Converts a document spread rectangle into a work rectangle in the
00323                 current view.
00324     SeeAlso:    OpZoom::WorkToSpread
00325 ********************************************************************************************/
00326 
00327 void OpZoom::SpreadToWork(Spread* pspdIn, const DocRect& drIn, WorkRect* pwrOut)
00328 {
00329     // Convert low and high corners of the rectangle.
00330     SpreadToWork(pspdIn, drIn.lo, &pwrOut->lo);
00331     SpreadToWork(pspdIn, drIn.hi, &pwrOut->hi);
00332 }
00333 
00334 
00335 
00336 /********************************************************************************************
00337 >   static INT32 OpZoom::GetPresetZoomPercent(INT32 nPreset)
00338 
00339     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00340     Created:    24/4/95
00341     Inputs:     nPreset         which preset zoom factor, with 0 the highest and
00342                                 cZoomTableSize-1 the lowest.
00343     Returns:    A standard preset zoom factor, as a percentage.
00344     Purpose:    
00345 ********************************************************************************************/
00346 
00347 INT32 OpZoom::GetPresetZoomPercent(INT32 nPreset)
00348 {
00349     ERROR3IF(nPreset < 0 || nPreset >= cZoomTableSize,
00350                 "Bad preset in OpZoom::GetPresetZoomPercent");
00351     return ZoomTable[nPreset];
00352 }
00353 
00354 
00355 
00356 /********************************************************************************************
00357 >   static FIXED16 OpZoom::GetPresetZoomScale(INT32 nPreset)
00358 
00359     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00360     Created:    24/4/95
00361     Inputs:     nPreset         which preset zoom factor, with 0 the highest and
00362                                 cZoomTableSize-1 the lowest.
00363     Returns:    A standard preset zoom factor, as a scale factor.
00364     Purpose:    
00365 ********************************************************************************************/
00366 
00367 FIXED16 OpZoom::GetPresetZoomScale(INT32 nPreset)
00368 {
00369     ERROR3IF(nPreset < 0 || nPreset >= cZoomTableSize,
00370                 "Bad preset in OpZoom::GetPresetZoomScale");
00371     return ((FIXED16) ZoomTable[nPreset]) / 100;
00372 }
00373 
00374 
00375 
00376 /********************************************************************************************
00377 >   BOOL OpZoom::DoDrag(Spread* pStartSpread,
00378                         const DocCoord& dcStartPos,
00379                         ClickModifiers cmods)
00380 
00381     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00382     Created:    23/4/95
00383     Inputs:     pStartSpread        the spread containing the initial mouse postion
00384                 dcStartPos          the initial mosue position, ie, where the drag started
00385                 cmods               the state of the mouse modifier keys
00386     Purpose:    Starts an auto-scroll drag operation at the given mouse position.  Note that
00387                 this function hides the base-class DoDrag() function.
00388     SeeAlso:    OpDragBox::DoDrag
00389 ********************************************************************************************/
00390 
00391 BOOL OpZoom::DoDrag(Spread* pStartSpread, const DocCoord& dcStartPos, ClickModifiers cmods)
00392 {
00393     return OpDragBox::DoDrag(DRAGTYPE_AUTOSCROLL, pStartSpread, dcStartPos, cmods);
00394 }
00395 
00396 
00397 
00398 /********************************************************************************************
00399 >   BOOL OpZoom::OnDragStarted(Spread*, const Doccoord&, ClickModifiers)
00400 
00401     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00402     Created:    23/4/95
00403     Inputs:     (not used)
00404     Returns:    TRUE (always)
00405     Purpose:    Called by OpZoom's base class, OpDragBox, when a drag has been started.
00406                 Sets the status line text to a helpful comment.
00407 ********************************************************************************************/
00408 
00409 BOOL OpZoom::OnDragStarted(Spread*, const DocCoord&, ClickModifiers)
00410 {
00411     // Remember where the drag started.  We have to "bodge" this as it is apparently too
00412     // difficult to translate document coordinates to work coordinates during a drag, so
00413     // we can't use the mouse position info passed to us by the OpDragBox base-class.
00414     DocView* pDocView = DocView::GetCurrent();
00415     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::OnDragStarted");
00416     m_wcStartPos = pDocView->GetClickWorkCoord();
00417 
00418     // Reset this flag.
00419     m_fStatusTextShown = FALSE;
00420 
00421     // Possibly set the zoom-cursor, saving the old one, and return success.
00422     if (m_nfShowZoomCursors) m_ncsrSaveDrag = CursorStack::GPush(&m_csrZoomDrag);
00423     return TRUE;
00424 }
00425 
00426 
00427 
00428 /********************************************************************************************
00429 >   BOOL OpZoom::OnPointerMoved(Spread*, const DocRect&, ClickModifiers)
00430 
00431     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00432     Created:    24/6/95
00433     Inputs:     (not used)
00434     Returns:    TRUE, meaning continue dragging.
00435     Purpose:    If this function is called then a drag has definitely started, so update
00436                 the status bar.  We don't do this on a button-down event.
00437 ********************************************************************************************/
00438 
00439 BOOL OpZoom::OnPointerMoved(Spread*, const DocRect&, ClickModifiers)
00440 {
00441 #if !defined(EXCLUDE_FROM_RALPH)
00442     // The first time through this function set the status-line text.  We don't really
00443     // want to do this on a button-down event as not all such events lead to drags.
00444     if (!m_fStatusTextShown)
00445     {
00446         // Set the status line text.  If we manage to do it then don't bother doing it
00447         // again until another drag really begins.
00448         String_256 str(_R(IDS_ZOOMOP_STATUSHELP));
00449         m_fStatusTextShown = GetApplication()->UpdateStatusBarText(&str);   
00450     }
00451 #endif
00452     
00453     // All fine, continue dragging.
00454     return TRUE;
00455 }
00456 
00457 
00458 
00459 /********************************************************************************************
00460 >   BOOL OpZoom::OnDragEnded(Spread* pBoxSpread,
00461                              const DocRect& drDragBox,
00462                              ClickModifiers cmods,
00463                              BOOL fDragOK)
00464     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00465     Created:    23/4/95
00466     Inputs:     pBoxSpread          the spread where the drag was started
00467                 drDragBox           the last extent of the drag box drawn by the user
00468                 cmods               the state of the mouse click modifiers (not used)
00469                 fDragOK             the FALSE the drag failed or was cancelled
00470     Returns:    TRUE (always)
00471     Purpose:    Called when the drag is successfully finished.  We check to see if the
00472                 mouse actually moved noticably during the drag. If it did not, then a
00473                 simple click operation is performed. If it did though, the area of the
00474                 drag box will be zoomed in on.
00475 ********************************************************************************************/
00476 
00477 BOOL OpZoom::OnDragEnded(Spread*, const DocRect&, ClickModifiers, BOOL fDragOK)
00478 {
00479     // Pop the cursor we possibly pushed in OnStartDrag.
00480     if (m_nfShowZoomCursors) CursorStack::GPop(m_ncsrSaveDrag);
00481     
00482     // If the drag didn't happen we do nothing.  We don't want FailAndExecute() called
00483     // though, so return TRUE.
00484     if (!fDragOK) return TRUE;
00485 
00486     // This could take a while . . .
00487 //  BeginSlowJob();
00488 
00489     // Get the current view.
00490     DocView* pDocView = DocView::GetCurrent();
00491     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::OnDragEnded");
00492 
00493     // Find the half of the absolute width and height of the drag box.
00494     WorkCoord wcLast = pDocView->GetClickWorkCoord();
00495     WorkRect wrZoom;
00496 
00497     if (m_fRadialZoomDragBox)
00498     {
00499         XLONG nWidth2 = m_wcStartPos.x - wcLast.x;
00500         if (nWidth2 < 0) nWidth2 = -nWidth2;
00501         XLONG nHeight2 = m_wcStartPos.y - wcLast.y;
00502         if (nHeight2 < 0) nHeight2 = -nHeight2;
00503 
00504         // Make a rectangle of this width and height, centred on the click point.
00505         wrZoom = WorkRect(m_wcStartPos.x - nWidth2, m_wcStartPos.y - nHeight2,
00506                           m_wcStartPos.x + nWidth2, m_wcStartPos.y + nHeight2);
00507     }
00508     else
00509     {
00510         #undef  MIN
00511         #undef  MAX
00512         #define MIN(a,b) (((a)<(b))?(a):(b))
00513         #define MAX(a,b) (((a)>(b))?(a):(b))
00514         
00515         wrZoom = WorkRect(MIN(m_wcStartPos.x, wcLast.x),
00516                           MIN(m_wcStartPos.y, wcLast.y),
00517                           MAX(m_wcStartPos.x, wcLast.x),
00518                           MAX(m_wcStartPos.y, wcLast.y));
00519     }
00520 
00521     // We must first check if we have a significant drag box.  If the size of the box
00522     // is less than the Camelot "click radius" we will ignore the drag and treat the
00523     // operation as a single-click "zoom in" action by the user.
00524 
00525     // Graeme (11/11/99): The comparison is now done against a constant value
00526     // (ZOOM_MIN_DRAG), which is defined in zoomops.h. dDragDistance gives an absolute
00527     // value, rather than testing against separate x and y values.
00528 
00529     // Zoom in bug fixed by Chris Snook/Graeme (14/12/99) ....
00530 
00531     double dDragDistance = sqrt ( ( (double) wrZoom.Width () * (double) wrZoom.Width () ) +
00532                                   ( (double) wrZoom.Height () * (double) wrZoom.Height () ) );
00533 
00534     if ( dDragDistance < ZOOM_MIN_DRAG || wrZoom.Width() <= 0 || wrZoom.Height() <= 0 )
00535     {
00536         // Drag is insignificant so zoom in instead.
00537         ZoomIn(m_wcStartPos, FALSE);                    // OpDragBox will end this op
00538     }
00539     else
00540     {
00541         // Do a proper mouse-drag zoom.
00542         ZoomInOnRect(wrZoom, FALSE);                    // OpDragBox will end this op
00543     }
00544     
00545     // tell people things have changed on screen
00546     TRACEUSER( "Diccon", _T("OnDragEnded\n"));
00547     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
00548 
00549     // Remove the hour-glass and return the success code.
00550 //  EndSlowJob();
00551     return TRUE;
00552 }
00553 
00554 
00555 
00556 /********************************************************************************************
00557 >   DocRect OpZoom::CalcDragBox(const DocCoord& dcStartPos, const DocCoord& dcMousePos) const
00558 
00559     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00560     Created:    23/4/95
00561     Inputs:     dcStartPos          the position where the drag was started
00562                 dcMousePos          the current position of the mouse
00563     Returns:    A document (spread) rectangle the is the current bounds of the drag box.
00564     Purpose:    Overrides the default OpDragBox method to allow the drag box to be drawn
00565                 from the centre (start of drag) to the corner (current mouse position), if
00566                 the 'ZoomDragOnCentre' preference allows.  If it doesn't the default method
00567                 is called instead.
00568     SeeAlso:    OpDragBox::CalcDragBox
00569 ********************************************************************************************/
00570 
00571 DocRect OpZoom::CalcDragBox(const DocCoord& dcStartPos, const DocCoord& dcMousePos) const
00572 {
00573     // Do what the preferences say.
00574     return (m_fRadialZoomDragBox) ? OpCentredDragBox::CalcDragBox(dcStartPos, dcMousePos)
00575                                   : OpDragBox::CalcDragBox(dcStartPos, dcMousePos);
00576 }
00577 
00578 
00579 
00580 /********************************************************************************************
00581 >   void OpZoom::ZoomOut(const WorkCoord& wcZoom, BOOL fEndOp = TRUE)
00582 
00583     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00584     Created:    23/4/95
00585     Inputs:     wcZoom          the point to zoom out at
00586                 fEndOp          whether to end this operation after this zoom
00587     Purpose:    Zooms out of the current DocView by one step.  By default this function
00588                 will call the End() function for this operation afterwards.
00589 ********************************************************************************************/
00590 
00591 void OpZoom::ZoomOut(const WorkCoord& wcZoom, BOOL fEndOp)
00592 {
00593     // Find out the current view.
00594     DocView* pDocView = DocView::GetCurrent();
00595     ERROR3IF(pDocView == 0, "No selected DocView in OpZoom::ZoomOut");
00596 
00597     if (pDocView)
00598     {
00599         // Get the current view's scaling factor as a rounded precentage.
00600         INT32 nOldScalePercent = ((pDocView->GetViewScale() * 100) + FIXED16_DBL(0.5)).MakeInt();
00601 
00602         // Search forwards through the zoom table until we find a lower zoom factor, or
00603         // until we hit the end of the table, meaning no lower zoom factor exists.
00604         for (INT32 i = 0; i < cZoomTableSize; i++)
00605         {
00606             // Found a lower zoom?  If so, set it, remember it's position in the zoom table
00607             // and return.
00608             if (nOldScalePercent > GetPresetZoomPercent(i))
00609             {
00610                 // Do the zoom.  We will (optionally) end the operation.
00611                 pDocView->SetZoomTableIndex(i);
00612                 ZoomAtPoint(wcZoom, GetPresetZoomScale(i), FALSE);
00613                 break;
00614             }
00615         }
00616     }
00617 
00618     // We must correctly end the operation.
00619     if (fEndOp) End();
00620 
00621     // tell people things have changed on screen
00622     TRACEUSER( "Diccon", _T("ZoomOut\n"));
00623     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
00624 }
00625 
00626 
00627 
00628 /********************************************************************************************
00629 >   void OpZoom::ZoomOut(Spread* pZoomSpread, const DocCoord& dcZoomPos, BOOL fEndOp = TRUE)
00630 
00631     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00632     Created:    23/4/95
00633     Inputs:     pZoomSpread     the spread containing the point to zoom out at
00634                 dcZoomPos       the point to zoom out at
00635                 fEndOp          whether to end this operation after this zoom
00636     Purpose:    Zooms out of the current DocView by one step.  By default this function
00637                 will call the End() function for this operation afterwards.
00638 ********************************************************************************************/
00639 
00640 void OpZoom::ZoomOut(Spread* pZoomSpread, const DocCoord& dcZoomPos, BOOL fEndOp)
00641 {
00642     WorkCoord wcZoom;
00643     SpreadToWork(pZoomSpread, dcZoomPos, &wcZoom);
00644     ZoomOut(wcZoom, fEndOp);
00645 }
00646 
00647 
00648 /********************************************************************************************
00649 >   void OpZoom::ZoomTo(const WorkCoord& wcZoom, INT32 nPercent, BOOL fEndOp = TRUE)
00650 
00651     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00652     Created:    23/4/95
00653     Inputs:     wcZoom          the point to zoom in at
00654                 fEndOp          whether to end this operation after this zoom
00655     Purpose:    Zooms into the current DocView by one step.  By default this function
00656                 will call the End() function for this operation afterwards.
00657 ********************************************************************************************/
00658 
00659 void OpZoom::ZoomTo(const WorkCoord& wcZoom, INT32 nPercent, BOOL fEndOp)
00660 {
00661     // Find out the current view.
00662     DocView* pDocView = DocView::GetCurrent();
00663     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::ZoomIn");
00664     
00665     if (pDocView)
00666     {
00667         // Do the zoom.  We will (optionally) end the operation.
00668         FIXED16     f16Scale = FIXED16(nPercent) / 100;
00669         ZoomAtPoint(wcZoom, f16Scale, FALSE);
00670     }
00671 
00672     // End the operation if the caller wants us to.
00673     if (fEndOp) End();
00674 }
00675 
00676 
00677 /********************************************************************************************
00678 >   void OpZoom::ZoomIn(const WorkCoord& wcZoom, BOOL fEndOp = TRUE)
00679 
00680     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00681     Created:    23/4/95
00682     Inputs:     wcZoom          the point to zoom in at
00683                 fEndOp          whether to end this operation after this zoom
00684     Purpose:    Zooms into the current DocView by one step.  By default this function
00685                 will call the End() function for this operation afterwards.
00686 ********************************************************************************************/
00687 
00688 void OpZoom::ZoomIn(const WorkCoord& wcZoom, BOOL fEndOp)
00689 {
00690     // Find out the current view.
00691     DocView* pDocView = DocView::GetCurrent();
00692     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::ZoomIn");
00693     
00694     if (pDocView)
00695     {
00696         // Find the current view's scaling factor.  By converting this to a percentage
00697         // and rounding we improve the accuracy of the comparison below.
00698         INT32 nOldScalePercent = ((pDocView->GetViewScale() * 100) + FIXED16_DBL(0.5)).MakeInt();
00699 
00700         // Search backwards until we find a higher zoom, or the end of the table (meaning that
00701         // there is no higher zoom).
00702         for (INT32 i = cZoomTableSize - 1; i >= 0; i--)
00703         {
00704             // Found a higher zoom?  If so, set it, remember it's position and return.
00705             if (nOldScalePercent < GetPresetZoomPercent(i))
00706             {
00707                 // Do the zoom.  We will (optionally) end the operation.
00708                 pDocView->SetZoomTableIndex(i);
00709                 ZoomAtPoint(wcZoom, GetPresetZoomScale(i), FALSE);
00710                 break;
00711             }
00712         }
00713     }
00714 
00715     // End the operation if the caller wants us to.
00716     if (fEndOp) End();
00717 }
00718 
00719 
00720 
00721 /********************************************************************************************
00722 >   void OpZoom::ZoomIn(Spread* pZoomSpread, const DocCoord& dcZoomPos, BOOL fEndOp = TRUE)
00723 
00724     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00725     Created:    23/4/95
00726     Inputs:     pZoomSpread     the spread containing the point to zoom in at
00727                 dcZoomPos       the point to zoom in at
00728                 fEndOp          whether to end this operation after this zoom
00729     Purpose:    Zooms in on the current DocView by one step.  By default this function
00730                 will call the End() function for this operation afterwards.
00731 ********************************************************************************************/
00732 
00733 void OpZoom::ZoomIn(Spread* pZoomSpread, const DocCoord& dcZoomPos, BOOL fEndOp)
00734 {
00735     WorkCoord wcZoom;
00736     SpreadToWork(pZoomSpread, dcZoomPos, &wcZoom);
00737     ZoomIn(wcZoom, fEndOp);
00738 }
00739 
00740 
00741 
00742 /********************************************************************************************
00743 >   void OpZoom::ZoomInOnRect(const WorkRect& wrZoom, BOOL fEndOp = TRUE)
00744 
00745     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00746     Created:    23/4/95
00747     Inputs:     wrZoom          the rectangle to zoom in on.
00748                 fEndOp          whether to end this operation after this zoom
00749     Purpose:    Zooms so that the given work rectangle completely fills the current
00750                 DocView view extents.  By default this function will call the End()
00751                 function for this operation afterwards.
00752 ********************************************************************************************/
00753 
00754 void OpZoom::ZoomInOnRect(const WorkRect& wrZoom, BOOL fEndOp)
00755 {
00756     // Make sure the zoom rectangle isn't empty, or we'll divide by zero later on.
00757     if (wrZoom.IsEmpty())
00758     {
00759         ERROR3("Empty zoom rectangle passed to OpZoom::ZoomInOnRect");
00760         return;
00761     }
00762 
00763     // Find out the current view and save its scale factor and scroll offsets.
00764     DocView* pDocView = DocView::GetCurrent();
00765     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::ZoomInOnRect");
00766     // Get out now if view 0 otherwise we will access violate later on
00767     if (pDocView == 0)
00768         return;
00769     
00770     OpZoomPrevZoomDescriptor::SaveZoom(pDocView);
00771 
00772     // Find out the size of the window and the given zoom rectangle in work coordinates.
00773     WorkRect wrView = pDocView->GetViewRect();
00774 
00775     // Get the current scale factor.
00776     double fpOldScaleFactor = pDocView->GetViewScale().MakeDouble();
00777 
00778     // Find out the ratios of the width and height (zoom rect to view rect).  We know
00779     // that the divisors are not zero, or we would not have entered this function.
00780     double fpWidthFactor  = (double)wrView.Width ()/wrZoom.Width ();
00781     double fpHeightFactor = (double)wrView.Height()/wrZoom.Height();
00782     double fpMinFactor = (fpWidthFactor < fpHeightFactor) ? fpWidthFactor : fpHeightFactor;
00783 
00784     // The new zoom factor is proportional to the above
00785     double fpNewScaleFactor = fpOldScaleFactor * fpMinFactor;
00786 
00787     // Push the zoom-in or zoom-out cursor, depending on whether we are zooming in or
00788     // out and the state of the preference.
00789     INT32 ncsrOldID=0;
00790     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors)
00791     {
00792         ncsrOldID = CursorStack::GPush((fpNewScaleFactor > fpOldScaleFactor)
00793                                             ? &m_csrZoomIn
00794                                             : &m_csrZoomOut);
00795     }
00796     
00797     // Convert the new scale factor to a percentage and check that it's in bounds.  If it
00798     // isn't adjust it to the lowest/highest zoom factors.
00799     INT32 nZoomPercent = (INT32) (fpNewScaleFactor * 100);
00800     if (nZoomPercent < GetPresetZoomPercent(cZoomTableSize - 1))
00801     {
00802         fpNewScaleFactor = GetPresetZoomScale(cZoomTableSize - 1).MakeDouble();
00803     }
00804     else if (nZoomPercent > GetPresetZoomPercent(0))
00805     {
00806         fpNewScaleFactor = GetPresetZoomScale(0).MakeDouble();
00807     }
00808 
00809     // Set the scroll offsets to the middle of the box.
00810     WorkCoord wcScrollOffset;
00811     wcScrollOffset.x = (wrZoom.lo.x + wrZoom.hi.x) / 2;
00812     wcScrollOffset.y = (wrZoom.lo.y + wrZoom.hi.y) / 2;
00813 
00814     // Scale the value to the correct number of pixels. 
00815     double fpRatio = fpNewScaleFactor / fpOldScaleFactor;
00816     wcScrollOffset.x = XLONG(wcScrollOffset.x*fpRatio);
00817     wcScrollOffset.y = XLONG(wcScrollOffset.y*fpRatio);
00818 
00819     // Offset it by half the size of the window.  WHY?  AND WHY THE MakeLong() CALL?
00820     wcScrollOffset.x = wcScrollOffset.x - (wrView.Width() / 2);
00821     wcScrollOffset.y += wrView.Height() / 2;
00822 
00823     // Check the scroll offsets bounds as we can't have scroll offsets anywhere.
00824     if (wcScrollOffset.x < 0) wcScrollOffset.x = 0;
00825     if (wcScrollOffset.y > 0) wcScrollOffset.y = 0;
00826 
00827     // Set the scale. This must be done before the scroll offset is set or
00828     // strangeness will follow . . .
00829     pDocView->SetViewScale((FIXED16) fpNewScaleFactor);
00830     pDocView->SetScrollOffsets(wcScrollOffset, FALSE);
00831 
00832     // Update the combo-box containing scale factors.
00833     pDocView->SetZoomTableIndex(cFractionalZoomIndex);
00834 #ifndef RALPH
00835     OpZoomComboDescriptor::Update();
00836 #endif
00837 
00838     // We have to force a redraw as the zoom has changed, reset the cursor, and end the
00839     // operation.
00840     pDocView->ForceRedraw(TRUE);
00841     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors) CursorStack::GPop(ncsrOldID);
00842     if (fEndOp) End();
00843 
00844 
00845     // tell people things have changed on screen
00846     TRACEUSER( "Diccon", _T("ZoomInOnRect\n"));
00847     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
00848 }
00849 
00850 
00851 
00852 /********************************************************************************************
00853 >   void OpZoom::ZoomInOnRect(Spread* pZoomSpread,
00854                               const DocRect& drZoomRect,
00855                               BOOL fEndOp = TRUE)
00856 
00857     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00858     Created:    23/4/95
00859     Inputs:     pZoomSpread     the spread containing the rectangle to zoom in on
00860                 drZoomRect      the rectangle to zoom in on.
00861                 fEndOp          whether to end this operation after this zoom
00862     Purpose:    Zooms so that the given spread rectangle completely fills the current
00863                 DocView view extents.  By default this function will call the End()
00864                 function for this operation afterwards.
00865 ********************************************************************************************/
00866 
00867 void OpZoom::ZoomInOnRect(Spread* pZoomSpread, const DocRect& drZoomRect, BOOL fEndOp)
00868 {
00869     // Call the WorkRect version of this function to do the zoom.
00870     WorkRect wrZoom;
00871     SpreadToWork(pZoomSpread, drZoomRect, &wrZoom);
00872     ZoomInOnRect(wrZoom, fEndOp);
00873 }
00874 
00875 
00876 
00877 /********************************************************************************************
00878 >   void OpZoom::ZoomAtPoint(const WorkCoord& wcZoom, FIXED16 fxNewScaleFactor,
00879                              BOOL fEndOp = TRUE)
00880 
00881     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00882     Created:    23/4/95
00883     Inputs:     wcZoom                  the point within the current view to zoom at,
00884                                         in work coordinates.
00885                 fxNewScaleFactor        the required scale factor
00886                 fEndOp                  whether to end this operation after this zoom
00887     Purpose:    Sets the current DocView to show the given point at the given scale factor.
00888                 By default this function will call the End() function for this operation
00889                 afterwards.
00890 ********************************************************************************************/
00891 /********************************************************************************************
00892 Technical notes:
00893     What the zoom does. This routine finds out the current scroll offsets and makes
00894     a vector from the clicked point to the top corner of the window (ie the scroll
00895     offsets).  It knows the ratio of the old scale factor and the new scale factor
00896     and uses this to calculate a new point from the click point along the vector.
00897 
00898     For example, if the ratio of the old and new zooms is one half then the new top
00899     corner of the window will be a point on the vector, half way between the click
00900     point and the old top corner of the window.
00901 
00902     Since the document will be changing size and since the scroll offsets are
00903     measured in pixels, these will be changing after the zoom has happened, so we
00904     have to compensate for that as well. All that remains to do after that is check
00905     that the offsets are valid and then set them.
00906 ********************************************************************************************/
00907 
00908 void OpZoom::ZoomAtPoint(const WorkCoord& wcZoom, FIXED16 fxNewScaleFactor, BOOL fEndOp)
00909 {
00910     // Get the current view.
00911     DocView* pDocView = DocView::GetCurrent();
00912     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::ZoomAtPoint");
00913 
00914     // Save the view's current zoom and find out current scaling factor.
00915     OpZoomPrevZoomDescriptor::SaveZoom(pDocView);
00916     FIXED16 fxOldScaleFactor = pDocView->GetViewScale();
00917 
00918     // Push the zoom-in or zoom-out cursor, depending on whether we are zooming in or
00919     // out.
00920     INT32 ncsrOldID=0;
00921     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors)
00922     {
00923         ncsrOldID = CursorStack::GPush((fxNewScaleFactor > fxOldScaleFactor)
00924                                             ? &m_csrZoomIn
00925                                             : &m_csrZoomOut);
00926     }
00927 
00928     // Find the current view size in 64-bit work coordinates.
00929     WorkRect wrView = pDocView->GetViewRect();
00930 
00931     // Work out the ratio of the new and old scale factors.
00932     double fpLineRatio = fxOldScaleFactor.MakeDouble() / fxNewScaleFactor.MakeDouble();
00933 
00934     // We either centre the clicked point or keep it fixed, depending on the preferences.
00935     // Calculate the new position of the top-left of the view accordingly.
00936     WorkCoord wcNewTopCorner = wcZoom;
00937     if (m_fFixZoomClickPoint)
00938     {
00939         // Find the vector from the click point to the top corner of the window, and
00940         // from this work out the new position of the top-left corner of the view.
00941         wcNewTopCorner.x += XLONG(fpLineRatio * (wrView.lo.x - wcZoom.x));
00942         wcNewTopCorner.y += XLONG(fpLineRatio * (wrView.hi.y - wcZoom.y));
00943     }
00944     else
00945     {
00946         // Find the vector from the centre of the view to the top-left corner, scaled by
00947         // the line-ratio.  Add this vector to the click point to work out the new position
00948         // of the top-left corner of the view.
00949         wcNewTopCorner.x -= XLONG(fpLineRatio * wrView.Width ()/2);
00950         wcNewTopCorner.y += XLONG(fpLineRatio * wrView.Height()/2);
00951     }
00952 
00953     // Scale the value to the correct number of pixels.  We convert to doubles as the
00954     // fixed-point numbers can lose precision at high zooms.
00955     double fpPixRatio = fxNewScaleFactor.MakeDouble() / fxOldScaleFactor.MakeDouble();
00956     wcNewTopCorner.x  = XLONG(fpPixRatio * wcNewTopCorner.x);
00957     wcNewTopCorner.y  = XLONG(fpPixRatio * wcNewTopCorner.y);
00958         
00959     // Set the new scale factor in the view.
00960     pDocView->SetViewScale(fxNewScaleFactor);   
00961 
00962     // Make sure that the new scroll offset is within workspace bounds and set it.
00963     if (wcNewTopCorner.x < 0) wcNewTopCorner.x = 0;
00964     if (wcNewTopCorner.y > 0) wcNewTopCorner.y = 0;
00965     pDocView->SetScrollOffsets(wcNewTopCorner, FALSE);
00966 
00967 #ifndef RALPH
00968     // Update the combo-box containing scale factors.
00969     OpZoomComboDescriptor::Update();
00970 #endif
00971 
00972     // Finally redraw the whole window, reset the cursor, and end the operation.
00973     pDocView->ForceRedraw(TRUE);
00974     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors) CursorStack::GPop(ncsrOldID);
00975     if (fEndOp) End();
00976 
00977     // tell people things have changed on screen
00978     TRACEUSER( "Diccon", _T("ZoomAtPoint\n"));
00979     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
00980 }
00981 
00982 
00983 
00984 /********************************************************************************************
00985 >   void OpZoom::ZoomAtPoint(Spread* pZoomSpread, const DocCoord& dcZoomPos,
00986                              FIXED16 fxNewScaleFactor, BOOL fEndOp = TRUE)
00987     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00988     Created:    23/4/95
00989     Inputs:     pZoomSpread             the spread containing the point to zoom at
00990                 dcZoomPos               the point to at.  If the CentreOnZoomClick preference
00991                                         is TRUE then this point will remain fixed on-screen,
00992                                         otherwise this point will be centred on-screen.
00993                 fxNewScaleFactor        the required scale factor
00994                 fEndOp                  whether to end this operation after this zoom
00995     Purpose:    Sets the current DocView to show the given point with the spread at the
00996                 given scale factor.  By default this function will call the End() function
00997                 for this operation afterwards.
00998 ********************************************************************************************/
00999 
01000 void OpZoom::ZoomAtPoint(Spread* pZoomSpread, const DocCoord& dcZoomPos,
01001                          FIXED16 fxNewScaleFactor, BOOL fEndOp)
01002 {
01003     // Now we can just pass to the WorkCoord version of this function.
01004     WorkCoord wcZoom;
01005     SpreadToWork(pZoomSpread, dcZoomPos, &wcZoom);
01006     ZoomAtPoint(wcZoom, fxNewScaleFactor, fEndOp);
01007 }
01008 
01009 
01010 
01011 /******************************************************************************************
01012 >   BOOL OpZoom::GetStatusLineText(String_256* pText, Spread*, DocCoord, ClickModifiers)
01013 
01014     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
01015     Created:    26/1/95
01016     Inputs:     Spread*, DocCoord, ClickModifiers - not used
01017     Outputs:    pText - 
01018     Returns:    TRUE if returning valid text
01019     Purpose:    get status line help for zoom drag op
01020     Errors:     this==0
01021 ******************************************************************************************/
01022 
01023 BOOL OpZoom::GetStatusLineText(String_256* pText, Spread*, DocCoord, ClickModifiers)
01024 {
01025     ERROR2IF(this == 0, FALSE, "OpZoom::GetStatusLineText() - this == 0");
01026     ERROR2IF(pText == 0, FALSE, "OpZoom::GetStatusLineText() - pText == 0");
01027     return pText->Load(_R(IDS_ZOOMOP_STATUSHELP));
01028 }
01029 
01030 
01031 
01032 /********************************************************************************************
01033 >   static BOOL OpZoom::Declare()
01034 
01035     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01036     Created:    23/4/95
01037     Returns:    TRUE if everything went OK, FALSE otherwise
01038     Purpose:    "Registers" the zoom operation's OpDescriptors, loads preferences, and
01039                 makes sure the zoom-in and zoom-out cursors are valid.
01040     SeeAlso:    class OpZoomComboDescriptor; class OpZoomPrevZoomDescriptor;
01041                 class OpZoomFitSpreadDescriptor; class OpZoomFitDrawingDescriptor
01042 ********************************************************************************************/
01043 
01044 BOOL OpZoom::Declare()
01045 {
01046     // Try to create OpDescriptors for each zoom gadget.
01047     ERRORIF(!new OpZoomComboDescriptor ||
01048             !new OpZoomPrevZoomDescriptor ||
01049             !new OpZoomFitSpreadDescriptor ||
01050             !new OpZoomFitDrawingDescriptor ||
01051             !new OpZoomFitSelectedDescriptor ||
01052             !new OpZoomFitRectDescriptor ||
01053             !OpZoomTo100::Init() ||
01054             !OpZoomTo200::Init() ||
01055             !OpZoomTo300::Init() ||
01056             !OpZoomTo400::Init(),
01057             _R(IDE_NOMORE_MEMORY),
01058             FALSE);
01059 
01060 #if !defined(EXCLUDE_FROM_RALPH)
01061     // Try to load preferences.
01062     ERRORIF(!GetApplication()->DeclareSection(TEXT("Zoom Tool"), 5) ||
01063             !GetApplication()->DeclarePref(TEXT("Zoom Tool"), TEXT("FixZoomClickPoint"),
01064                                            &m_fFixZoomClickPoint, FALSE, TRUE) ||
01065             !GetApplication()->DeclarePref(TEXT("Zoom Tool"), TEXT("RadialZoomDragBox"),
01066                                            &m_fRadialZoomDragBox, FALSE, TRUE) ||
01067             !GetApplication()->DeclarePref(TEXT("Zoom Tool"), TEXT("ShowZoomCursors"),
01068                                            &m_nfShowZoomCursors, 0, 1),
01069             _R(IDE_BAD_INI_FILE),
01070             FALSE);
01071 #endif
01072 
01073     // Success.
01074     return TRUE;
01075 }
01076 
01077 
01078 
01079 /********************************************************************************************
01080 >   void OpZoom::MouseWheelZoomAtPoint(const WorkCoord& wcZoom, INT32 nNewScalePercent,
01081                              BOOL fEndOp = TRUE)
01082 
01083     Author:     Priestley (Xara Group Ltd) <camelotdev@xara.com> (BLATANTLY ripped from JustinF & Rik)
01084     Created:    17/11/2000
01085     Inputs:     wcZoom                  the point within the current view to zoom at,
01086                                         in work coordinates.
01087                 fxNewScaleFactor        the required scale factor
01088                 fEndOp                  whether to end this operation after this zoom
01089     Purpose:    Sets the current DocView to show the given point at the given scale factor.
01090                 By default this function will call the End() function for this operation
01091                 afterwards.
01092 ********************************************************************************************/
01093 
01094 void OpZoom::MouseWheelZoomAtPoint(const WorkCoord& wcZoom, FIXED16 fxNewScaleFactor, BOOL fEndOp)
01095 {
01096     // Get the current view.
01097     DocView* pDocView = DocView::GetCurrent();
01098     ERROR3IF(pDocView == 0, "No current DocView in OpZoom::ZoomAtPoint");
01099 
01100     // Save the view's current zoom and find out current scaling factor.
01101     OpZoomPrevZoomDescriptor::SaveZoom(pDocView);
01102     FIXED16 fxOldScaleFactor = pDocView->GetViewScale();
01103 
01104     // Push the zoom-in or zoom-out cursor, depending on whether we are zooming in or
01105     // out.
01106     INT32 ncsrOldID=0;
01107     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors)
01108     {
01109         ncsrOldID = CursorStack::GPush((fxNewScaleFactor > fxOldScaleFactor)
01110                                             ? &m_csrZoomIn
01111                                             : &m_csrZoomOut);
01112     }
01113 
01114     // Find the current view size in 64-bit work coordinates.
01115     WorkRect wrView = pDocView->GetViewRect();
01116 
01117     // Work out the ratio of the new and old scale factors.
01118     double fpLineRatio = fxOldScaleFactor.MakeDouble() / fxNewScaleFactor.MakeDouble();
01119 
01120     // We either centre the clicked point or keep it fixed, depending on the preferences.
01121     // Calculate the new position of the top-left of the view accordingly.
01122     WorkCoord wcNewTopCorner = wcZoom;
01123 
01124 //  if (!m_fFixZoomClickPoint)
01125 //  {
01126         // Find the vector from the click point to the top corner of the window, and
01127         // from this work out the new position of the top-left corner of the view.
01128         wcNewTopCorner.x += XLONG(fpLineRatio * (wrView.lo.x - wcZoom.x));
01129         wcNewTopCorner.y += XLONG(fpLineRatio * (wrView.hi.y - wcZoom.y));
01130 //  }
01131 //  else
01132 //  {
01133 //      // Find the vector from the centre of the view to the top-left corner, scaled by
01134 //      // the line-ratio.  Add this vector to the click point to work out the new position
01135 //      // of the top-left corner of the view.
01136 //      wcNewTopCorner.x -= MakeXLong(fpLineRatio * (wrView.Width().MakeDouble() / 2));
01137 //      wcNewTopCorner.y += MakeXLong(fpLineRatio * (wrView.Height().MakeDouble() / 2));
01138 //  }
01139 
01140     // Scale the value to the correct number of pixels.  We convert to doubles as the
01141     // fixed-point numbers can lose precision at high zooms.
01142     double fpPixRatio = fxNewScaleFactor.MakeDouble() / fxOldScaleFactor.MakeDouble();
01143     wcNewTopCorner.x  = XLONG(fpPixRatio * wcNewTopCorner.x);
01144     wcNewTopCorner.y  = XLONG(fpPixRatio * wcNewTopCorner.y);
01145         
01146     // Set the new scale factor in the view.
01147     pDocView->SetViewScale(fxNewScaleFactor);   
01148 
01149     // Make sure that the new scroll offset is within workspace bounds and set it.
01150     if (wcNewTopCorner.x < 0) wcNewTopCorner.x = 0;
01151     if (wcNewTopCorner.y > 0) wcNewTopCorner.y = 0;
01152     pDocView->SetScrollOffsets(wcNewTopCorner, FALSE);
01153 
01154 #ifndef RALPH
01155     // Update the combo-box containing scale factors.
01156     OpZoomComboDescriptor::Update();
01157 #endif
01158 
01159     // Finally redraw the whole window, reset the cursor, and end the operation.
01160     pDocView->ForceRedraw(TRUE);
01161     if (ZoomTool::IsSelectedTool() && m_nfShowZoomCursors) CursorStack::GPop(ncsrOldID);
01162     if (fEndOp) End();
01163 
01164     // tell people things have changed on screen
01165     TRACEUSER( "Diccon", _T("ZoomAtPoint\n"));
01166     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
01167 }
01168 
01169 
01171 // class OpZoomTo100
01172 OpZoomTo100::OpZoomTo100()
01173 {
01174 }
01175 
01176 BOOL OpZoomTo100::Init()
01177 {
01178     BOOL ok = RegisterOpDescriptor(
01179                                     0, 
01180                                     _R(IDS_ZOOMTO100),
01181                                     CC_RUNTIME_CLASS(OpZoomTo100), 
01182                                     OPTOKEN_ZOOMTO100,
01183                                     OpZoomTo100::GetState,
01184                                     0,                  /* help ID */
01185                                     _R(IDBBL_ZOOMTO100),/* bubble ID */
01186                                     0                   /* bitmap ID */
01187                                     );
01188     return ok;
01189 }
01190 
01191 /***********************************************************************************************
01192 
01193 >   static OpState OpZoomToo100::GetState(String_256* Description, OpDescriptor*)
01194 
01195     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01196     Created:    18/09/06
01197     Inputs:     Description = ptr to place description of why this op can't happen
01198                 pOpDesc     = ptr to the Op Desc associated with this op
01199     Outputs:    -
01200     Returns:    An OpState object
01201     Purpose:    Func for determining the usability of this op
01202     SeeAlso:    -
01203         
01204 ***********************************************************************************************/
01205 OpState OpZoomTo100::GetState(String_256* Description, OpDescriptor*)
01206 {
01207     OpState State;
01208     return State;
01209 }
01210 
01211 /********************************************************************************************
01212 
01213 >   virtual void OpZoomToo100::Do(OpDescriptor* pOpDesc)
01214 
01215     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01216     Created:    18/09/06
01217     Inputs:     pointer to the OpZoomDescriptor being invoked
01218     Purpose:    Calls the base class function to zoom to 100%!
01219 
01220 ********************************************************************************************/
01221 void OpZoomTo100::Do(OpDescriptor *pOpDesc)
01222 {
01223     // Ok! lets zoom in!
01224     DocView* pDocView = DocView::GetCurrent();
01225 
01226     if(pDocView)
01227     {
01228         const WorkRect ZoomRect = pDocView->GetViewRect();
01229         ZoomTo( ZoomRect.Centre(), 100 );
01230     }
01231     else
01232     {
01233         ERROR3IF(pDocView == 0, "No current DocView found!");
01234     }
01235 }
01236 
01238 // class OpZoomTo200
01239 OpZoomTo200::OpZoomTo200()
01240 {
01241 }
01242 
01243 BOOL OpZoomTo200::Init()
01244 {
01245     BOOL ok = RegisterOpDescriptor(
01246                                     0, 
01247                                     _R(IDS_ZOOMTO200),
01248                                     CC_RUNTIME_CLASS(OpZoomTo200), 
01249                                     OPTOKEN_ZOOMTO200,
01250                                     OpZoomTo200::GetState,
01251                                     0,                  /* help ID */
01252                                     _R(IDBBL_ZOOMTO200),/* bubble ID */
01253                                     0                   /* bitmap ID */
01254                                     );
01255     return ok;
01256 }
01257 
01258 /***********************************************************************************************
01259 
01260 >   static OpState OpZoomTo200::GetState(String_256* Description, OpDescriptor*)
01261 
01262     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01263     Created:    18/09/06
01264     Inputs:     Description = ptr to place description of why this op can't happen
01265                 pOpDesc     = ptr to the Op Desc associated with this op
01266     Outputs:    -
01267     Returns:    An OpState object
01268     Purpose:    Func for determining the usability of this op
01269     SeeAlso:    -
01270         
01271 ***********************************************************************************************/
01272 OpState OpZoomTo200::GetState(String_256* Description, OpDescriptor*)
01273 {
01274     OpState State;
01275     return State;
01276 }
01277 
01278 /********************************************************************************************
01279 
01280 >   virtual void OpZoomTo200::Do(OpDescriptor* pOpDesc)
01281 
01282     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01283     Created:    18/09/06
01284     Inputs:     pointer to the OpZoomDescriptor being invoked
01285     Purpose:    Calls the base class function to zoom to 200%!
01286 
01287 ********************************************************************************************/
01288 void OpZoomTo200::Do(OpDescriptor *pOpDesc)
01289 {
01290     // Ok! lets zoom in!
01291     DocView* pDocView = DocView::GetCurrent();
01292 
01293     if(pDocView)
01294     {
01295         const WorkRect ZoomRect = pDocView->GetViewRect();
01296         ZoomTo( ZoomRect.Centre(), 200 );
01297     }
01298     else
01299     {
01300         ERROR3IF(pDocView == 0, "No current DocView found!");
01301     }
01302 }
01303 
01305 // class OpZoomTo400
01306 OpZoomTo300::OpZoomTo300()
01307 {
01308 }
01309 
01310 BOOL OpZoomTo300::Init()
01311 {
01312     BOOL ok = RegisterOpDescriptor(
01313                                     0, 
01314                                     _R(IDS_ZOOMTO300),
01315                                     CC_RUNTIME_CLASS(OpZoomTo300), 
01316                                     OPTOKEN_ZOOMTO300,
01317                                     OpZoomTo300::GetState,
01318                                     0,                  /* help ID */
01319                                     _R(IDBBL_ZOOMTO300),/* bubble ID */
01320                                     0                   /* bitmap ID */
01321                                     );
01322 
01323     return ok;
01324 }
01325 
01326 /***********************************************************************************************
01327 
01328 >   static OpState OpZoomToo100::GetState(String_256* Description, OpDescriptor*)
01329 
01330     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01331     Created:    18/09/06
01332     Inputs:     Description = ptr to place description of why this op can't happen
01333                 pOpDesc     = ptr to the Op Desc associated with this op
01334     Outputs:    -
01335     Returns:    An OpState object
01336     Purpose:    Func for determining the usability of this op
01337     SeeAlso:    -
01338         
01339 ***********************************************************************************************/
01340 OpState OpZoomTo300::GetState(String_256* Description, OpDescriptor*)
01341 {
01342     OpState State;
01343     return State;
01344 }
01345 
01346 /********************************************************************************************
01347 
01348 >   virtual void OpZoomTo300::Do(OpDescriptor* pOpDesc)
01349 
01350     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01351     Created:    18/09/06
01352     Inputs:     pointer to the OpZoomDescriptor being invoked
01353     Purpose:    Calls the base class function to zoom to 300%!
01354 
01355 ********************************************************************************************/
01356 void OpZoomTo300::Do(OpDescriptor *pOpDesc)
01357 {
01358     // Ok! lets zoom in!
01359     DocView* pDocView = DocView::GetCurrent();
01360 
01361     if(pDocView)
01362     {
01363         const WorkRect ZoomRect = pDocView->GetViewRect();
01364         ZoomTo( ZoomRect.Centre(), 300 );
01365     }
01366     else
01367     {
01368         ERROR3IF(pDocView == 0, "No current DocView found!");
01369     }
01370 }
01371 
01373 // class OpZoomTo400
01374 OpZoomTo400::OpZoomTo400()
01375 {
01376 }
01377 
01378 BOOL OpZoomTo400::Init()
01379 {
01380     BOOL ok = RegisterOpDescriptor(
01381                                     0, 
01382                                     _R(IDS_ZOOMTO400),
01383                                     CC_RUNTIME_CLASS(OpZoomTo400), 
01384                                     OPTOKEN_ZOOMTO400,
01385                                     OpZoomTo400::GetState,
01386                                     0,                  /* help ID */
01387                                     _R(IDBBL_ZOOMTO400),/* bubble ID */
01388                                     0                   /* bitmap ID */
01389                                     );
01390 
01391     return ok;
01392 }
01393 
01394 /***********************************************************************************************
01395 
01396 >   static OpState OpZoomToo100::GetState(String_256* Description, OpDescriptor*)
01397 
01398     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01399     Created:    18/09/06
01400     Inputs:     Description = ptr to place description of why this op can't happen
01401                 pOpDesc     = ptr to the Op Desc associated with this op
01402     Outputs:    -
01403     Returns:    An OpState object
01404     Purpose:    Func for determining the usability of this op
01405     SeeAlso:    -
01406         
01407 ***********************************************************************************************/
01408 OpState OpZoomTo400::GetState(String_256* Description, OpDescriptor*)
01409 {
01410     OpState State;
01411     return State;
01412 }
01413 
01414 /********************************************************************************************
01415 
01416 >   virtual void OpZoomToo100::Do(OpDescriptor* pOpDesc)
01417 
01418     Author:     Luke_Hart (Xara Group Ltd) <camelotdev@xara.com>
01419     Created:    18/09/06
01420     Inputs:     pointer to the OpZoomDescriptor being invoked
01421     Purpose:    Calls the base class function to zoom to 400%!
01422 
01423 ********************************************************************************************/
01424 void OpZoomTo400::Do(OpDescriptor *pOpDesc)
01425 {
01426     // Ok! lets zoom in!
01427     DocView* pDocView = DocView::GetCurrent();
01428 
01429     if(pDocView)
01430     {
01431         const WorkRect ZoomRect = pDocView->GetViewRect();
01432         ZoomTo( ZoomRect.Centre(), 400 );
01433     }
01434     else
01435     {
01436         ERROR3IF(pDocView == 0, "No current DocView found!");
01437     }
01438 }
01439 
01440 
01442 // class OpZoomIn
01443 OpZoomIn::OpZoomIn()
01444 {
01445 }
01446 
01447 BOOL OpZoomIn::Init()
01448 {
01449     BOOL ok = RegisterOpDescriptor(
01450                                     0, 
01451                                     _R(IDS_ZOOMIN),
01452                                     CC_RUNTIME_CLASS(OpZoomIn), 
01453                                     OPTOKEN_ZOOMIN,
01454                                     OpZoomIn::GetState,
01455                                     0,  /* help ID */
01456                                     0,  /* bubble ID */
01457                                     0   /* bitmap ID */
01458                                     );
01459     return ok;
01460 }
01461 
01462 /***********************************************************************************************
01463 
01464 >   static OpState OpZoomIn::GetState(String_256* Description, OpDescriptor*)
01465 
01466     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01467     Created:    26/3/97
01468     Inputs:     Description = ptr to place description of why this op can't happen
01469                 pOpDesc     = ptr to the Op Desc associated with this op
01470     Outputs:    -
01471     Returns:    An OpState object
01472     Purpose:    Func for determining the usability of this op
01473     SeeAlso:    -
01474         
01475 ***********************************************************************************************/
01476 OpState OpZoomIn::GetState(String_256* Description, OpDescriptor*)
01477 {
01478     OpState State;
01479     return State;
01480 }
01481 
01482 /********************************************************************************************
01483 
01484 >   virtual void OpZoomIn::Do(OpDescriptor* pOpDesc)
01485 
01486     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01487     Created:    19/11/00
01488     Inputs:     pointer to the OpZoomDescriptor being invoked
01489     Purpose:    Calls the base class function to zoom in!
01490 
01491 ********************************************************************************************/
01492 void OpZoomIn::Do(OpDescriptor *pOpDesc)
01493 {
01494     // Ok! lets zoom in!
01495     DocView* pDocView = DocView::GetCurrent();
01496 
01497     if(pDocView)
01498     {
01499         const WorkRect ZoomRect = pDocView->GetViewRect();
01500         ZoomIn(ZoomRect.Centre());
01501     }
01502     else
01503     {
01504         ERROR3IF(pDocView == 0, "No current DocView found!");
01505     }
01506 }
01507 
01509 // class OpZoomOut
01510 OpZoomOut::OpZoomOut()
01511 {
01512 }
01513 
01514 BOOL OpZoomOut::Init()
01515 {
01516     BOOL ok = RegisterOpDescriptor(
01517                                     0, 
01518                                     _R(IDS_ZOOMOUT),
01519                                     CC_RUNTIME_CLASS(OpZoomOut), 
01520                                     OPTOKEN_ZOOMOUT,
01521                                     OpZoomOut::GetState,
01522                                     0,  /* help ID */
01523                                     0,  /* bubble ID */
01524                                     0   /* bitmap ID */
01525                                     );
01526     return ok;
01527 }
01528 
01529 /***********************************************************************************************
01530 
01531 >   static OpState OpZoomOut::GetState(String_256* Description, OpDescriptor*)
01532 
01533     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01534     Created:    26/3/97
01535     Inputs:     Description = ptr to place description of why this op can't happen
01536                 pOpDesc     = ptr to the Op Desc associated with this op
01537     Outputs:    -
01538     Returns:    An OpState object
01539     Purpose:    Func for determining the usability of this op
01540     SeeAlso:    -
01541         
01542 ***********************************************************************************************/
01543 OpState OpZoomOut::GetState(String_256* Description, OpDescriptor*)
01544 {
01545     OpState State;
01546     return State;
01547 }
01548 
01549 /********************************************************************************************
01550 
01551 >   virtual void OpZoomOut::Do(OpDescriptor* pOpDesc)
01552 
01553     Author:     Mark_Howitt (Xara Group Ltd) <camelotdev@xara.com>
01554     Created:    19/11/00
01555     Inputs:     pointer to the OpZoomDescriptor being invoked
01556     Purpose:    Calls the base class function to zoom Out!
01557 
01558 ********************************************************************************************/
01559 void OpZoomOut::Do(OpDescriptor *pOpDesc)
01560 {
01561     // Ok! lets zoom Out!
01562     DocView* pDocView = DocView::GetCurrent();
01563 
01564     if(pDocView)
01565     {
01566         const WorkRect ZoomRect = pDocView->GetViewRect();
01567         ZoomOut(ZoomRect.Centre());
01568     }
01569     else
01570     {
01571         ERROR3IF(pDocView == 0, "No current DocView found!");
01572     }
01573 }
01574 
01576 // class OpZoomDescriptor
01577 
01578 /********************************************************************************************
01579 >   OpZoomDescriptor::OpZoomDescriptor(const TCHAR* pcszToken, UINT32 wStatusID,
01580                                        UINT32 wHelpID, UINT32 wBubbleID,
01581                                        UINT32 resourceID=0, UINT32 controlID=0)
01582 
01583     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01584     Created:    26/5/94
01585     Inputs:     pcszToken       the "token" (OLE verb?) of the associated Operation
01586                 wStatusID       string resource ID of status-bar text
01587                 wHelpID         string ID of help text/jump (?)
01588                 wBubbleID       string ID of bubble-help text
01589     Outputs:    -
01590     Returns:    -
01591     Purpose:    Constructs the base class of the OpZoom's OpDescriptors
01592     Errors:     -
01593     SeeAlso:    class OpZoomFitSpreadDescriptor; class OpZoomFitDrawingDescriptor;
01594                 class OpZoomFitSelectedDescriptor; class OpZoomPrevZoomDescriptor
01595 ********************************************************************************************/
01596 
01597 OpZoomDescriptor::OpZoomDescriptor(const TCHAR* pcszToken, UINT32 wStatusID,
01598                                    UINT32 wHelpID, UINT32 wBubbleID, UINT32 resourceID, UINT32 controlID)
01599   : OpDescriptor(0,                                 // tool ID
01600                  wStatusID,                         // string ID of text in status bar
01601                  CC_RUNTIME_CLASS(OpZoom),
01602                  (TCHAR*) pcszToken,
01603                  GetState,
01604                  wHelpID,                           // help link ID
01605                  wBubbleID,                         // bubble help string ID
01606                  resourceID,
01607                  controlID,
01608                  TRUE)                              // wants to receive messages
01609 {
01610     // Empty.
01611 }
01612 
01613 
01614 
01615 /********************************************************************************************
01616 >   static OpState OpZoomDescriptor::GetState(String_256* pDesc, OpDescriptor* pOpDesc)
01617 
01618     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01619     Created:    23/4/95
01620     Inputs:     pDesc       --- A pointer to a String. GetState fills this with the
01621                                 appropriate details for the conditions arising eg. why
01622                                 "Previous Zoom" is greyed out.
01623                 pOpDesc     --- A pointer to the OpDescriptor whose state is being
01624                                 queried.
01625     Returns:    An OpState containing the flags that show what is valid.
01626     Purpose:    Returns the state that this zoom operation should appear in the menus 
01627                 or as a buttom, for example - greyed out, or ticked.
01628     SeeAlso:    OpZoomDescriptor::IsAvailable
01629 ********************************************************************************************/
01630 
01631 OpState OpZoomDescriptor::GetState(String_256*, OpDescriptor* pOpDesc)
01632 {
01633     BOOL fCanDo = ((OpZoomDescriptor*) pOpDesc)->IsAvailable();
01634 /*  TRACEUSER( "JustinF", _T("OpZoomDescriptor::GetState for %-12s (0x%lX) - %-8s at %lu ms\n"),
01635                             (LPCTSTR)   pOpDesc->Token,
01636                             (UINT32)        pOpDesc,
01637                             (LPCTSTR)   (fCanDo ? TEXT("OK") : TEXT("Greyed")),
01638                             (UINT32)        ::GetTickCount());
01639 */  return OpState(FALSE, !fCanDo);
01640 }
01641 
01642 
01643 
01644 /********************************************************************************************
01645 >   virtual BOOL OpZoomDescriptor::IsAvailable()
01646 
01647     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01648     Created:    26/5/94
01649     Inputs:     -
01650     Outputs:    -
01651     Returns:    TRUE if the Operation is available.  By default this returns TRUE if there
01652                 is a "selected" document, a spread, and a rectangle to zoom in on.
01653     Purpose:    Default "GetState"-like function for OpZoomDescriptor derivatives.
01654     Errors:     -
01655     SeeAlso:    OpZoom::GetState; DocView::GetSelected; OpState::OpState;
01656                 OpZoomDescriptor::GetSpread; OpZoomDescriptor::GetRect
01657 ********************************************************************************************/
01658 
01659 BOOL OpZoomDescriptor::IsAvailable()
01660 {
01661     // Try to get the "selected" view.
01662     DocView* pDocView = DocView::GetCurrent();
01663     if (pDocView == 0)
01664     {
01665 //      TRACEUSER( "JustinF", _T("\tNo current DocView in OpZoomDescriptor::IsAvailable\n"));
01666         return FALSE;
01667     }
01668 
01669     // Find the relevant spread, if any.
01670     Spread* pSpread = GetSpread(pDocView);
01671     if (pSpread == 0)
01672     {
01673 //      TRACEUSER( "JustinF", _T("\tNo relevant spread in OpZoomDescriptor::IsAvailable\n"));
01674         return FALSE;
01675     }
01676 
01677     DocRect ZoomRect = GetRect(pSpread);
01678     BOOL Empty = ZoomRect.IsEmpty();
01679 #ifdef _DEBUG
01680     // Is there actually no relevant rectangle within the spread to zoom on?
01681     if (Empty)
01682     {
01683 //      TRACEUSER( "JustinF", _T("\tEmpty rectangle in OpZoomDescriptor::IsAvailable\n"));
01684     }                                                                                 
01685 #endif
01686 
01687     // Find the relevant zoom rectangle, if any.
01688     return !Empty;
01689 }
01690 
01691 
01692 
01693 /********************************************************************************************
01694 >   virtual MsgResult OpZoomDescriptor::Message(Msg* pMsg)
01695 
01696     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01697     Created:    26/5/94
01698     Inputs:     -
01699     Outputs:    -
01700     Returns:    -
01701     Purpose:    Default message despatcher for OpZoomDescriptor derivatives.  Passes
01702                 button messages to HandleButtonMsg (virtual).
01703     Errors:     -
01704     SeeAlso:    OpZoomDescriptor::HandleButtonMsg
01705 ********************************************************************************************/
01706 
01707 MsgResult OpZoomDescriptor::Message(Msg* pMsg)
01708 {
01709     // Check if the message is an OpDesc message.
01710     if (!MESSAGE_IS_A(pMsg, OpDescMsg)) return OK;
01711     
01712     // Cast it into the correct type etc.
01713     OpDescMsg* pOpDescMsg = (OpDescMsg*) pMsg;
01714     
01715     // Process the message . . .
01716     if (pOpDescMsg->OpDesc == this && MESSAGE_IS_A(pOpDescMsg, OpDescControlMsg))
01717     {
01718         // Cast to a control message, unpack, and despatch to the handler.
01719         OpDescControlMsg* pControlMsg = (OpDescControlMsg*) pOpDescMsg;
01720         if (pControlMsg->DlgMsg == DIM_LFT_BN_CLICKED)
01721         {
01722             if (IsAvailable())
01723                 return HandleButtonMsg(pControlMsg->pDlgOp, pOpDescMsg->SetGadgetID);
01724 #if !defined(EXCLUDE_FROM_RALPH)
01725             else
01726 //              Beep();
01727                 wxBell();
01728 #endif
01729         }
01730     }
01731 
01732     // Let the base class do its stuff on the message.
01733     return OpDescriptor::Message(pMsg);
01734 }
01735 
01736 
01737 
01738 /********************************************************************************************
01739 >   virtual BOOL OpZoomDescriptor::DoZoom(OpZoom * pOpZoom)
01740 
01741     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01742     Created:    21/9/95
01743     Inputs:     pZoomOp     pointer to the OpZoom to be used
01744     Returns:    True if operation has happened correctly
01745     Purpose:    Is the base zoom descriptor class function for performing a zoom operation.
01746                 It does this by calling (virtual) GetSpread to find the spread to zoom in on,
01747                 then (virtual) GetRect to find the rectangle within the spread. The (virtual)
01748                 function AdjustRect is called to modify the resultant rectangle. Derived
01749                 classes can override these functions to customise the effects of particular
01750                 zoom operation.
01751                 Performs the zoom, after saving the current zoom settings, then updates
01752                 the zoom combo box.
01753                 Similar button to HandleButtonMsg but is designed to be called by the Do()
01754                 operator in OpZoom and hence from keyboard short-cuts or menu operations.
01755     Errors:     -
01756     SeeAlso:    OpZoom::Do;
01757                 OpZoomDescriptor::GetSpread; OpZoomDescriptor::GetRect;
01758                 OpZoomDescriptor::AdjustRect
01759 ********************************************************************************************/
01760 
01761 BOOL OpZoomDescriptor::DoZoom(OpZoom* pZoomOp)
01762 {
01763     ERROR2IF(pZoomOp == 0, FALSE, "OpZoomDescriptor::DoZoom called with no operation");
01764 
01765     // Get the current view.
01766     DocView* pDocView = DocView::GetCurrent();
01767     ERROR3IF(pDocView == 0, "No current DocView in OpZoomDescriptor::HandleButtonMsg");
01768     if (pDocView == 0)
01769         return FAIL;
01770         
01771     // Find the relevant spread, if any.
01772     Spread* pSpread = GetSpread(pDocView);
01773     ERROR3IF(pSpread == 0, "No relevant spread - can't do zoom\n");
01774     if (pSpread == 0)
01775         return FAIL;
01776 
01777     // Find the relevant zoom rectangle.
01778     DocRect drBounds = GetRect(pSpread);
01779     ERROR3IF(drBounds.IsEmpty(), "Relevant rectangle is empty - can't do zoom\n");
01780 
01781     // Allow derived class to adjust the document rectangle if it so desires.
01782     AdjustRect(&drBounds);
01783 
01784     // Do the zoom, the scaling factor of which will not appear in the zoom op's table.
01785     pZoomOp->ZoomInOnRect(pSpread, drBounds);
01786 
01787     return TRUE;    
01788 }
01789 
01790 
01791 
01792 /********************************************************************************************
01793 >   virtual MsgResult OpZoomDescriptor::HandleButtonMsg(DialogOp* pdlgop, CGadgetID gid)
01794 
01795     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01796     Created:    26/5/94
01797     Inputs:     pdlgop          pointer to the dialog operation ("unpacked" from a message)
01798                 gid             the gadget ID associated with this OpDescriptor
01799     Outputs:    -
01800     Returns:    The message result code (either EAT_MSG or OK)
01801     Purpose:    Handles a button click message, by calling (virtual) GetSpread to find the
01802                 spread to zoom in on, then (virtual) GetRect to find the rectangle within
01803                 the spread.  The (virtual) function AdjustRect is called to modify the
01804                 resultant rectangle.  Derived classes can override these functions to
01805                 customise the effects of particular buttons.  Performs the zoom, after
01806                 saving the current zoom settings, then updates the zoom combo box.
01807     Errors:     -
01808     SeeAlso:    OpZoomDescriptor::GetSpread; OpZoomDescriptor::GetRect;
01809                 OpZoomDescriptor::AdjustRect
01810 ********************************************************************************************/
01811 
01812 MsgResult OpZoomDescriptor::HandleButtonMsg(DialogOp*, CGadgetID)
01813 {
01814     // Try to create an instance of the zoom operation.
01815     OpZoom* pZoomOp = new OpZoom;
01816     ERRORIF(pZoomOp == 0, _R(IDE_NOMORE_MEMORY), FAIL);
01817 
01818     // Do the zoom, the scaling factor of which will not appear in the zoom op's table.
01819     // DoZoom will End the operation
01820     BOOL ok = DoZoom(pZoomOp);
01821     if (!ok) return FAIL;
01822     return OK;
01823 }
01824 
01825 
01826 
01827 /********************************************************************************************
01828 >   virtual Spread* OpZoomDescriptor::GetSpread(DocView* pDocView) const
01829 
01830     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01831     Created:    26/5/94
01832     Inputs:     pDocView        the DocView containing the spread.
01833     Outputs:    -
01834     Returns:    A pointer to the relevant spread to zoom in on.  By default this is the
01835                 document page, ie. the first spread in the document.
01836     Purpose:    Gets a spread given a DocView.
01837     Errors:     -
01838     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; View::GetDoc; Document::FindFirstSpread
01839 ********************************************************************************************/
01840 
01841 Spread* OpZoomDescriptor::GetSpread(DocView* pDocView) const
01842 {
01843 PORTNOTE("spread", "Multi-spread warning!")
01844     return pDocView->GetDoc()->FindFirstSpread();
01845 }
01846 
01847 
01848 
01849 /********************************************************************************************
01850 >   virtual DocRect OpZoomDescriptor::GetRect(Spread* pSpread)
01851 
01852     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01853     Created:    26/5/94
01854     Inputs:     pSpread         the spread to zoom in on
01855     Outputs:    -
01856     Returns:    A rectangle within the spread to zoom in on.  By default this is the
01857                 "bounding rectangle" of the given spread.
01858     Purpose:    Gets a rectangle given a spread.
01859     Errors:     -
01860     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; Spread::GetBoundingRect
01861 ********************************************************************************************/
01862 
01863 DocRect OpZoomDescriptor::GetRect(Spread* pSpread)
01864 {
01865     return pSpread->GetBoundingRect();
01866 }
01867 
01868 
01869 
01870 /********************************************************************************************
01871 >   virtual void OpZoomDescriptor::AdjustRect(DocRect* pRect) const
01872 
01873     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01874     Created:    31/5/94
01875     Inputs:     pRect               pointer to a DocRect to adjust
01876     Outputs:    The adjusted DocRect.
01877     Returns:    -
01878     Purpose:    In the base class version inflates the given document rectangle by
01879                 5% in each direction.
01880     Errors:     -
01881     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; OpZoomDescriptor::GetRect
01882 ********************************************************************************************/
01883 
01884 void OpZoomDescriptor::AdjustRect(DocRect* pRect) const
01885 {
01886     INT32 xinc = pRect->Width() / 20;           // find 5% of the width and height
01887     INT32 yinc = pRect->Height() / 20;
01888     if (xinc < 1) xinc = 1;                     // make sure we inflate by some amount
01889     if (yinc < 1) yinc = 1;
01890     pRect->lo.x -= xinc;                        // inflate the given rectangle
01891     pRect->lo.y -= yinc;
01892     pRect->hi.x += xinc;
01893     pRect->hi.y += yinc;
01894 }
01895 
01896 
01897 
01898 /********************************************************************************************
01899 >   static void OpZoomDescriptor::FakeInvoke(TCHAR* pszToken)
01900 
01901     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01902     Created:    18/7/94
01903     Inputs:     pszToken    ---     pointer to the "invoked" OpDescriptor's token
01904     Outputs:    -
01905     Returns:    -
01906     Purpose:    "Fakes" a button message for OpDescriptor classes derived from
01907                 OpZoomDescriptor.  Searches for the OpDescriptor associated with the
01908                 specified token.  If it finds it then casts it to an OpZoomDescriptor*,
01909                 checks if the associated button isn't greyed, and if not, calls its
01910                 HandleButtonMsg function.  Finally it makes sure that the percentage
01911                 scale factor of the selected DocView is updated in the zoom combo box.
01912     Errors:     -
01913     SeeAlso:    OpZoomComboDescriptor::OnSelectionChanged
01914 ********************************************************************************************/
01915 
01916 void OpZoomDescriptor::FakeInvoke(TCHAR* pszToken)
01917 {
01918     // Try to find the OpDescriptor.
01919     OpZoomDescriptor* pZoomOpDesc = (OpZoomDescriptor*) FindOpDescriptor(pszToken);
01920     
01921     // If that worked then call its button handler.
01922     if (pZoomOpDesc != 0 && pZoomOpDesc->IsAvailable())
01923     {
01924         pZoomOpDesc->HandleButtonMsg(0, 0);
01925     }
01926 #ifndef RALPH
01927     else
01928     {
01929         // If it didn't then refresh the zoom combo with some percentages.
01930 //      Beep();
01931         wxBell();
01932         OpZoomComboDescriptor::Update();
01933     }
01934 #endif
01935 }
01936 
01937 /********************************************************************************************
01938 
01939 >   static void OpZoomDescriptor::FakeZoomToRect(DocRect* pRect)
01940 
01941     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
01942     Created:    13/9/96
01943     Inputs:     pRect, pointer to a rect to zoom to
01944     Outputs:    -
01945     Returns:    -
01946     Purpose:    "Fakes" a button message for the ZoomRect OpDescriptor, using the specified,
01947                 rectangle.
01948     Errors:     -
01949 
01950 ********************************************************************************************/
01951 
01952 void OpZoomDescriptor::FakeZoomToRect(const DocRect& rect)
01953 {
01954     // Try to find the OpDescriptor.
01955     OpZoomDescriptor* pZoomOpDesc = (OpZoomDescriptor*) FindOpDescriptor(OPTOKEN_ZOOMRECT);
01956     
01957     // If that worked then call its button handler.
01958     if (pZoomOpDesc != 0)
01959     {
01960         ((OpZoomFitRectDescriptor*) pZoomOpDesc)->SetZoomRect(rect);
01961         pZoomOpDesc->HandleButtonMsg(0, 0);
01962     }
01963 }
01964 
01966 // class OpZoomFitSpreadDescriptor
01967 
01968 /********************************************************************************************
01969 >   OpZoomFitSpreadDescriptor::OpZoomFitSpreadDescriptor()
01970 
01971     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01972     Created:    26/5/94
01973     Inputs:     -
01974     Outputs:    -
01975     Returns:    -
01976     Purpose:    Constructs an OpDescriptor for the "Zoom to spread" button.
01977     Errors:     -
01978     SeeAlso:    class OpZoomDescriptor
01979 ********************************************************************************************/
01980 
01981 OpZoomFitSpreadDescriptor::OpZoomFitSpreadDescriptor()
01982   : OpZoomDescriptor(OPTOKEN_ZOOMSPREAD, _R(IDS_ZOOMSPREADSTATUSTEXT),
01983                      0, _R(IDBBL_FIT_TO_SPREAD))
01984 {
01985     // default to always scaling in AdjustRect
01986     m_DontScale = TRUE;
01987 }
01988 
01989 
01990 
01991 /********************************************************************************************
01992 >   virtual DocRect OpZoomFitSpreadDescriptor::GetRect(Spread* pSpread)
01993 
01994     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
01995     Created:    26/5/94
01996     Inputs:     pSpread         pointer to a spread
01997     Outputs:    -
01998     Returns:    The "page bounds" of the given spread.
01999     Purpose:    Provides the rectangle that OpZoomDescriptor::HandleButtonMsg will
02000                 zoom in on.
02001     Errors:     -
02002     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; OpZoomFitSpreadDescriptor::AdjustRect;
02003                 Spread::GetPageBounds
02004 ********************************************************************************************/
02005 
02006 DocRect OpZoomFitSpreadDescriptor::GetRect(Spread* pSpread)
02007 {
02008 /*
02009 #ifdef _DEBUG
02010     if (IsUserName("JustinF"))
02011     {
02012         static DocRect drOld = pSpread->GetPageBounds();
02013         DocRect drNew = pSpread->GetPageBounds();
02014         
02015         if (drNew != drOld)
02016         {
02017             TRACE( _T("In OpZoomFitSpreadDesriptor - Spread::GetPageBounds has changed!\n")
02018                   "\t- drOld is %ld x %ld\n\t- drNew is %ld x %ld\n",
02019                     (INT32) drOld.Width(), (INT32) drOld.Height(),
02020                     (INT32) drNew.Width(), (INT32) drNew.Height());
02021         }
02022                 
02023         return drOld = drNew;
02024     }
02025 #endif
02026 */
02027     // These are both in Document coords not spread coords!
02028     DocRect SpreadSize = pSpread->GetPageBounds();
02029     DocRect PasteBoardSize = pSpread->GetPasteboardRect(FALSE);
02030     // If the two sizes are the same then this means we have a zero sized pasteboard
02031     // In this case, we should not try and scale up the resulting rectangle in AdjustRect
02032     // So note this state for later use.
02033     // Cannot do a straight equality check as we will have rounding errors.
02034     const MILLIPOINT delta = 1000;
02035     if (
02036         (SpreadSize.lo.x > PasteBoardSize.lo.x - delta) && (SpreadSize.lo.x < PasteBoardSize.lo.x + delta) &&
02037         (SpreadSize.hi.x > PasteBoardSize.hi.x - delta) && (SpreadSize.hi.x < PasteBoardSize.hi.x + delta) &&
02038         (SpreadSize.lo.y > PasteBoardSize.lo.y - delta) && (SpreadSize.lo.y < PasteBoardSize.lo.y + delta) &&
02039         (SpreadSize.hi.y > PasteBoardSize.hi.y - delta) && (SpreadSize.hi.y < PasteBoardSize.hi.y + delta)
02040        )
02041     {
02042         m_DontScale = FALSE;
02043     }
02044     else
02045     {
02046         m_DontScale = TRUE;
02047     }
02048 
02049     return SpreadSize;
02050 }
02051 
02052 
02053 
02054 /********************************************************************************************
02055 >   virtual void OpZoomFitSpreadDescriptor::AdjustRect(DocRect* pRect) const
02056 
02057     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02058     Created:    9/2/95
02059     Inputs:     pRect               pointer to a DocRect to adjust
02060     Outputs:    The adjusted DocRect.
02061     Returns:    -
02062     Purpose:    Override the base class version of the fcuntion which inflates the given
02063                 document rectangle by 5% in each direction for one which inflates it by 2%.
02064     Errors:     -
02065     SeeAlso:    OpZoomDescriptor::AdjustRect; OpZoomDescriptor::GetRect
02066 ********************************************************************************************/
02067 
02068 void OpZoomFitSpreadDescriptor::AdjustRect(DocRect* pRect) const
02069 {
02070     if (m_DontScale)
02071     {
02072         INT32 xinc = pRect->Width() / 50;           // find 2% of the width and height
02073         INT32 yinc = pRect->Height() / 50;
02074         if (xinc < 1) xinc = 1;                     // make sure we inflate by some amount
02075         if (yinc < 1) yinc = 1;
02076         pRect->lo.x -= xinc;                        // inflate the given rectangle
02077         pRect->lo.y -= yinc;
02078         pRect->hi.x += xinc;
02079         pRect->hi.y += yinc;
02080     }
02081 }
02082 
02083 
02084 
02086 // class OpZoomFitDrawingDescriptor
02087 
02088 /********************************************************************************************
02089 >   OpZoomFitDrawingDescriptor::OpZoomFitDrawingDescriptor()
02090 
02091     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02092     Created:    26/5/94
02093     Inputs:     -
02094     Outputs:    -
02095     Returns:    -
02096     Purpose:    Constructs an OpDescriptor for the "Zoom to drawing" button.
02097     Errors:     -
02098     SeeAlso:    class OpZoomDescriptor
02099 ********************************************************************************************/
02100 
02101 OpZoomFitDrawingDescriptor::OpZoomFitDrawingDescriptor()
02102   : OpZoomDescriptor(OPTOKEN_ZOOMDRAWING, _R(IDS_ZOOMDRAWINGSTATUSTEXT),
02103                      0, _R(IDBBL_FIT_TO_DRAWING))
02104 {
02105     // Empty.
02106 }
02107 
02108 
02109 
02110 /********************************************************************************************
02111 >   virtual DocRect OpZoomFitDrawingDescriptor::GetRect(Spread* pSpread)
02112 
02113     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02114     Created:    26/5/94
02115     Inputs:     pSpread         pointer to a spread
02116     Outputs:    -
02117     Returns:    The "bounds" of the drawing on the given spread, ignoring invisible
02118                 layers.
02119     Purpose:    Provides the rectangle that OpZoomDescriptor::HandleButtonMsg will
02120                 zoom in on.
02121     Errors:     -
02122     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; OpZoomFitSpreadDescriptor::AdjustRect;
02123                 Spread::GetPageVisibleBounds
02124 ********************************************************************************************/
02125 
02126 DocRect OpZoomFitDrawingDescriptor::GetRect(Spread* pSpread)
02127 {
02128     return pSpread->GetPageVisibleBounds();
02129 }
02130 
02131 
02132 
02134 // class OpZoomFitSelectedDescriptor
02135 
02136 /********************************************************************************************
02137 >   OpZoomFitSelectedDescriptor::OpZoomFitSelectedDescriptor()
02138 
02139     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02140     Created:    26/5/94
02141     Inputs:     -
02142     Outputs:    -
02143     Returns:    -
02144     Purpose:    Constructs an OpDescriptor for the "Zoom to selected objects" button.
02145     Errors:     -
02146     SeeAlso:    class OpZoomDescriptor
02147 ********************************************************************************************/
02148 
02149 OpZoomFitSelectedDescriptor::OpZoomFitSelectedDescriptor()
02150   : OpZoomDescriptor(OPTOKEN_ZOOMSELECTED, _R(IDS_ZOOMSELECTEDSTATUSTEXT),
02151                      0, _R(IDBBL_FIT_TO_SELECTED))
02152 {
02153     // Empty.
02154 }
02155 
02156 
02157 
02158 /********************************************************************************************
02159 >   virtual Spread* OpZoomFitSelectedDescriptor::GetSpread(DocView* pDocView) const
02160 
02161     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02162     Created:    26/5/94
02163     Inputs:     pDocView        pointer to a DocView showing selected objects
02164     Outputs:    -
02165     Returns:    A pointer to the first spread within the viewed document that
02166                 contains selected objects.
02167     Purpose:    Provides the spread that OpZoomDescriptor::HandleButtonMsg will zoom
02168                 in on.
02169     Errors:     -
02170     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; DocView::GetFirstSelectedSpread
02171 ********************************************************************************************/
02172 
02173 Spread* OpZoomFitSelectedDescriptor::GetSpread(DocView* pDocView) const
02174 {
02175     return pDocView->GetFirstSelectedSpread();
02176 }
02177 
02178 
02179 
02180 /********************************************************************************************
02181 >   virtual DocRect OpZoomFitSelectedDescriptor::GetRect(Spread* pSpread)
02182 
02183     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02184     Created:    27/5/94
02185     Inputs:     pSpread             pointer to the spread containing the selection
02186     Outputs:    -
02187     Returns:    The bounding rectangle of the selected objects.
02188     Purpose:    Assuming that some objects are selected, this calculates the bounding
02189                 rectangle of the selected objects, including blobs.
02190     Errors:     ERROR2/3 failure if there isn't any selected objects - if this happens
02191                 then something is screwy, as SelRange immediately before reported
02192                 that there are selected objects, or this function wouldn't have been
02193                 called.
02194     SeeAlso:    OpZoomFitSelectedDescriptor::GetSpread; SelRange::GetBlobBoundingRect
02195 ********************************************************************************************/
02196 
02197 DocRect OpZoomFitSelectedDescriptor::GetRect(Spread* pSpread)
02198 {
02199     // If this function is called then we know that there is a valid selection
02200     // somewhere.
02201     SelRange* pSel = GetApplication()->FindSelection();
02202 
02203     // Doesn't do any harm to check, though!
02204     ERROR3IF(pSel == 0 || pSel->FindFirst() == 0,
02205                 "Can't find a selected node in OpZoomFitSelectedDescriptor::GetRect");
02206     ERROR3IF(pSpread != pSel->FindFirst()->FindParent(CC_RUNTIME_CLASS(Spread)),
02207                 "Spread pointer has changed between calls on SelRange");
02208     
02209     // We really need to call the equivalent of GetUnionBlobBoundingRect() for the SelRange,
02210     // but this function doesn't exist, so we mimic its result here.
02211     DocRect drSel = pSel->GetBlobBoundingRect().Union(pSel->GetBoundingRect());
02212 
02213     // And convert it into document coordinates
02214     pSpread->SpreadCoordToDocCoord(&drSel);
02215 
02216     // Return the bounding rectangle of the selection in "proper" document coordinates.
02217     return drSel;
02218 }
02219 
02220 
02221 
02222 /********************************************************************************************
02223 >   virtual void OpZoomFitSelectedDescriptor::AdjustRect(DocRect* pRect) const
02224 
02225     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02226     Created:    31/5/94
02227     Inputs:     pRect               pointer to a DocRect to adjust
02228     Outputs:    The adjusted DocRect.
02229     Returns:    -
02230     Purpose:    Inflates the given rectangle by the same amount as the selector tool when it
02231                 draws bounds blobs around the selection.  This ensures that after a "Fit to
02232                 Selected" zoom the bounds blobs of the zoomed object will be visible.
02233     Errors:     -
02234     SeeAlso:    OpZoomFitSelectedDescriptor::GetRect; SelectorTool::InflateByBlobBorder
02235 ********************************************************************************************/
02236 
02237 void OpZoomFitSelectedDescriptor::AdjustRect(DocRect* pRect) const
02238 {
02239 #ifndef STANDALONE
02240     SelectorTool::InflateByBlobBorder(pRect);
02241 #endif
02242 }
02243 
02244 
02246 // class OpZoomFitRectDescriptor
02247 
02248 /********************************************************************************************
02249 >   OpZoomFitRectDescriptor::OpZoomFitRectDescriptor()
02250 
02251     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02252     Created:    13/9/96
02253     Inputs:     -
02254     Outputs:    -
02255     Returns:    -
02256     Purpose:    Constructs an OpDescriptor for zooming to a specified rect.
02257     Errors:     -
02258     SeeAlso:    class OpZoomDescriptor
02259 ********************************************************************************************/
02260 
02261 OpZoomFitRectDescriptor::OpZoomFitRectDescriptor()
02262   : OpZoomDescriptor(OPTOKEN_ZOOMRECT, 0, 0, 0),
02263     TheRect(0, 0, 0, 0)
02264 {
02265     // Empty.
02266 }
02267 
02268 /********************************************************************************************
02269 
02270 >   void OpZoomFitRectDescriptor::SetZoomRect(const DocRect& rect)
02271 
02272     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02273     Created:    13/9/96
02274     Inputs:     pRect
02275     Outputs:    -
02276     Purpose:    Sets the rectangle that the op will zoom to.
02277     Errors:     -
02278 
02279 ********************************************************************************************/
02280 
02281 void OpZoomFitRectDescriptor::SetZoomRect(const DocRect& rect)
02282 {
02283     TheRect = rect;
02284 }
02285 
02286 /********************************************************************************************
02287 >   virtual DocRect OpZoomFitRectDescriptor::GetRect(Spread* pSpread)
02288 
02289     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
02290     Created:    13/9/96
02291     Inputs:     pSpread         pointer to a spread
02292     Outputs:    -
02293     Returns:    The "bounds" of the drawing on the given spread, ignoring invisible
02294                 layers.
02295     Purpose:    Provides the rectangle that OpZoomDescriptor::HandleButtonMsg will
02296                 zoom in on.
02297     Errors:     -
02298     SeeAlso:    OpZoomDescriptor::HandleButtonMsg; OpZoomFitSpreadDescriptor::AdjustRect;
02299                 Spread::GetPageVisibleBounds
02300 ********************************************************************************************/
02301 
02302 DocRect OpZoomFitRectDescriptor::GetRect(Spread* pSpread)
02303 {
02304     DocRect t = TheRect;
02305     // Convert the value from spread coordinates to document coords
02306     pSpread->SpreadCoordToDocCoord(&t);
02307 
02308     return t;
02309     //return TheRect;
02310 }
02311 
02312 
02314 // class OpZoomPrevZoomDescriptor
02315 
02316 /********************************************************************************************
02317 >   OpZoomPrevZoomDescriptor::OpZoomPrevZoomDescriptor()
02318 
02319     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02320     Created:    26/5/94
02321     Inputs:     -
02322     Outputs:    -
02323     Returns:    -
02324     Purpose:    Constructs an OpDescriptor for the "Previous zoom" button.
02325     Errors:     -
02326     SeeAlso:    class OpZoomDescriptor
02327 ********************************************************************************************/
02328 
02329 OpZoomPrevZoomDescriptor::OpZoomPrevZoomDescriptor()
02330   : OpZoomDescriptor(OPTOKEN_ZOOMPREV, _R(IDS_ZOOMPREVSTATUSTEXT), 0, _R(IDBBL_PREV_ZOOM))
02331 {
02332     // Empty.
02333 }
02334 
02335 
02336 
02337 /********************************************************************************************
02338 >   virtual BOOL OpZoomPrevZoomDescriptor::IsAvailable()
02339 
02340     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02341     Created:    26/5/94
02342     Inputs:     -
02343     Outputs:    -
02344     Returns:    TRUE if the "previous zoom" button is available
02345     Purpose:    Decides whether the "Previous zoom" button is enabled, which it is if
02346                 there is a "selected" DocView and at least one zoom has been performed
02347                 upon it.
02348     Errors:     -
02349     SeeAlso:    OpZoom::GetState; OpZoomDescriptor::IsAvailable
02350 ********************************************************************************************/
02351 
02352 BOOL OpZoomPrevZoomDescriptor::IsAvailable()
02353 {
02354     // Check for a selected DocView, if any (the base class IsAvailable does this), and
02355     // "grey" the button if it doesn't exist or hasn't been zoomed previously.
02356     DocView* pDocView = DocView::GetCurrent();
02357     return pDocView != 0 && pDocView->GetPrevZoomIndex() != cUninitZoomIndex;
02358 }
02359 
02360 
02361 
02362 /********************************************************************************************
02363 >   static void OpZoomPrevZoomDescriptor::SaveZoom(DocView* pDocView)
02364 
02365     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02366     Created:    26/5/94
02367     Inputs:     pDocView        the DocView whose current "zoom setting" is to be saved
02368     Outputs:    -
02369     Returns:    -
02370     Purpose:    Saves the given DocView's view-scale, scroll-offsets, and index into
02371                 OpZoom::ZoomTable.  Used by the "Previous zoom" button.  This function
02372                 is called by all zoom tool routines that perform a zoom.
02373     Errors:     -
02374     SeeAlso:    OpZoomPrevZoomDescriptor::HandleButtonMsg; DocView::SetPrevZoomIndex;
02375                 DocView::SetPrevZoomScale; DocView::SetPrevZoomOffset
02376 ********************************************************************************************/
02377 
02378 void OpZoomPrevZoomDescriptor::SaveZoom(DocView* pDocView)
02379 {
02380     // Save data about the current zoom.
02381     ERROR3IF(pDocView == 0, "No DocView in OpZoomPrevZoomDescriptor::SaveZoom");
02382     if (pDocView != 0)
02383     {
02384         pDocView->SetPrevZoomIndex(pDocView->GetZoomTableIndex());
02385         pDocView->SetPrevZoomScale(pDocView->GetViewScale());
02386         pDocView->SetPrevZoomOffset(pDocView->GetScrollOffsets());
02387     }
02388 
02389 #if !defined(EXCLUDE_FROM_RALPH)
02390     // Force the GetState function to be called again.
02391     DialogBarOp::SetSystemStateChanged();
02392 
02393     // If we have saved a "previous zoom" then there is a new zoom, hence the status-
02394     // bar text must have become invalid.
02395     ZoomTool::InvalidateStatusText();
02396 #endif
02397 }
02398 
02399 
02400 
02401 /********************************************************************************************
02402 >   virtual BOOL OpZoomPrevZoomDescriptor::DoZoom(OpZoom* pOpZoom)
02403 
02404     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02405     Created:    21/9/95
02406     Inputs:     pZoomOp     pointer to the OpZoom to be used, can be 0 for this.
02407     Returns:    True if operation has happened correctly
02408     Purpose:    Overrides the base zoom descriptor class function for performing a zoom
02409                 operation. This one is different as it just needs to invoke the previous zoom
02410                 that was in operation.
02411                 Performs the zoom, after saving the current zoom settings, then updates
02412                 the zoom combo box.
02413                 Similar button to HandleButtonMsg but is designed to be called by the Do()
02414                 operator in OpZoom and hence from keyboard short-cuts or menu operations.
02415     Errors:     -
02416     SeeAlso:    OpZoom::Do; OpZoomDescriptor::DoZoom;
02417                 OpZoomDescriptor::GetSpread; OpZoomDescriptor::GetRect;
02418                 OpZoomDescriptor::AdjustRect
02419 ********************************************************************************************/
02420 
02421 BOOL OpZoomPrevZoomDescriptor::DoZoom(OpZoom* pZoomOp)
02422 {
02423     // ZoomOp can be null.
02424 //  ERROR2IF(pZoomOp == 0, FALSE, "No operation in OpZoomPrevZoomDescriptor::DoZoom")
02425 
02426     // Get the selected DocView.
02427     DocView* pDocView = DocView::GetCurrent();
02428     ERROR2IF(pDocView == 0, FAIL, "No DocView in OpZoomPrevZoomDescriptor::HandleClickMsg");
02429 
02430     DialogBarOp::SetSystemStateChanged();
02431 
02432     // Record the current scale and scroll offset.
02433     INT32 nIndex = pDocView->GetZoomTableIndex();
02434     FIXED16 fxScale = pDocView->GetViewScale();
02435     WorkCoord wcOffset = pDocView->GetScrollOffsets();
02436     
02437     // Restore the previous scale factor and scroll offsets.
02438     pDocView->SetZoomTableIndex(pDocView->GetPrevZoomIndex());
02439     pDocView->SetViewScale(pDocView->GetPrevZoomScale());
02440     pDocView->SetScrollOffsets(pDocView->GetPrevZoomOffset(), FALSE);
02441 
02442     // Remember the "previous previous" zoom . . .
02443     pDocView->SetPrevZoomIndex(nIndex);
02444     pDocView->SetPrevZoomScale(fxScale);
02445     pDocView->SetPrevZoomOffset(wcOffset);
02446 
02447 #ifndef RALPH
02448     // Update the combo-box etc.
02449     OpZoomComboDescriptor::Update();
02450     ZoomTool::InvalidateStatusText();
02451 #endif
02452 
02453     // Finally, force a redraw and return the success code.
02454     pDocView->ForceRedraw(TRUE);
02455     
02456     // End the operation as we have finished
02457     if (pZoomOp)
02458         pZoomOp->End();
02459     
02460     // tell people things have changed on screen
02461     TRACEUSER( "Diccon", _T("DoZoom\n"));
02462     BROADCAST_TO_ALL(ScreenChangeMsg(TRUE));
02463     return TRUE;    
02464 }
02465 
02466 /********************************************************************************************
02467 >   virtual MsgResult OpZoomPrevZoomDescriptor::HandleButtonMsg(DialogOp*, CGadgetID)
02468 
02469     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02470     Created:    26/5/94
02471     Inputs:     (not used, see OpZoomDescriptor::HandleButtonMsg)
02472     Outputs:    -
02473     Returns:    The message result code (always OK)
02474     Purpose:    Responds to a click on the "Previous zoom" button by reading the
02475                 saved zoom parameters in the "selected" DocView, if any, and resetting
02476                 the DocView to them.
02477     Errors:     -
02478     SeeAlso:    OpZoomPrevZoomDescriptor::SaveZoom; DocView::SetZoomTableIndex;
02479                 DocView::SetPrevZoomIndex; DocView::SetPrevZoomOffset;
02480                 DocView::SetPrevZoomScale
02481 ********************************************************************************************/
02482 
02483 MsgResult OpZoomPrevZoomDescriptor::HandleButtonMsg(DialogOp*, CGadgetID)
02484 {
02485     // Just call the DoZoom operator but with 0 as we have no valid operation
02486     return DoZoom(0) ? OK : FAIL;
02487 }
02488 
02489 
02490 
02492 // class OpZoomComboDescriptor
02493 
02494 /********************************************************************************************
02495 >   OpZoomComboDescriptor::OpZoomComboDescriptor()
02496 
02497     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02498     Created:    26/5/94
02499     Inputs:     -
02500     Outputs:    -
02501     Returns:    -
02502     Purpose:    Constructs an OpDescriptor for the zoom control's combo-box, which
02503                 contains a list of percentage zoom factors.
02504     Errors:     -
02505     SeeAlso:    class OpZoomDescriptor
02506 ********************************************************************************************/
02507 
02508 OpZoomComboDescriptor::OpZoomComboDescriptor()
02509   : OpZoomDescriptor(OPTOKEN_ZOOMCOMBO, _R(IDS_ZOOMCOMBOSTATUSTEXT), 0, _R(IDBBL_ZOOM_COMBO), _R(IDCB_ZOOM_COMBO_BOX), _R(IDCB_ZOOM_COMBO_BOX))
02510 {
02511     
02512     // Empty.
02513 }
02514 
02515 
02516 
02517 /********************************************************************************************
02518 >   BOOL OpZoomComboDescriptor::IsAvailable()
02519 
02520     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02521     Created:    20/7/94
02522     Inputs:     -
02523     Outputs:    -
02524     Returns:    TRUE if the zoom combo is available for use, FALSE otherwise.
02525     Purpose:    Checks if their is a "selected" DocView, if so you can use the zoom combo
02526                 on it.
02527     Errors:     -
02528     SeeAlso:    OpZoom::GetState; OpZoomDescriptor::IsAvailable
02529 ********************************************************************************************/
02530 
02531 BOOL OpZoomComboDescriptor::IsAvailable()
02532 {
02533     return DocView::GetSelected() != 0;
02534 }
02535 
02536 
02537 
02538 /********************************************************************************************
02539 >   virtual MsgResult OpZoomComboDescriptor::Message(Msg* pMsg)
02540 
02541     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02542     Created:    26/5/94
02543     Inputs:     pMsg            a pointer to a kernel message to process
02544     Outputs:    -
02545     Returns:    A message result code (generally OK)
02546     Purpose:    Despatches a message, if relevant to the appropriate handler for it,
02547                 after "unpacking" it into a more useful form.
02548     Errors:     -
02549     SeeAlso:    OpZoomComboDescriptor::HandleViewChangeMsg;
02550                 OpZoomComboDescriptor::HandleCreateMsg;
02551                 OpZoomComboDescriptor::HandleSelectMsg;
02552                 class DocViewMsg
02553 ********************************************************************************************/
02554 
02555 MsgResult OpZoomComboDescriptor::Message(Msg* pMsg)
02556 {
02557     // Does the message mean that something has happened to the DocView?
02558     if (MESSAGE_IS_A(pMsg, DocViewMsg))
02559     {
02560         DocViewMsg* pViewMsg = (DocViewMsg*) pMsg;
02561         switch (pViewMsg->State)
02562         {
02563             case DocViewMsg::BORN:
02564                 // Initialise our data in the DocView when it is constructed.
02565                 pViewMsg->pDocView->SetZoomTableIndex(cDefaultZoomIndex);
02566                 pViewMsg->pDocView->SetPrevZoomIndex(cUninitZoomIndex);
02567                 return OK;
02568 
02569             case DocViewMsg::SELCHANGED:
02570                 // Handle the selected view changing.
02571                 return HandleViewChangeMsg(pViewMsg->pNewDocView);
02572 
02573             case DocViewMsg::SCALECHANGED:
02574                 // Handle the scale being changed. Since it can be set to anything,
02575                 // say that it is fractional so the field is updated properly.
02576                 pViewMsg->pDocView->SetZoomTableIndex(cFractionalZoomIndex);
02577                 return HandleViewChangeMsg(pViewMsg->pDocView);
02578 
02579             default:
02580                 // Ignore all other messages.
02581                 return OK;
02582         }
02583     }
02584 
02585     // If we have dropped down the combo-box - make sure it is upto date!
02586     if (MESSAGE_IS_A(pMsg, OpDescControlMsg))
02587     {
02588         OpDescControlMsg* pOpDescControlMsg = (OpDescControlMsg*) pMsg;
02589 
02590         if (pOpDescControlMsg->DlgMsg == DIM_LISTDROPPED)
02591         {
02592             if (DocView::GetCurrent() != 0)
02593             {
02594 // We really don't want the name gallery to have any effect on the zoom dropdown...
02595 //              CreateDisplayScan().Scan();
02596                 Update(TRUE);
02597             }
02598         }
02599     }
02600 
02601     // Check if the message is an OpDesc message.
02602     if (!MESSAGE_IS_A(pMsg, OpDescMsg)) return OK;
02603     
02604     // Cast it into the correct type etc.
02605     OpDescMsg* pOpDescMsg = (OpDescMsg*) pMsg;
02606         
02607     // Is it for us?
02608     if (pOpDescMsg->OpDesc != this) return OK;
02609     
02610 
02611 
02612     // Process the message . . .
02613     if (MESSAGE_IS_A(pOpDescMsg, OpDescControlCreateMsg))
02614         return HandleCreateMsg(pOpDescMsg->pDlgOp, pOpDescMsg->SetGadgetID);
02615 
02616     // Let base class do the default.
02617     return OpZoomDescriptor::Message(pMsg);
02618 }
02619 
02620 
02621 
02622 /********************************************************************************************
02623 >   MsgResult OpZoomComboDescriptor::HandleViewChangeMsg(DocView* pSelectedDocView)
02624 
02625     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02626     Created:    26/5/94
02627     Inputs:     pSelectedDocView        points to the DocView that is now "selected",
02628                                         or 0 if there isn't a selected view.
02629     Returns:    A message result code (always OK)
02630     Purpose:    Updates the zoom control combo-box with the zoom factor of a DocView
02631                 as the user moves from view to view.
02632     Errors:     Out of memory
02633     SeeAlso:    OpZoomComboDescriptor::UpdateComboWithViewScale;
02634                 OpZoomComboDescriptor::Message
02635 ********************************************************************************************/
02636 
02637 MsgResult OpZoomComboDescriptor::HandleViewChangeMsg(DocView* pSelectedDocView)
02638 {
02639 #if !defined(EXCLUDE_FROM_RALPH)
02640     ZoomTool::InvalidateStatusText();
02641     String_256 dummy;
02642     return (pSelectedDocView != 0 
02643                 // There is a new view, so set the combos to the scale factor.
02644                 ? UpdateComboWithViewScale(pSelectedDocView)
02645                 // There is no view, so blank the zoom combos.
02646                 : UpdateAllCombos(&dummy))
02647                         ? OK : FAIL;
02648 #else
02649     return OK;
02650 #endif
02651 }
02652 
02653 
02654 
02655 /********************************************************************************************
02656 >   BOOL OpZoomComboDescriptor::UpdateAllCombos(String_256* pStr)
02657 
02658     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02659     Created:    26/5/94
02660     Inputs:     pStr            the text to be placed in all zoom combos
02661     Returns:    TRUE if successful.
02662     Errors:     Out of memory
02663     Purpose:    Updates the zoom combo-box(es) with the given text.  The function is
02664                 complicated by design deficiencies in the Operation system!
02665     Errors:     -
02666     SeeAlso:    OpDescriptor::BuildGadgetList; DocView::GetZoomTableIndex
02667 ********************************************************************************************/
02668 
02669 BOOL OpZoomComboDescriptor::UpdateAllCombos(String_256* pStr)
02670 {
02671 #if !defined(EXCLUDE_FROM_RALPH)
02672     // We must set the combos to something!
02673     ERROR3IF(pStr == 0, "No parameter in OpZoomComboDescriptor::UpdateAllCombos");
02674 
02675     // Create a list for the dialogue manager to put gadget ID's on.
02676     List* pGadgetList = new List;
02677     ERRORIF(pGadgetList == 0, _R(IDE_NOMORE_MEMORY), FALSE);
02678 
02679     // See if the dialogue manager can remember where its controls live, or even
02680     // what identifiers they possess . . .
02681     if (BuildGadgetList(pGadgetList))
02682     {   
02683         // Success.  Walk the generated list
02684         ListItem* pListItem = pGadgetList->GetHead();
02685         while (pListItem != 0)
02686         {
02687             // Set the edit field of each gadget (which according to Simon will all be
02688             // combo-boxes) to the given percentage text.
02689             GadgetListItem* pGadgetItem = (GadgetListItem*) pListItem;
02690             pGadgetItem->pDialogOp->SetStringGadgetValue(pGadgetItem->gidGadgetID,
02691                                                             *pStr,
02692                                                             FALSE,
02693                                                             -1);
02694 
02695             // This can be useful when bamboozled by the Operations system . . .
02696 /*          TRACEUSER( "JustinF", _T("\t\tUpdating zoom combo at 0x%lX (GID# %lX)\n"),
02697                         (UINT32) pGadgetItem, (UINT32) pGadgetItem->gidGadgetID);
02698 */      
02699             // Do the next control in the list, if any.
02700             pListItem = pGadgetList->GetNext(pListItem);
02701         }
02702     }
02703 /*  else
02704     {
02705         // Something went wrong!
02706         TRACEUSER( "JustinF", _T("Couldn't build gadget list in ")
02707                              "OpZoomComboDescriptor::UpdateAllCombos!\n");
02708     }
02709 */
02710     // Don't forget to delete the list afterwards!
02711     pGadgetList->DeleteAll();
02712     delete pGadgetList;
02713 #endif
02714 
02715     return TRUE;
02716 }
02717 
02718 
02719 
02720 /********************************************************************************************
02721 >   BOOL OpZoomComboDescriptor::UpdateComboWithViewScale(DocView* pDocView)
02722 
02723     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02724     Created:    26/5/94
02725     Inputs:     pDocView        the DocView whose zoom factor will appear in the
02726                                 zoom control's combo-box.
02727     Returns:    TRUE if successful.
02728     Errors:     Out of memory
02729     Purpose:    Updates the combo-box with the DocView's current percentage zoom
02730                 factor.  This works even if there is more than one combo-box.  The
02731                 function is complicated by design deficiencies in the Operation system!
02732     Errors:     -
02733     SeeAlso:    OpDescriptor::BuildGadgetList; DocView::GetZoomTableIndex
02734 ********************************************************************************************/
02735 
02736 BOOL OpZoomComboDescriptor::UpdateComboWithViewScale(DocView* pDocView)
02737 {
02738     // Get the DocView's scale percentage.  If it's -1 then we must calculate the
02739     // percentage from the raw scale factor, otherwise we can look it up.
02740     INT32 nScalePercent;
02741     String_256 txt;
02742 
02743     if (pDocView)
02744     {
02745         INT32 nTableIndex = pDocView->GetZoomTableIndex();
02746         if (nTableIndex == cUninitZoomIndex)
02747         {
02748             // This value is set by DocView's constructor, and means that the view has not
02749             // been given a ZoomTableIndex yet.  Give it the default, ie. 100%.
02750             pDocView->SetZoomTableIndex(nTableIndex = cDefaultZoomIndex);
02751             nScalePercent = OpZoom::GetPresetZoomPercent(nTableIndex);
02752         }
02753         else if (nTableIndex == cFractionalZoomIndex)
02754         {
02755             // Convert from a fixed16 scale factor to a percentage.  This must be rounded
02756             // to the nearest percent.
02757             nScalePercent = ((pDocView->GetViewScale() * 100) + FIXED16_DBL(0.5)).MakeInt();
02758         }
02759         else
02760         {
02761             nScalePercent = OpZoom::GetPresetZoomPercent(nTableIndex);
02762         }
02763     
02764         // Convert the percentage to a formatted text string.
02765         txt.MakeMsg(_R(IDS_ZOOM_INFO_FORMAT), nScalePercent);
02766     }
02767 
02768     // Update all existing zoom combos with the text.
02769     return UpdateAllCombos(&txt);
02770 }
02771 
02772 
02773 
02774 /********************************************************************************************
02775 >   BOOL OpZoomComboDescriptor::RefreshList()
02776 
02777     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02778     Created:    26/5/94
02779     Purpose:    Fills the zoom control's combo-box with a list of percentage scale
02780                 factors and set names, corresponding to those held in OpZoom::ZoomTable[]
02781     Returns:    TRUE if successful.
02782     Errors:     Out of memory
02783     SeeAlso:    OpZoomComboDescriptor::Message; DialogOp::SetStringGadgetValue
02784 ********************************************************************************************/
02785 
02786 BOOL OpZoomComboDescriptor::RefreshList()
02787 {
02788     List* pList = new List;
02789     ERRORIF(pList == 0, _R(IDE_NOMORE_MEMORY), FALSE);
02790 
02791     // See if the dialogue manager can remember where its controls live, or even
02792     // what identifiers they possess . . .
02793     if (BuildGadgetList(pList))
02794     {   
02795         // Success.  Walk the generated list
02796         ListItem* pListItem = pList->GetHead();
02797         while (pListItem != 0)
02798         {
02799             DialogOp* pBarOp = ((GadgetListItem*) pListItem)->pDialogOp;
02800             CGadgetID gid = ((GadgetListItem*) pListItem)->gidGadgetID;
02801 
02802             // Start with a clean sheet.
02803             pBarOp->DeleteAllValues(gid);
02804 
02805             // Set each percentage zoom factor at successive positions in the combo-box.
02806             String_256 txt;
02807             INT32 i;
02808             for (i = 0; i < cZoomTableSize; i++)
02809             {
02810                 txt.MakeMsg(_R(IDS_ZOOM_INFO_FORMAT), OpZoom::GetPresetZoomPercent(i));
02811                 pBarOp->SetStringGadgetValue(gid, txt, FALSE, i);
02812             }
02813 
02814             // Insert a divider so it all looks nice.
02815             String_256 strDivide(_R(IDS_ZOOM_COMBO_DIVIDER));
02816             pBarOp->SetStringGadgetValue(gid, strDivide, FALSE, i++);
02817 
02818             // Add the text commands after the percentages.
02819             txt.Load(_R(IDS_ZOOMSPREADCOMBOTEXT));
02820             pBarOp->SetStringGadgetValue(gid, txt, FALSE, i++);
02821             txt.Load(_R(IDS_ZOOMDRAWINGCOMBOTEXT));
02822             pBarOp->SetStringGadgetValue(gid, txt, FALSE, i++);
02823 
02824 #ifndef STANDALONE
02825             txt.Load(_R(IDS_ZOOMSELECTEDCOMBOTEXT));
02826             pBarOp->SetStringGadgetValue(gid, txt, FALSE, i++);
02827 #endif
02828 
02829             txt.Load(_R(IDS_ZOOMPREVIOUSCOMBOTEXT));
02830             pBarOp->SetStringGadgetValue(gid, txt, FALSE, i++);
02831 
02832             // Set the required depth of the combo-box when it drops down.
02833             pBarOp->SetComboListLength(gid);
02834 
02835             // Blank the string to start off with
02836             txt=_T("");
02837             pBarOp->SetStringGadgetValue(gid, txt, FALSE, -1);
02838 
02839             // Do the next control in the list, if any.
02840             pListItem = pList->GetNext(pListItem);
02841         }
02842 
02843         pList->DeleteAll();
02844     }
02845 
02846     delete pList;
02847     return TRUE;
02848 }
02849 
02850 
02851 
02852 /********************************************************************************************
02853 >   MsgResult OpZoomComboDescriptor::HandleCreateMsg(DialogOp* popdlgThis,
02854                                                      CGadgetID gidThis)
02855 
02856     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02857     Created:    26/5/94
02858     Inputs:     popdlgThis          points to a DialogOp (a control?)
02859                 gidThis             gadget ID of control
02860     Outputs:    -
02861     Returns:    A message result (always EAT_MSG)
02862     Purpose:    Fills the zoom control's combo-box with a list of percentage scale
02863                 factors, corresponding to those held in OpZoom::ZoomTable[]
02864     Errors:     -
02865     SeeAlso:    OpZoomComboDescriptor::Message; DialogOp::SetStringGadgetValue
02866 ********************************************************************************************/
02867 
02868 MsgResult OpZoomComboDescriptor::HandleCreateMsg(DialogOp* popdlgThis, CGadgetID gidThis)
02869 {
02870 #if !defined(EXCLUDE_FROM_RALPH)
02871     // Delegate delegate delegate!
02872     if (!RefreshList()) return FAIL;
02873 
02874     // Make sure the visuals reflect all this.
02875     DocView* pDocView = DocView::GetCurrent();
02876     if (pDocView != 0) UpdateComboWithViewScale(pDocView);
02877 #endif
02878     // Processed message successfully.
02879     return EAT_MSG;
02880 }
02881 
02882 
02883 
02884 /********************************************************************************************
02885 >   void OpZoomComboDescriptor::OnSelectionChange(OpDescControlMsg* pCtrlMsg,
02886                                                   List* pGadgetList)
02887 
02888     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
02889     Created:    18/7/94
02890     Inputs:     pCtrlMsg    ---     pointer to the message from a control
02891                 pGadgetList ---     list of all gadgets associated with this OpDescriptor.
02892     Outputs:    -
02893     Returns:    -
02894     Purpose:    Handles the user changing the selection, or typing text, in the zoom factor
02895                 combo-box.   Reads the selected text, checking for "%" or "x" which
02896                 indicates a percentage zoom factor (absolute) or a multiplier (relative),
02897                 converts to a number and performs the requested zoom on the selected
02898                 view.
02899     Errors:     -
02900     SeeAlso:    OpZoomComboDescriptor::StringToLong; OpZoomDescriptor::FakeInvoke
02901 ********************************************************************************************/
02902 
02903 void OpZoomComboDescriptor::OnSelectionChange(OpDescControlMsg* pCtrlMsg, List*)
02904 {
02905 #if !defined(EXCLUDE_FROM_RALPH)
02906     // Check that we have reasonable input.
02907     ERROR3IF(pCtrlMsg == 0 || pCtrlMsg->pDlgOp == 0,
02908                 "No OpDescriptor message in OpZoomComboDescriptor::OnSelectionChange");
02909     if (pCtrlMsg == 0 || pCtrlMsg->pDlgOp == 0) return;
02910 
02911     // Get the selected DocView etc.
02912     DocView* pDocView = DocView::GetCurrent();
02913     ERROR3IF(pDocView == 0,
02914                 "No current DocView in OpZoomComboDescriptor::OnSelectionChange");
02915     if (pDocView == 0) return;
02916 
02917     // If the selected text is actually one of the zoom commands, eg. "(Fit to) Spread",
02918     // then dispatch that to the appropriate handler.
02919     WORD wComboIndex;
02920     pCtrlMsg->pDlgOp->GetValueIndex(pCtrlMsg->SetGadgetID, &wComboIndex);
02921     INT32 nComboIndex = (short) wComboIndex;
02922     switch (nComboIndex)
02923     {
02924         case cFitToSpreadIndex:
02925             FakeInvoke(OPTOKEN_ZOOMSPREAD);
02926             return;
02927 
02928         case cFitToDrawingIndex:
02929             FakeInvoke(OPTOKEN_ZOOMDRAWING);
02930             return;
02931 
02932         case cFitToSelectedIndex:
02933             FakeInvoke(OPTOKEN_ZOOMSELECTED);
02934             return;
02935 
02936         case cPreviousZoomIndex:
02937             FakeInvoke(OPTOKEN_ZOOMPREV);
02938             return;
02939 
02940         case cComboDivider1:
02941         case cComboDivider2:
02942 //          Beep();
02943             wxBell();
02944             OpZoomComboDescriptor::Update();
02945             return;
02946 
02947         default:
02948             break;
02949     }
02950 
02951     // Have we selected a set item from the list?
02952 // We really don't want the name gallery to have any effect on the zoom dropdown...
02953 /*  INT32 n = nComboIndex - cComboDivider2;
02954     if (n > 0)
02955     {
02956         NameGallery *pNameGallery = NameGallery::Instance();
02957         if (pNameGallery)
02958         {
02959             SGUsedNames* pUsedNames = pNameGallery->GetUsedNames();
02960             if (pUsedNames != 0)
02961             {
02962                 SGNameItem* pItem = (SGNameItem*) pUsedNames->GetChild();
02963                 if (pItem != 0)
02964                 {
02965                     for (; pItem != 0; pItem = (SGNameItem*) pItem->GetNext())
02966                         if (!pItem->GetSetBounds().IsEmpty() && --n == 0)
02967                         {
02968                             // Extract the bounds of the chosen set and zoom to them.
02969                             ERROR3IF(!pItem->GetSetBounds().IsValid(),
02970                                 "OpZoomComboDescriptor::OnSelectionChange: invalid bounds");
02971                             OpZoomDescriptor::FakeZoomToRect(pItem->GetSetBounds());
02972                             return;
02973                         }
02974 
02975                     Beep();
02976                     ERROR3("OpZoomComboDescriptor::OnSelectionChange: can't find SGNameItem");
02977                     return;
02978                 }
02979             }
02980         }
02981     }
02982 */
02983 
02984     // Extract the highlighted text.  We pass a pointer to our "StringToLong" function
02985     // that knows how to extract a zoom factor from the user's input.
02986     BOOL bIsValid;
02987     INT32 nPercent = pCtrlMsg->pDlgOp->GetLongGadgetValue(pCtrlMsg->SetGadgetID,
02988                                                          INT32_MIN, INT32_MAX,
02989                                                          _R(IDE_INVALIDZOOMFACTOR),
02990                                                          &bIsValid, StringToLong);
02991     
02992     // Check if the input is valid.  If it isn't then reset the result.  The
02993     // GetStringGadgetValue will have reported the error if the input isn't valid.
02994     if (!bIsValid)
02995     {
02996         UpdateComboWithViewScale(pDocView);
02997         return;
02998     }
02999 
03000     // If the returned value is negative it represents a "multiplier", which must
03001     // first be converted to a percentage.
03002     if (nPercent < 0)
03003     {
03004         INT32 nIndex = pDocView->GetZoomTableIndex();
03005         if (nIndex == cFractionalZoomIndex)
03006             nPercent = -nPercent * ((pDocView->GetViewScale() * 100) + FIXED16(0.5)).MakeInt();
03007         else
03008             nPercent = -nPercent * OpZoom::GetPresetZoomPercent(nIndex);
03009 
03010         // If the zoom factor is larger than the permitted maximum then adjust it.
03011         INT32 nMaxPercent = OpZoom::GetPresetZoomPercent(0);
03012         if (nPercent > nMaxPercent) nPercent = nMaxPercent;
03013     }
03014 
03015     // Begin by assuming the percentage isn't in the table.
03016     INT32 nIndex = cFractionalZoomIndex;
03017 
03018     // Look for the percentage in the zoom factor table.
03019     for (INT32 i = 0; i < cZoomTableSize; i++)
03020     {
03021         if (OpZoom::GetPresetZoomPercent(i) == nPercent)
03022         {
03023             // Found the percentage in the table.
03024             nIndex = i;
03025             break;
03026         }
03027     }
03028 
03029     // Try to create an OpZoom operation.
03030     OpZoom* pZoomOp = new OpZoom;
03031     if (pZoomOp == 0)
03032     {
03033         // We ran out of memory, so sorry.
03034         InformError(_R(IDE_NOMORE_MEMORY));
03035         return;
03036     }
03037 
03038     // Find the mid-point of the view, in work coordinates.
03039     WorkRect wrView = pDocView->GetViewRect();
03040     WorkCoord wcMidView((wrView.lo.x + wrView.hi.x) / 2,
03041                         (wrView.lo.y + wrView.hi.y) / 2);
03042     
03043     // Ask the operation to zoom at this point.
03044     pDocView->SetZoomTableIndex(nIndex);
03045     pZoomOp->ZoomAtPoint(wcMidView, ((FIXED16) (INT32) nPercent) / 100);
03046 #endif
03047 }
03048 
03049 
03050 
03051 /********************************************************************************************
03052 >   static BOOL OpZoomComboDescriptor::StringToLong(const StringBase& strIn, INT32* pnOut)
03053 
03054     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03055     Created:    18/7/94
03056     Inputs:     pstrIn      ---     pointer to the string containing text
03057                 pnOut       ---     pointer to the number which will contain the result
03058     Outputs:    -
03059     Returns:    TRUE if the text is successfully parsed, FALSE otherwise.
03060     Purpose:    Parses the text within the zoom factor combo-box, checking for a percentage
03061                 factor ("%") or a multiplier factor ("x"), converting it to a number.
03062     Errors:     -
03063     SeeAlso:    OpZoomComboDescriptor::OnSelectionChange; DialogOp::GetLongGadgetValue
03064 ********************************************************************************************/
03065 
03066 BOOL OpZoomComboDescriptor::StringToLong(const StringBase& strIn, INT32* pnOut)
03067 {
03068     const StringBase * pstrIn = &strIn;
03069     ERROR2IF(pstrIn == 0 || pnOut == 0, FALSE,
03070             "No parameter(s) in OpZoomComboDescriptor::StringToLong");
03071 
03072     // Remove any leading or trailing whitespace.  psczStart is set to point to first non-
03073     // whitespace character (or the terminating null), pszEnd points to the last.  If the
03074     // string is entirely whitespace these two will cross over, and we return FALSE.
03075     const TCHAR* psczStart = (const TCHAR*) *pstrIn;
03076     const TCHAR* psczForward = psczStart;
03077     const TCHAR* psczBack = psczStart + pstrIn->Length() - 1;
03078 
03079     while (StringBase::IsSpace(*psczForward))
03080         psczForward = camStrinc(psczForward);
03081     
03082     while (psczBack > psczForward && StringBase::IsSpace(*psczBack))
03083         psczBack = camStrdec(psczStart, psczBack);
03084     
03085     if (psczForward >= psczBack) return FALSE;
03086 
03087     // Check if the string ends with a '%' or an 'x'.  If it is an 'x' then the number
03088     // is a multipler, eg. "2 x" (two times).  If it is a '%', or not there at all,
03089     // then it represents a percentage.
03090     BOOL bIsMultiplier = FALSE;
03091     if (*psczBack == TEXT('x') || *psczBack == TEXT('X'))
03092     {
03093         // Parse a multiplier.  Skip over the 'x'.
03094         psczBack--;
03095         bIsMultiplier = TRUE;
03096     }
03097     else if (*psczBack == TEXT('%'))
03098     {
03099         // Parse a percentage.  Skip over the '%'
03100         psczBack--;
03101     }
03102     else if (!StringBase::IsNumeric(*psczBack))
03103     {
03104         // Can't recognise the format - not a number.
03105         return FALSE;
03106     }
03107 
03108     // Make a working copy of what is left of the string.
03109     String_256 strWork;
03110     pstrIn->Mid(&strWork, (INT32) (psczForward - psczStart),
03111                 (INT32) (psczBack - psczForward) + 1);
03112 
03113     // Convert the remaining text into a number and return it.  Percentages and
03114     // multipliers cannot be negative or zero (especially as multipliers are returned
03115     // back as negative to distinguish them from percentages).
03116     if (!Convert::StringToLong(strWork, pnOut) || *pnOut <= 0) return FALSE;
03117     
03118     // Make sure it's within allowed bounds.
03119     INT32 nMaxPercent = OpZoom::GetPresetZoomPercent(0);
03120     INT32 nMinPercent = OpZoom::GetPresetZoomPercent(cZoomTableSize - 1);
03121 
03122     if (*pnOut > nMaxPercent) *pnOut = nMaxPercent;
03123     if (*pnOut < nMinPercent && !bIsMultiplier) *pnOut = nMinPercent;    
03124     if (bIsMultiplier) *pnOut = -(*pnOut);
03125 
03126     return TRUE;
03127 }
03128 
03129 
03130 
03131 /********************************************************************************************
03132 >   static BOOL OpZoomComboDescriptor::Update(BOOL fRefreshList = FALSE)
03133 
03134     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03135     Created:    26/5/94
03136     Inputs:     fRefreshList    ---     if TRUE then regenerate all items in the
03137                                         list (by default, just regenerate the item
03138                                         shown in the edit field).
03139     Purpose:    Gets a pointer to the (one and only) OpZoomComboDescriptor in the
03140                 system, and calls its member function UpdateComboWithViewScale for
03141                 the "selected" DocView, if any.  Available publicly to other zoom
03142                 tool classes, to be called when they modify a DocView's zoom factor.
03143     Returns:    FALSE if there's an error.
03144     Errors:     Out of memory.
03145     SeeAlso:    OpZoomComboDescriptor::UpdatecomboWithViewScale;
03146                 OpDescriptor::FindOpDescriptor; DocView::GetSelected
03147 ********************************************************************************************/
03148 
03149 BOOL OpZoomComboDescriptor::Update(BOOL fRefreshList)
03150 {
03151     // Get the "selected" DocView, ie. the view that the user has made top-most.
03152     DocView* pDocView = DocView::GetCurrent();
03153     ERROR3IF(pDocView == 0, "No current DocView in OpZoomComboDescriptor::Update");
03154     if (pDocView == 0) return FALSE;
03155 
03156 // WEBSTER - markn 15/1/97
03157 // No rulers in Webster
03158 #ifndef WEBSTER
03159 #if !defined(EXCLUDE_FROM_RALPH)
03160     // update the rulers after every scale change
03161     if (pDocView->GetpRulerPair()) pDocView->GetpRulerPair()->Update();
03162 #endif
03163 #endif // WEBSTER
03164 
03165     // Find the one and only OpZoomComboDescriptor object.
03166     OpDescriptor* popd = OpDescriptor::FindOpDescriptor(OPTOKEN_ZOOMCOMBO);
03167     ERROR3IF(popd == 0, "Can't find OpZoomComboDescriptor in "
03168                          "OpZoomFitSelectedDescriptor::HandleButtonMsg");
03169     if (popd == 0) return FALSE;
03170     
03171     // Update it with values of the Selected DocView.
03172     OpZoomComboDescriptor* pCombo = (OpZoomComboDescriptor*) popd;
03173     if (fRefreshList && !pCombo->RefreshList()) return FALSE;
03174     return pCombo->UpdateComboWithViewScale(pDocView);
03175 
03176 }
03177 
03178 
03179 #if !defined(EXCLUDE_FROM_RALPH)
03180 
03182 // Classes ZoomInfoBarOp and ZoomInfoBarOpCreate.
03183 
03184 /********************************************************************************************
03185 >   ZoomInfoBarOp::ZoomInfoBarOp()
03186 
03187     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03188     Created:    15/3/95
03189     Inputs:     -
03190     Outputs:    -
03191     Returns:    -
03192     Purpose:    Constructs a zoom info-bar operation.
03193     Errors:     -
03194     SeeAlso:    -
03195 ********************************************************************************************/
03196 #if 0
03197 ZoomInfoBarOp::ZoomInfoBarOp()
03198   : InformationBarOp(0)
03199 {
03200     // Empty.
03201 }
03202 #endif
03203 
03204 
03205 /********************************************************************************************
03206 >   virtual MsgResult ZoomInfoBarOp::Message(Msg* pMsg)
03207 
03208     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03209     Created:    15/3/95
03210     Inputs:     -
03211     Outputs:    -
03212     Returns:    The result of processing the message.
03213     Purpose:    Handles a Camelot message for the zoom info-bar.
03214     Errors:     -
03215     SeeAlso:    DialogBarOp::Message
03216 ********************************************************************************************/
03217 
03218 MsgResult ZoomInfoBarOp::Message(Msg* pMsg)
03219 {
03220     // Pass on to base class for default handling.
03221     return DialogBarOp::Message(pMsg);
03222 }
03223 
03224 
03225 
03226 /********************************************************************************************
03227 >   virtual DialogBarOp* ZoomInfoBarOpCreate::Create()
03228 
03229     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
03230     Created:    26/5/94
03231     Inputs:     -
03232     Outputs:    -
03233     Returns:    A pointer to a DialogBarOp, which represents an info-bar.
03234     Purpose:    Constructs a ZoomInfoBarOp (or derivative) on the heap and returns a
03235                 pointer to it.  Used internally by the info-bar system.
03236     Errors:     -
03237     SeeAlso:    class ZoomInfoBarOp; class InformationBarOp
03238 ********************************************************************************************/
03239 
03240 DialogBarOp* ZoomInfoBarOpCreate::Create()
03241 {
03242     return new ZoomInfoBarOp;
03243 }
03244 
03245 #endif

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