oilprog.cpp

Go to the documentation of this file.
00001 // $Id: oilprog.cpp 1282 2006-06-09 09:46:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 
00099 /*
00100     The progress indicator (OIL implementation).
00101 
00102 
00103 */
00104 
00105 
00106 #include "camtypes.h"
00107 
00108 #include <string.h>                     // for memset()
00109 #include "csrstack.h"
00110 #include "oilprog.h"
00111 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "keypress.h"
00113 #include "unicdman.h"
00114 
00115 //#include "justin.h"                       // for cursor bitmaps
00116 //#include "justin2.h"
00117 
00118 
00119 DECLARE_SOURCE("$Revision: 1282 $");
00120 
00121 
00122 
00123 // This structure defines a pair of bitmaps, which can be combined to make a cursor.
00124 
00125 struct MaskPair
00126 {
00127     UINT32 AndID;
00128     UINT32 XorID;
00129 };
00130 
00131 
00132 struct CursorMask
00133 {
00134     CBitmap* pAndMask;
00135     CBitmap* pXorMask;
00136 };
00137 
00138 
00139 
00140 // Declare an array of CursorMasks, which together form the animation sequence.
00141 
00142 const INT32 nFrameCount = 9;
00143 INT32 CurrentFrame;
00144 
00145 CursorMask CursorSeq[nFrameCount];
00146 
00147 
00148 
00149 // This array stores the numeric resource identifiers of each mask bitmap.
00150 
00151 const MaskPair CursorMaskID[nFrameCount] =
00152 {
00153     { _R(IDB_AND_PROGRESS_0), _R(IDB_XOR_PROGRESS_0) },
00154     { _R(IDB_AND_PROGRESS_1), _R(IDB_XOR_PROGRESS_1) },
00155     { _R(IDB_AND_PROGRESS_2), _R(IDB_XOR_PROGRESS_2) },
00156     { _R(IDB_AND_PROGRESS_3), _R(IDB_XOR_PROGRESS_3) },
00157     { _R(IDB_AND_PROGRESS_4), _R(IDB_XOR_PROGRESS_4) },
00158     { _R(IDB_AND_PROGRESS_5), _R(IDB_XOR_PROGRESS_5) },
00159     { _R(IDB_AND_PROGRESS_6), _R(IDB_XOR_PROGRESS_6) },             
00160     { _R(IDB_AND_PROGRESS_7), _R(IDB_XOR_PROGRESS_7) },
00161     { _R(IDB_AND_PROGRESS_8), _R(IDB_XOR_PROGRESS_8) }
00162 };
00163 
00164 
00165 
00166 // GDI objects we use etc.
00167 
00168 CDC* pMemoryDC1;
00169 CDC* pMemoryDC2;
00170 CBitmap* pAndBmp;
00171 CBitmap* pXorBmp;
00172 CFont* pCursorFont;
00173 
00174 CRect TextRect;
00175 CRect MaskRect;
00176 
00177 
00178 
00179 
00180 /********************************************************************************************
00181 >   BOOL InitProgressCursor()
00182 
00183     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00184     Created:    19/11/93
00185     Inputs:     -
00186     Outputs:    -
00187     Returns:    TRUE if initialisation was successful.
00188     Purpose:    Does initial calculations and creates all the GDI objects that
00189                 UpdateProgressCursor() requires.
00190     Errors:     -
00191     SeeAlso:    UpdateProgressCursor; DeInitProgressCursor
00192 ********************************************************************************************/
00193 
00194 BOOL InitProgressCursor()
00195 {
00196     // Load in the mask bitmap pairs which make up the cursor animation sequence.
00197     for (INT32 i = 0; i < nFrameCount; i++)
00198     {
00199         // Allocate two new bitmap objects on the heap.
00200         CursorSeq[i].pAndMask = new CBitmap;
00201         CursorSeq[i].pXorMask = new CBitmap;
00202         if (!CursorSeq[i].pAndMask || !CursorSeq[i].pXorMask)
00203         {
00204             if (IsUserName("JustinF"))
00205                 TRACE( _T("Couldn't allocate CBitmap objects in InitProgressCursor()!\n"));
00206             return FALSE;
00207         }
00208 
00209         // Load the appropriate bitmaps from resources.
00210         if (!CursorSeq[i].pAndMask->LoadBitmap(CursorMaskID[i].AndID) ||
00211             !CursorSeq[i].pXorMask->LoadBitmap(CursorMaskID[i].XorID))
00212         {
00213             if (IsUserName("JustinF"))
00214                 TRACE( _T("Couldn't load bitmap resources in InitProgressCursor()!\n"));
00215             return FALSE;
00216         }
00217 
00218         // In the debugging version, check for AppStudio sabotage (it converts monochrome
00219         // bitmaps to colour - b*st*rd!)
00220         #ifdef  _DEBUG
00221             BITMAP andinfo, xorinfo;
00222             CursorSeq[i].pAndMask->GetObject(sizeof(andinfo), &andinfo);
00223             CursorSeq[i].pXorMask->GetObject(sizeof(xorinfo), &xorinfo);
00224             ENSURE(andinfo.bmBitsPixel == 1 && andinfo.bmPlanes == 1 &&
00225                    xorinfo.bmBitsPixel == 1 && xorinfo.bmPlanes == 1,
00226                    "Bitmaps in InitProgressCursor() are not monochrome!\n");
00227         #endif  // _DEBUG
00228     }
00229 
00230     // Make two scratch bitmaps with the same size as cursors.  These bitmaps are
00231     // monochrome, like standard Windows cursors.
00232     pAndBmp = new CBitmap;
00233     pXorBmp = new CBitmap;
00234     if (!pAndBmp || !pXorBmp ||
00235         !pAndBmp->CreateBitmap(Cursor::Width(), Cursor::Height(), 1, 1, 0) ||
00236         !pXorBmp->CreateBitmap(Cursor::Width(), Cursor::Height(), 1, 1, 0))
00237     {
00238         if (IsUserName("JustinF"))
00239             TRACE( _T("Couldn't create scratch bitmaps in InitProgressCursor()!\n"));
00240         return FALSE;
00241     }
00242 
00243     // Create a font to write the percentage text with.
00244     LOGFONT fontinfo;
00245     memset(&fontinfo, 0, sizeof(fontinfo));             // all fields zero means use default values
00246     fontinfo.lfCharSet = UnicodeManager::GetFontCharSet();
00247     fontinfo.lfHeight = -Cursor::Width() / 3;
00248 
00249     pCursorFont = new CFont;
00250     if (!pCursorFont || !pCursorFont->CreateFontIndirect(&fontinfo))
00251     {
00252         if (IsUserName("JustinF"))
00253             TRACE( _T("Couldn't create font object in InitProgressCursor()!\n"));
00254         return FALSE;
00255     }
00256 
00257     // Make a device context in memory which is compatible with the screen.
00258     pMemoryDC1 = new CDC;
00259     pMemoryDC2 = new CDC;
00260     if (!pMemoryDC1 || !pMemoryDC2 ||
00261         !pMemoryDC1->CreateCompatibleDC(0) ||
00262         !pMemoryDC2->CreateCompatibleDC(0))
00263     {
00264         if (IsUserName("JustinF"))
00265             TRACE( _T("Couldn't create memory DC's in InitProgressCursor()!\n"));
00266         return FALSE;
00267     }
00268 
00269     // Find out how large the font we created REALLY is, so we can calculate where within
00270     // the cursor we can write the text.
00271     TEXTMETRIC textinfo;
00272     CFont* pf = pMemoryDC1->SelectObject(pCursorFont);
00273     pMemoryDC1->GetTextMetrics(&textinfo);
00274     pMemoryDC1->SelectObject(pf);
00275 
00276     // The text appears at the bottom of the cursor.  Calculate its bounding rectangle, which
00277     // includes room for a two-pixel wide border
00278     TextRect.left   = 0;
00279     TextRect.top    = Cursor::Height() - textinfo.tmAscent;
00280     TextRect.right  = Cursor::Width();
00281     TextRect.bottom = Cursor::Height();
00282 
00283     // The mask bitmaps are stretched into the remaining square space.
00284     MaskRect.top    = 0;
00285     MaskRect.bottom = Cursor::Height() - textinfo.tmHeight;
00286     MaskRect.left   = Cursor::Width() / 2 - MaskRect.bottom / 2;
00287     MaskRect.right  = Cursor::Width() / 2 + MaskRect.bottom / 2;
00288 
00289     // Finally, set the animation to begin with the first frame and . . . success!
00290     CurrentFrame = 0;
00291     return TRUE;
00292 }
00293 
00294 
00295 
00296 
00297 
00298 /********************************************************************************************
00299 >   Cursor* UpdateProgressCursor(INT32 percent)
00300 
00301     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> (Messed around by Jason)
00302     Created:    19/11/93
00303     Inputs:     percent -   A value between 0% and 100% to be displayed under the pointer, OR
00304                             -1 to indicate that no percentage should be displayed.
00305     Outputs:    -
00306     Returns:    A pointer to the new progress cursor object if successful, NULL otherwise.
00307     Purpose:    (If percent >= 0 it draws the percentage text into the cursor masks and then)
00308                 creates and sets a new cursor.
00309     Errors:     -
00310     SeeAlso:    InitProgressCursor; DeInitProgressCursor
00311 ********************************************************************************************/
00312 
00313 Cursor* UpdateProgressCursor(INT32 percent)
00314 {
00315     // Before we get too confused, the truth table for the combination of the 2 bitmaps is:
00316     //
00317     //      ANDbmp  XORbmp  Result in cursor
00318     //      Black   Black   Black
00319     //      Black   White   White
00320     //      White   Black   Transparent
00321     //      White   White   Invert screen colour at this point
00322     //
00323     // First, we set AND/XOR to White/Black respectively so that the cursor is transparent...
00324 
00325     CBitmap* poldbmp1 = pMemoryDC1->SelectObject(pAndBmp);
00326     pMemoryDC1->PatBlt(0, 0, Cursor::Width(), Cursor::Height(), WHITENESS);
00327 
00328     CBitmap* poldbmp2 = pMemoryDC2->SelectObject(pXorBmp);
00329     pMemoryDC2->PatBlt(0, 0, Cursor::Width(), Cursor::Height(), BLACKNESS);
00330 
00331     // Find out how large the mask bitmaps are (they are assumed to all be of the same size).
00332     BITMAP bmpinfo;
00333     CursorSeq[CurrentFrame].pAndMask->GetObject(sizeof(bmpinfo), &bmpinfo);
00334 
00335     // Stretch the cursor masks for the current animation frame into the scratch bitmaps.
00336     // First the XOR mask, then the AND mask.
00337     pMemoryDC2->SelectObject(CursorSeq[CurrentFrame].pXorMask);         // source
00338     pMemoryDC1->SelectObject(pXorBmp);                                  // destination
00339     pMemoryDC1->StretchBlt(MaskRect.left, MaskRect.top, MaskRect.Width(), MaskRect.Height(),
00340                            pMemoryDC2, 0, 0, bmpinfo.bmWidth, bmpinfo.bmHeight, SRCCOPY);
00341 
00342     pMemoryDC2->SelectObject(CursorSeq[CurrentFrame].pAndMask);         // source
00343     pMemoryDC1->SelectObject(pAndBmp);                                  // destination
00344     pMemoryDC1->StretchBlt(MaskRect.left, MaskRect.top, MaskRect.Width(), MaskRect.Height(),
00345                            pMemoryDC2, 0, 0, bmpinfo.bmWidth, bmpinfo.bmHeight, SRCCOPY);
00346 
00347     if (percent >= 0)       // Only display percentage text if 'percent' >= 0
00348     {
00349         // Next, write the percentage text inside the text rectangle.
00350         // We want this to be black text on a white rub-out box, so we plot black-on-white text
00351         // into the XOR bitmap, and black-on-black into the AND bitmap (rather than plotting a
00352         // rectangle, because we want the rub-out box to be only slightly bigger than the text
00353         // sitting upon it...)
00354         pMemoryDC1->SelectObject(pXorBmp);
00355 
00356         pMemoryDC1->SetTextColor(RGB(0, 0, 0));
00357         pMemoryDC1->SetBkColor(RGB(255, 255, 255));
00358 
00359         CFont   *poldfont1 = pMemoryDC1->SelectObject(pCursorFont);
00360         TCHAR   txt[8];                     // Cache - percentage text
00361         INT32       numchars;                   // Cache - number of chars in the above %age text
00362 
00363         String_32 jcf(_R(IDS_PERCENT_FORMAT));
00364         numchars = ::wsprintf(txt, jcf, (INT32) percent);
00365         pMemoryDC1->DrawText(txt, numchars, &TextRect,
00366                              DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);
00367 
00368         pMemoryDC1->SelectObject(pAndBmp);
00369         pMemoryDC1->SetTextColor(RGB(0, 0, 0));
00370         pMemoryDC1->SetBkColor(RGB(0, 0, 0));
00371 
00372         pMemoryDC1->DrawText(txt, numchars, &TextRect,
00373                              DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);
00374 
00375         pMemoryDC1->SelectObject(poldfont1);
00376     }
00377 
00378     // Deselect the bitmaps.
00379     pMemoryDC1->SelectObject(poldbmp1);
00380     pMemoryDC2->SelectObject(poldbmp2);
00381 
00382     // Finally, create and set the new cursor.
00383     Cursor* pnc = new Cursor(pAndBmp, pXorBmp);
00384     if (!pnc || !pnc->IsValid())
00385     {
00386         if (IsUserName("JustinF"))
00387             TRACE( _T("Couldn't create new Cursor object in UpdateProgressCursor()!\n"));
00388         delete pnc;
00389         return 0;
00390     }
00391 
00392     // Update the animation frame counter.
00393     if (++CurrentFrame >= nFrameCount) CurrentFrame = 0;
00394     return pnc;
00395 }
00396 
00397 
00398 
00399 
00400 
00401 /********************************************************************************************
00402 >   void DeInitProgressCursor()
00403 
00404     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00405     Created:    19/11/93
00406     Inputs:     -
00407     Outputs:    -
00408     Returns:    -
00409     Purpose:    Deallocates all objects created in InitProgressCursor()
00410     Errors:     -
00411     SeeAlso:    InitProgressCursor; UpdateProgressCursor
00412 ********************************************************************************************/
00413 
00414 void DeInitProgressCursor()
00415 {
00416     // Deallocate the mask bitmaps.
00417     for (INT32 i = 0; i < nFrameCount; i++)
00418     {
00419         CursorSeq[i].pAndMask->DeleteObject();
00420         CursorSeq[i].pXorMask->DeleteObject();
00421         delete CursorSeq[i].pAndMask;
00422         delete CursorSeq[i].pXorMask;
00423     }
00424 
00425     // Destroy the other GDI objects.
00426     pMemoryDC1->DeleteDC();
00427     delete pMemoryDC1;
00428 
00429     pMemoryDC2->DeleteDC();
00430     delete pMemoryDC2;
00431 
00432     pAndBmp->DeleteObject();
00433     delete pAndBmp;
00434 
00435     pXorBmp->DeleteObject();
00436     delete pXorBmp;
00437 
00438     delete pCursorFont;
00439 }
00440 
00441 
00442 
00443 
00444 /********************************************************************************************
00445 >   BOOL BreakKeyHit()
00446 
00447     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00448     Created:    18/11/93
00449     Inputs:     -
00450     Outputs:    -
00451     Returns:    TRUE if the Escape key is pressed.
00452     Purpose:    Checks if the user is trying to interrupt or cancel a task.
00453     Errors:     -
00454     SeeAlso:    ContinueSlowJob
00455 ********************************************************************************************/
00456 
00457 BOOL BreakKeyHit()
00458 {
00459     return KeyPress::IsEscapePressed();
00460 /*
00461     if (::GetAsyncKeyState(CAMKEY(ESCAPE)) <0 )
00462     {
00463         MSG msg;
00464         BOOL Again;
00465         // if Esc is pressed down, lets throw away all key messages otherwise the Esc is likely
00466         // to get passed on e.g. to the next dialog box
00467         do
00468         {
00469             Again = PeekMessage( &msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE );
00470         } while (Again);
00471 
00472         return TRUE;
00473     }
00474     return FALSE;
00475 */
00476 }
00477 
00478 
00479 
00480 
00481 /********************************************************************************************
00482 
00483 >   void Beep()
00484 
00485     Author:     Justin_Flude (Xara Group Ltd) <camelotdev@xara.com>
00486     Created:    19/11/93
00487     Inputs:     -
00488     Outputs:    -
00489     Returns:    -
00490     Purpose:    Makes a beep sound, stupid!
00491     Errors:     -
00492     SeeAlso:    BreakKeyHit; ContinueSlowJob
00493 
00494 ********************************************************************************************/
00495 
00496 void Beep()
00497 {
00498     ::MessageBeep(MB_OK);
00499 }

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