sgcolour.cpp

Go to the documentation of this file.
00001 // $Id: sgcolour.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 // SGColour.cpp - Colour SuperGallery classes - ColourSGallery and SGDisplayColour
00099 
00100 #include "camtypes.h"
00101 
00102 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00103 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00104 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00105 #include "colcomp.h"
00106 #include "collist.h"
00107 #include "colourix.h"
00108 #include "colormgr.h"
00109 #include "colpick.h"
00110 #include "comattrmsg.h"
00111 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 #include "dragcol.h"
00113 #include "dragmgr.h"
00114 #include "fileutil.h"
00115 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00116 //#include "filters.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //#include "galres.h"
00118 //#include "galstr.h"
00119 //#include "isetres.h"
00120 //#include "jason.h"
00121 #include "lineattr.h"
00122 //#include "markn.h"
00123 //#include "newcol.h"
00124 //#include "resdll.h"
00125 //#include "resource.h" // For _R(IDS_CANCEL)
00126 #include "sgcolour.h"
00127 #include "sgdrag.h"
00128 #include "sginit.h"
00129 #include "sgliboil.h"
00130 #include "sgmenu.h"
00131 
00132 #include "ccdc.h"       // For render-into-dialogue support
00133 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00134 #include "grnddib.h"
00135 //#include "richard2.h" // resources to remove naughty inline strings
00136 #include "ccolbar.h"    // EnsureLibraryColoursPresent
00137 #include "backgrnd.h"   // OpBackground
00138 
00139 // WEBSTER - markn 31/1/97
00140 #include "helpuser.h"
00141 //#include "xshelpid.h"
00142 //#include "helppath.h"
00143 
00144 // Implement the dynamic class bits...
00145 CC_IMPLEMENT_DYNCREATE(ColourSGallery, SuperGallery)
00146 CC_IMPLEMENT_DYNAMIC(SGDisplayColour, SGDisplayItem)
00147 CC_IMPLEMENT_DYNAMIC(SGDisplayLibColour, SGDisplayColour)
00148 CC_IMPLEMENT_DYNAMIC(SGDisplayColourGroup, SGDisplayGroup)
00149 CC_IMPLEMENT_DYNAMIC(SGDisplayLibColGroup, SGDisplayColourGroup)
00150 CC_IMPLEMENT_DYNCREATE(OpDisplayColourGallery, Operation)
00151 CC_IMPLEMENT_DYNCREATE(GalleryColourDragInfo, ColourDragInformation)
00152 CC_IMPLEMENT_DYNAMIC(SGColourDragTarget, SGListDragTarget);
00153 CC_IMPLEMENT_DYNCREATE(ColourNameDlg, DialogOp)
00154 CC_IMPLEMENT_MEMDUMP(ColourNameParam, OpParam)
00155 
00156 
00157 // This line mustn't go before any CC_IMPLEMENT_... macros
00158 #define new CAM_DEBUG_NEW
00159 
00160 
00161 // Nasty PANTONE bodge - after any change of ordering in any library, the 
00162 // Pantone library no longer puts line breaks after every 9th item.
00163 static BOOL LibraryHasBeenSorted = FALSE;
00164 
00165 const INT32 SG_ColourNameWidth = 127000;        // Width of colour name field (just long enough
00166                                             // for "Pantone Process Magenta CV"!!)
00167 
00168 // This always points to the colour gallery, or NULL if it doesn't exist.
00169 ColourSGallery* ColourSGallery::m_pTheGallery = NULL;
00170 
00171 /********************************************************************************************
00172 
00173     Preference:     AutoScrollColGal
00174     Section:        Displays
00175     Range:          TRUE or FALSE
00176     Purpose:        If TRUE, the colour gallery will automatically scroll its display list
00177                     to show the currently selected line and fill colours whenever the
00178                     selection changes. If FALSE, these colours will still become selected,
00179                     but the gallery will not be scrolled.
00180 
00181                     This is because it can be annoying that the gallery keeps scrolling
00182                     away from a colour which you were about to apply to the selection (though
00183                     you'd be better off dragging the colour, rather than selecting different
00184                     objects in this case)
00185 
00186     Notes:          Normal preference, available from the options dialogue.
00187     SeeAlso:        ColourSGallery
00188 
00189 ********************************************************************************************/
00190 
00191 #ifdef WEBSTER
00192 // In Webster don't scroll to the selected colour by default
00193 INT32 ColourSGallery::AutoScrollSelection = FALSE;
00194 #else
00195 // In Camelot do scroll to the selected colour by default
00196 INT32 ColourSGallery::AutoScrollSelection = TRUE;
00197 #endif
00198 
00199 
00200 /********************************************************************************************
00201 
00202     Preference:     ColourDisplayMode
00203     Section:        Displays
00204     Range:          0..2
00205     Purpose:        Memory of the current colour gallery display mode, saved between
00206                     sessions for convenience. Not shown in the options dialogue.
00207     SeeAlso:        ColourSGallery
00208 
00209 ********************************************************************************************/
00210 
00211 INT32 ColourSGallery::DefaultDisplayMode = 0;
00212 
00213 /********************************************************************************************
00214 
00215     Preference:     ShowDocumentColours
00216     Section:        ColourLine
00217     Range:          TRUE, FALSE (0,1)
00218     Purpose:        Memory of the current state of showing document colours in the colour
00219                     line.
00220     SeeAlso:        ColourSGallery
00221 
00222 ********************************************************************************************/
00223 
00224 // Webster and Camelot's default should be the same (True).
00225 BOOL ColourSGallery::ShowDocumentColours = TRUE;
00226 
00227 
00228 /********************************************************************************************
00229 
00230     Preference:     ShowNetscapeColours
00231     Section:        ColourLine
00232     Range:          TRUE, FALSE (0,1)
00233     Purpose:        Memory of the current state of showing Netscape colours in the colour
00234                     line.
00235                     Webster needs to default to True.
00236     SeeAlso:        ColourSGallery
00237 
00238 ********************************************************************************************/
00239 
00240 // True if want Netscape colours being shown in colour line
00241 // Webster only at present
00242 BOOL ColourSGallery::ShowNetscapeColours = TRUE;
00243 
00244 /********************************************************************************************
00245 
00246     Preference:     Path
00247     Section:        Palette
00248     Range:          0 .. 256 characters
00249     Purpose:        The path to load the palettes from. Defaults to blank which means alongside
00250                     the exe.
00251     SeeAlso:        ColourSGallery
00252 
00253 ********************************************************************************************/
00254 
00255 String_256 ColourSGallery::PalettePath = TEXT("");
00256 
00257 
00258 /********************************************************************************************
00259 
00260 >   SGColourDragTarget::SGColourDragTarget(DialogOp *TheDialog, CGadgetID TheGadget = NULL)
00261      
00262     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00263     Created:    20/3/95
00264     Inputs:     TheDialog - The kernel dialog in which the target exists
00265                 TheGadget - The gadget within that dialogue which is the target
00266 
00267     Purpose:    Constructor
00268 
00269 ********************************************************************************************/
00270 
00271 SGColourDragTarget::SGColourDragTarget(DialogOp *TheDialog, CGadgetID TheGadget)
00272                     : SGListDragTarget(TheDialog, TheGadget)
00273 {
00274     ERROR3IF(!TheDialog->IsKindOf(CC_RUNTIME_CLASS(ColourSGallery)),
00275             "You can only use SGColourDragTargets with ColourSGallery dialogues!");
00276 }
00277 
00278 
00279 
00280 /********************************************************************************************
00281 
00282     BOOL SGColourDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
00283                                         OilCoord *pMousePos, KeyPress* pKeyPress)
00284 
00285     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00286     Created:    20/3/95
00287     Inputs:     Event - Indicates what has happened
00288                 pDragInfo - points to drag information describing this drag. This
00289                 should be a ColourDragInformation or derivation thereof
00290                 pMousePos - points to information on the current mouse position, in OIL coords
00291                 pKeyPress - NULL, or if for a keypress event, keypress information
00292 
00293     Returns:    TRUE to claim the event, FALSE to let it through to other targets
00294 
00295     Purpose:    Event Handler for SuperGallery listitem drag events. Overrides the
00296                 base class handler to enable it to sort out the node being dragged
00297                 for colour drags.
00298 
00299 ********************************************************************************************/
00300 
00301 BOOL SGColourDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
00302                                     OilCoord *pMousePos, KeyPress* pKeyPress)
00303 {
00304     if (!pDragInfo->IsKindOf(CC_RUNTIME_CLASS(ColourDragInformation)))
00305         return(FALSE);
00306 
00307     SGDisplayNode *DraggedNode = NULL;
00308     BOOL IsSimpleColourDrag = FALSE;
00309 
00310     if (IS_A(pDragInfo, ColourDragInformation))
00311     {
00312         ColourDragInformation *ColourDragInfo = (ColourDragInformation *) pDragInfo;
00313 
00314         SuperGallery *ParentGallery = (SuperGallery *)TargetDialog;
00315 
00316         IsSimpleColourDrag = TRUE;
00317 
00318         // Search the display tree for an item which displays the dragged IndexedColour
00319         IndexedColour *DraggedColour = ColourDragInfo->GetInitiallyDraggedColour();
00320 
00321         // If the colour is NULL, it's "no colour" (or possibly some weird library colour which
00322         // we didn't start the drag of, because we'd use a GalleryColourDragInfo), so ignore it
00323         if (DraggedColour == NULL)
00324             return(FALSE);
00325 
00326         SGDisplayRoot *DisplayTree = ParentGallery->GetDisplayTree();
00327         if (DisplayTree == NULL)        // No tree?!
00328             return(FALSE);
00329 
00330         // Scan the display tree for the document in which the colour resides, to find
00331         // the display item that references the colour. If we weren't given a parent
00332         // document, then we'll scan the entire thing.
00333         // If we find it, we exit this bit with DraggedNode pointing at the relevant
00334         // SGDisplayNode item for it, and drop through to the regular handler
00335         BOOL Found = FALSE;
00336 
00337         SGDisplayNode *TheGroup = NULL;     // Find an appropriate group to start searching
00338         if (ColourDragInfo->GetParentDoc() != NULL)
00339         {
00340             TheGroup = DisplayTree->FindSubtree(ParentGallery,
00341                                 ((ColourDragInformation *) pDragInfo)->GetParentDoc(), NULL);
00342         }
00343         else
00344             TheGroup = DisplayTree->GetChild();
00345 
00346         DocColour *TheDocCol;
00347         while (TheGroup != NULL && !Found)
00348         {
00349             DraggedNode = TheGroup->GetChild();
00350             while (DraggedNode != NULL)
00351             {
00352                 TheDocCol = ((SGDisplayColour *)DraggedNode)->GetDisplayedColour();
00353                 if (TheDocCol != NULL && TheDocCol->FindParentIndexedColour() == DraggedColour)
00354                 {
00355                     Found = TRUE;
00356                     break;
00357                 }
00358 
00359                 DraggedNode = DraggedNode->GetNext();
00360             }
00361 
00362             TheGroup = TheGroup->GetNext();
00363         }
00364 
00365         if (!Found)         // No colour matching that description is in the gallery
00366             return(FALSE);
00367     }
00368     else if (IS_A(pDragInfo, GalleryColourDragInfo))
00369     {
00370         DraggedNode = ((GalleryColourDragInfo *)pDragInfo)->GetDraggedColour();
00371     }
00372     // else ignore the drag (as DraggedNode will still be NULL)
00373 
00374     if (DraggedNode != NULL)
00375     {
00376         switch(Event)
00377         {
00378             case DRAGEVENT_COMPLETED:
00379                 HandleDragCompleted((SuperGallery *) TargetDialog,
00380                                     DraggedNode, pMousePos, IsSimpleColourDrag);
00381                 return(TRUE);
00382 
00383 
00384             case DRAGEVENT_MOUSESTOPPED:
00385             case DRAGEVENT_MOUSEMOVED:
00386             case DRAGEVENT_MOUSEIDLE:
00387                 // Call a subroutine to work out and set our current cursor shape
00388                 return(DetermineCursorShape((SuperGallery *) TargetDialog,
00389                                             DraggedNode, pMousePos));
00390             default:
00391                 break;
00392         }
00393     }
00394 
00395     // Otherwise, we aren't interested in the event, so we don't claim it
00396     return(FALSE);
00397 }
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 /********************************************************************************************
00408 
00409 >   void GalleryColourDragInfo::GalleryColourDragInfo() 
00410      
00411     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00412     Created:    16/2/95       
00413 
00414     Purpose:    Default constructor - do not call this constructor
00415 
00416 ********************************************************************************************/
00417 
00418 GalleryColourDragInfo::GalleryColourDragInfo()
00419 {
00420     ERROR3("Default GalleryColourDragInfo constructor called"); 
00421 }
00422 
00423 
00424 
00425 /********************************************************************************************
00426 
00427 >   GalleryColourDragInfo::GalleryColourDragInfo(Document *pDocument, SGDisplayColour *pSourceItem,
00428                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00429                                             BOOL IsAdjust = FALSE)
00430     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00431     Created:    16/2/95       
00432 
00433     Inputs:     pDocument   - The document in which the colour lives
00434                 pSourceItem - The gallery item from which the drag originated
00435                 pMouseInfo  - The mouse info which made the item start the drag
00436                 pMiscInfo   - The MiscInfo which accompanied the mouse event
00437                 IsAdjust    - TRUE if this is an adjust drag
00438 
00439     Purpose:    Constructor - use this one for "document colours" - ones that already live
00440                 in a document. The Display item's colour MUST reference an IndexedColour.
00441 
00442 ********************************************************************************************/
00443 
00444 GalleryColourDragInfo::GalleryColourDragInfo(Document *pDocument, SGDisplayColour *pSourceItem,
00445                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00446                                             BOOL IsAdjust)
00447                       : ColourDragInformation(pSourceItem->GetDisplayedColour()->FindParentIndexedColour(),
00448                                                 IsAdjust, pDocument)
00449 {
00450     ERROR3IF(pSourceItem == NULL || pMouseInfo == NULL || pMiscInfo == NULL,
00451                 "GalleryColourDragInfo constructor: Illegal NULL param");
00452 
00453     SourceItem  = pSourceItem;  // Copy the source item pointer
00454 
00455     MouseInfo   = *pMouseInfo;  // Duplicate the structures (they may cease to exist
00456     MiscInfo    = *pMiscInfo;   // soon after the drag is started)
00457 }
00458 
00459 
00460 
00461 /********************************************************************************************
00462 
00463 >   GalleryColourDragInfo::GalleryColourDragInfo(SGDisplayColour *pSourceItem,
00464                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00465                                             BOOL IsAdjust = FALSE)
00466      
00467     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00468     Created:    16/2/95       
00469 
00470     Inputs:     pSourceItem - The gallery item from which the drag originated
00471                 pMouseInfo  - The mouse info which made the item start the drag
00472                 pMiscInfo   - The MiscInfo which accompanied the mouse event
00473                 IsAdjust    - TRUE if this is an adjust drag
00474 
00475     Purpose:    Constructor - use this for drags of "library colours" (ones with
00476                 no parent document)
00477 
00478 ********************************************************************************************/
00479 
00480 GalleryColourDragInfo::GalleryColourDragInfo(SGDisplayColour *pSourceItem,
00481                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00482                                             BOOL IsAdjust)
00483                       : ColourDragInformation(pSourceItem->GetDisplayedColour(), IsAdjust,
00484                                                 NULL, pSourceItem->IsASpotColour())
00485 {
00486     ERROR3IF(pSourceItem == NULL || pMouseInfo == NULL || pMiscInfo == NULL,
00487                 "GalleryColourDragInfo constructor: Illegal NULL param");
00488 
00489     // Fill in the base class' name member, which we passed NULL for in the construction above
00490     String_256 Bob;
00491     pSourceItem->GetNameText(&Bob);
00492     Bob.Left(&ColourName, 63);
00493 
00494     SourceItem  = pSourceItem;  // Copy the source item pointer
00495 
00496     MouseInfo   = *pMouseInfo;  // Duplicate the structures (they may cease to exist
00497     MiscInfo    = *pMiscInfo;   // soon after the drag is started)
00498 }
00499 
00500 
00501 
00502 /********************************************************************************************
00503 
00504 >   virtual void GalleryColourDragInfo::OnClick(INT32 Flags, POINT Point) 
00505      
00506     Author:     Chris_Snook (Xara Group Ltd) <camelotdev@xara.com>
00507     Created:    12/1/95       
00508     Inputs:     -
00509     Outputs:    -
00510     Returns:    -
00511     Purpose:    This is called if a drag was attempted but never started because it was a 
00512                 click all along. It calls back the SourceItem SGDisplayColour, to get it
00513                 to handle the click. 
00514     Errors:     -
00515     SeeAlso:    -
00516 
00517 ********************************************************************************************/
00518 
00519 void GalleryColourDragInfo::OnClick(INT32 Flags, POINT Point)
00520 {
00521     if (SourceItem != NULL)
00522         SourceItem->DragWasReallyAClick(&MouseInfo, &MiscInfo);
00523 }
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 /***********************************************************************************************
00534 
00535 >   SGDisplayColour::SGDisplayColour()
00536 
00537     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00538     Created:    28/10/94
00539 
00540     Purpose:    SGDisplayColour constructor
00541                 DON'T call this constructor. Call the other constructor
00542 
00543 ***********************************************************************************************/
00544 
00545 SGDisplayColour::SGDisplayColour()
00546 {
00547     // We don't like people calling this constructor, but we have to put up with it
00548     // now that we have a derived class.
00549 }
00550 
00551 
00552 
00553 /***********************************************************************************************
00554 
00555 >   SGDisplayColour::SGDisplayColour(IndexedColour *ColourToDisplay)
00556 
00557     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00558     Created:    28/10/94
00559 
00560     Inputs:     ColourToDisplay - The colour this item will display
00561 
00562     Purpose:    SGDisplayColour constructor
00563 
00564 ***********************************************************************************************/
00565 
00566 SGDisplayColour::SGDisplayColour(IndexedColour *ColourToDisplay)
00567 {
00568     TheColour.MakeRefToIndexedColour(ColourToDisplay);
00569 }
00570 
00571 
00572 
00573 /***********************************************************************************************
00574 
00575 >   virtual INT32 SGDisplayColour::CompareTo(SGDisplayNode *Other, INT32 SortKey)
00576 
00577     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00578     Created:    10/4/95
00579 
00580     Inputs:     Other - the Colour to compare this Colour to
00581                 SortKey - An integer identifying how to compare the items
00582                     0 = No sorting (always returns 0)
00583                     1 = Sort-by-name
00584                     2 = Sort-by-hue
00585                     3 = Sort-by-intensity
00586                     4 = Sort-by-model
00587 
00588     Returns:    negative (I am lesser), 0 (we are equal), or positive (I am greater)
00589 
00590     Purpose:    Compares this Colour to the 'other' Colour, to determine their relative positions
00591                 in the display tree. Returns a value which usually indicates that the other
00592                 Colour should be inserted before (-1, or 0) or after (+1) this item.
00593 
00594     SeeAlso:    SGDisplayNode::CompareTo
00595 
00596 ***********************************************************************************************/
00597 
00598 const INT32 SGSORTKEY_BYHUE = 2;
00599 const INT32 SGSORTKEY_BYINTENSITY = 3;
00600 const INT32 SGSORTKEY_BYMODEL = 4;
00601 
00602 INT32 SGDisplayColour::CompareTo(SGDisplayNode *Other, INT32 SortKey)
00603 {
00604     ERROR3IF(Other == NULL, "Illegal NULL parameter");
00605 
00606     ERROR3IF(!Other->IsKindOf(CC_RUNTIME_CLASS(SGDisplayColour)),
00607                 "SGDisplayColour::CompareTo - The other item's not a colour!");
00608 
00609     DocColour *OtherCol = ((SGDisplayColour *)Other)->GetDisplayedColour();
00610     DocColour *ThisCol  = GetDisplayedColour();
00611 
00612     switch (SortKey)
00613     {
00614         case SGSORTKEY_BYNAME:
00615             {
00616                 IndexedColour *OtherColIx = OtherCol->FindParentIndexedColour();
00617                 IndexedColour *ThisColIx  = ThisCol->FindParentIndexedColour();
00618 
00619                 // Safety check - if either colour is NULL, then return "equal"
00620                 if (OtherColIx == NULL || ThisColIx == NULL)
00621                     return(0);
00622 
00623                 // We override the base class name comparison, because it is forced to
00624                 // actually copy the names first! This one just compares them in-place
00625                 return(ThisColIx->GetName()->CompareTo( (TCHAR *) (*(OtherColIx->GetName())) ) );
00626             }
00627             break;
00628 
00629 
00630         case SGSORTKEY_BYHUE:
00631         {
00632             ColourContextHSVT   *ColContext;
00633             ColourHSVT  ResultCol;
00634             ColourValue Hue1;
00635 
00636             Document *ParentDoc = ((SGDisplayGroup *)GetParent())->GetParentDocument();
00637 
00638             // Get a default context, or if ParentDoc != NULL, the current context for the doc.
00639             ColContext = (ColourContextHSVT *) ColourManager::GetColourContext(COLOURMODEL_HSVT, ParentDoc);
00640             if (ColContext == NULL)
00641                 return(0);
00642 
00643             // Convert the 2 colours to HSV and compare their Hue values
00644             ColContext->ConvertColour(ThisCol, (ColourGeneric *) &ResultCol);
00645             Hue1 = ResultCol.Hue;
00646 
00647             ColContext->ConvertColour(OtherCol, (ColourGeneric *) &ResultCol);
00648 
00649             if (Hue1 < ResultCol.Hue)
00650                 return(-1);
00651 
00652             return((Hue1 == ResultCol.Hue) ? 0 : 1);
00653         }
00654 
00655 
00656         case SGSORTKEY_BYINTENSITY:
00657         {
00658             ColourContextGreyT  *ColContext;
00659             ColourGreyT         ResultCol;
00660             ColourValue         Intensity1;
00661 
00662             Document *ParentDoc = ((SGDisplayGroup *)GetParent())->GetParentDocument();
00663 
00664             // Get a default context, or if ParentDoc != NULL, the current context for the doc.
00665             ColContext = (ColourContextGreyT *) ColourManager::GetColourContext(COLOURMODEL_GREYT, ParentDoc);
00666             if (ColContext == NULL)
00667                 return(0);
00668 
00669             // Convert the 2 colours to Greyscale and compare their intensity values
00670             ColContext->ConvertColour(ThisCol, (ColourGeneric *) &ResultCol);
00671             Intensity1 = ResultCol.Intensity;
00672 
00673             ColContext->ConvertColour(OtherCol, (ColourGeneric *) &ResultCol);
00674 
00675             if (Intensity1 < ResultCol.Intensity)
00676                 return(-1);
00677 
00678             return((Intensity1 == ResultCol.Intensity) ? 0 : 1);
00679         }
00680 
00681 
00682         case SGSORTKEY_BYMODEL:
00683             return((INT32)ThisCol->GetColourModel() - (INT32)OtherCol->GetColourModel());
00684     }
00685 
00686     // No sorting (SGSORTKEY_NONE - 0), or unknown
00687     return(SGDisplayItem::CompareTo(Other, SortKey));
00688 }
00689 
00690 
00691 
00692 /********************************************************************************************
00693 
00694 >   virtual void SGDisplayColour::GetNameText(String_256 *Result)
00695 
00696     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00697     Created:    9/3/95
00698 
00699     Outputs:    On exit, the string pointed at by Result will contain either a blank
00700                 string, or the name text associated with this item (if any)
00701 
00702     Purpose:    To determine a name string for this node. Generally, this is used for
00703                 a simple mechanism which searches for display items whose names match
00704                 given search parameters in some way. It is also used in libraries to
00705                 provide default redraw methods.
00706 
00707     SeeAlso:    SGDisplayColour::GetFullInfoText
00708 
00709 ********************************************************************************************/
00710 
00711 void SGDisplayColour::GetNameText(String_256 *Result)
00712 {
00713     ERROR3IF(Result == NULL, "Illegal NULL param");
00714 
00715     IndexedColour *ParentCol = TheColour.FindParentIndexedColour();
00716     if (ParentCol != NULL)
00717         *Result = *(ParentCol->GetName());
00718     else
00719         Result->MakeMsg(_R(IDS_UNNAMEDCOLOUR));
00720 }
00721 
00722 
00723 
00724 /********************************************************************************************
00725 
00726 >   virtual void SGDisplayColour::GetFullInfoText(String_256 *Result)
00727 
00728     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00729     Created:    9/3/95
00730 
00731     Outputs:    On exit, the string pointed at by Result will contain either a blank
00732                 string, or the full-information text associated with this item (if any)
00733 
00734     Purpose:    To determine a full-info string for this node. Generally, this is used for
00735                 a simple mechanism which searches for display items whose info matches
00736                 given search parameters in some way. It is also used in libraries to
00737                 provide default redraw methods.
00738 
00739     SeeAlso:    SGDisplayColour::GetNameText
00740 
00741 ********************************************************************************************/
00742 
00743 void SGDisplayColour::GetFullInfoText(String_256 *Result)
00744 {
00745     ERROR3IF(Result == NULL, "Illegal NULL param");
00746 
00747     *Result = TEXT("");     // Set a safe default
00748 
00749     // Generate an info string of the form:
00750     // <ColModel> (<components>) [, <tint/link/spot information>] [, not in use]
00751     // e.g.     "HSV(324, 80, 75), Linked to Red"
00752 
00753     String_256 Info(TEXT(""));
00754 
00755     ColourContext *cc = ColourContext::GetGlobalDefault(TheColour.GetColourModel());
00756     ERROR3IF(cc == NULL, "Default colour context is NULL!?");
00757 
00758     ColourGeneric col;
00759     TheColour.GetSourceColour(&col);
00760     cc->GetModelName(&Info);
00761 
00762     String_128  TempStr(TEXT("("));
00763     String_16   CompStr;
00764     if (cc->GetComponentName(1, NULL))
00765     {
00766         double CompVal;
00767         if (TheColour.GetColourModel() == COLOURMODEL_HSVT)
00768             CompVal = (col.Component1.MakeDouble()) * 360.0;
00769         else
00770             CompVal = (col.Component1.MakeDouble()) * 100.0;
00771 
00772         // Convert it to a string rounded to 1 decimal place accuracy
00773         Convert::DoubleToString(CompVal, &CompStr, 1);
00774 
00775         TempStr += CompStr;
00776     }
00777 
00778     if (cc->GetComponentName(2, NULL))
00779     {
00780         Convert::DoubleToString(col.Component2.MakeDouble() * 100.0, &CompStr, 1);
00781         TempStr += TEXT(", ");
00782         TempStr += CompStr;
00783     }
00784 
00785     if (cc->GetComponentName(3, NULL))
00786     {
00787         Convert::DoubleToString(col.Component3.MakeDouble() * 100.0, &CompStr, 1);
00788         TempStr += TEXT(", ");
00789         TempStr += CompStr;
00790     }
00791 
00792     if (cc->GetComponentName(4, NULL))
00793     {
00794         Convert::DoubleToString(col.Component4.MakeDouble() * 100.0, &CompStr, 1);
00795         TempStr += TEXT(", ");
00796         TempStr += CompStr;
00797     }
00798 
00799     TempStr += TEXT(")");
00800     Info    += TempStr;
00801 
00802     IndexedColour *ParentCol = TheColour.FindParentIndexedColour();     // If this refs an IndexedColour...
00803     if (ParentCol != NULL)
00804     {
00805         switch(ParentCol->GetType())
00806         {
00807             case COLOURTYPE_SPOT:
00808                 TempStr.MakeMsg(_R(IDS_COLGAL_ISPOT));
00809                 Info += TempStr;
00810                 break;
00811 
00812             case COLOURTYPE_TINT:
00813                 {
00814                     ERROR3IF(ParentCol->FindLinkedParent() == NULL,
00815                             "A tint without a parent colour? Oh bums!");
00816 
00817                     if (ParentCol->TintIsShade())
00818                     {
00819                         TempStr.MakeMsg(_R(IDS_COLGAL_ISHADE),
00820                                         (TCHAR *) *(ParentCol->FindLinkedParent()->GetName()));
00821                     }
00822                     else
00823                     {
00824                         TempStr.MakeMsg(_R(IDS_COLGAL_ITINT),
00825                                         (INT32) ((ParentCol->GetTintValue().MakeDouble() + 0.005)*100),
00826                                         (TCHAR *) *(ParentCol->FindLinkedParent()->GetName()));
00827                     }
00828                     Info += TempStr;
00829                 }
00830                 break;
00831 
00832             case COLOURTYPE_LINKED:
00833                 {
00834                     ERROR3IF(ParentCol->FindLinkedParent() == NULL,
00835                             "A linked colour without a parent colour? Oh bums!");
00836 
00837                     TempStr.MakeMsg(_R(IDS_COLGAL_ILINKED),
00838                         (TCHAR *) *(ParentCol->FindLinkedParent()->GetName()));
00839                     Info += TempStr;
00840                 }
00841                 break;
00842 
00843             default:
00844                 break;
00845         }
00846 
00847 
00848         SGDisplayGroup *DocumentGroup = (SGDisplayGroup *) GetParent();
00849         ERROR3IF(DocumentGroup == NULL, "SGallery DisplayTree linkage corruption detected");
00850 
00851         Document *ScopeDoc = DocumentGroup->GetParentDocument();
00852         ERROR3IF(ScopeDoc == NULL, "SGallery group is not for a document! Unimplemented! Eek!");
00853 
00854         ColourList *ParentColList = ScopeDoc->GetIndexedColours();
00855         ERROR3IF(ParentColList == NULL, "A document with no colour list? Now I've seen it all");
00856 
00857         if (!ParentColList->IsColourInUseInDoc(ParentCol, TRUE))
00858         {
00859             // Add ' (not in use)' for any colour not currently used in the
00860             // document, or as a linked-colour parent
00861             TempStr.MakeMsg(_R(IDS_COLGAL_INOTUSED));
00862             Info += TempStr;
00863         }
00864     }
00865 
00866     *Result = Info;
00867 }
00868 
00869 
00870 
00871 /***********************************************************************************************
00872 
00873 >   virtual BOOL SGDisplayColour::IsALibraryColour(void) const
00874 
00875     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00876     Created:    7/8/96
00877 
00878     Inputs:     -
00879     Returns:    FALSE if this is a base-class SGDisplayColour (IndexedColour)
00880                 TRUE  if this is a derived class SGDisplayLibColour (library DocColour)
00881 
00882     Purpose:    Proper virtual-function method for differentiating between IndexedColour
00883                 and library DocColour gallery display items.
00884 
00885     Notes:      Always returns FALSE
00886 
00887 ***********************************************************************************************/
00888 
00889 BOOL SGDisplayColour::IsALibraryColour(void) const
00890 {
00891     return(FALSE);
00892 }
00893 
00894 
00895 
00896 /***********************************************************************************************
00897 
00898 >   virtual BOOL SGDisplayColour::IsASpotColour(void)
00899 
00900     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00901     Created:    2/9/96
00902 
00903     Inputs:     -
00904     Returns:    FALSE if this is a normal colour
00905                 TRUE  if this is a spot colour
00906 
00907     Purpose:    Determine if the displayed colour is a normal or spot colour
00908 
00909 ***********************************************************************************************/
00910 
00911 BOOL SGDisplayColour::IsASpotColour(void)
00912 {
00913     if (TheColour.FindParentIndexedColour() != NULL)
00914     {
00915         if (TheColour.FindParentIndexedColour()->IsSpotOrTintOfSpot())
00916             return(TRUE);
00917     }
00918 
00919     return(FALSE);
00920 }
00921 
00922 
00923 
00924 /***********************************************************************************************
00925 
00926 >   void SGDisplayColour::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo)
00927 
00928     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00929     Created:    13/1/95
00930 
00931     Inputs:     FormatInfo - The formatting info from which to calculate my position/size
00932                 MiscInfo    - The MiscInfo, as usual
00933 
00934     Outputs:    member variable FormatRect - is returned filled in with the size/position of
00935                 this colour item's display area. This is dependent upon the current display
00936                 mode and format state
00937 
00938     Purpose:    Shared code for colour items to calculate where they will appear in the
00939                 grand scheme of things
00940 
00941     Scope:      private (to sgcolour.cpp, for use of SGDisplayColour class only)
00942 
00943 ***********************************************************************************************/
00944 
00945 void SGDisplayColour::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo)
00946 {
00947     const INT32 SGC_FullInfoWidth = SG_InfiniteWidth; //300000;
00948 
00949     INT32 XSize;
00950     INT32 YSize;
00951 
00952     // Note: The text is usually something like 9 point, so a minimum Y size to fit text
00953     // in is going to be around 12 point (12000 millipoints)
00954 
00955     switch (MiscInfo->DisplayMode)
00956     {
00957         case 1:                     // 1 - Full Info
00958             XSize = GridLock(MiscInfo, SGC_FullInfoWidth);
00959             YSize = GridLock(MiscInfo, SG_DefaultSmallIcon);
00960             break;
00961 
00962         case 2:                     // 2 - Icon only, no text at all
00963             XSize = YSize = GridLock(MiscInfo, SG_DefaultLargeIcon);
00964             break;
00965 
00966         default:                    // 0 (Default) - Small icon with name
00967             XSize = GridLock(MiscInfo, SG_ColourNameWidth);
00968             YSize = GridLock(MiscInfo, SG_DefaultSmallIcon);
00969             break;
00970     }
00971 
00972     CalculateFormatRect(FormatInfo, MiscInfo, XSize, YSize);
00973 }
00974 
00975 
00976 /***********************************************************************************************
00977 
00978 >   void DrawCircle(RenderRegion *Renderer, DocRect &BoundRect)
00979 
00980     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00981     Created:    16/6/96
00982 
00983     Inputs:     Renderer - The render region to render into
00984                 BoundRect - The bounding rectangle to draw the circle into
00985 
00986     Purpose:    Draws a circle filling the width of the given rectangle,
00987                 using the current render region attributes.
00988 
00989     Scope:      private
00990 
00991 ***********************************************************************************************/
00992 
00993 void DrawCircle(RenderRegion *Renderer, DocRect &BoundRect)
00994 {
00995     // WEBSTER - markn 23/1/97
00996     // No Circles required.
00997     //
00998 #ifndef WEBSTER
00999     const INT32 CircleSize = BoundRect.Width() / 2;
01000     const INT32 CPDist = (const INT32) ( ((double)CircleSize) * 0.552 );
01001 
01002     Path Circle;
01003     Circle.Initialise(12, 12);
01004     Circle.FindStartOfPath();
01005 
01006     DocCoord Center(BoundRect.lo.x + BoundRect.Width()/2,
01007                     BoundRect.lo.y + BoundRect.Height()/2);
01008 
01009     Circle.InsertMoveTo(DocCoord(Center.x+CircleSize, Center.y));
01010     Circle.InsertCurveTo(DocCoord(Center.x+CircleSize, Center.y+CPDist),
01011                             DocCoord(Center.x+CPDist, Center.y+CircleSize),
01012                             DocCoord(Center.x, Center.y+CircleSize));
01013     Circle.InsertCurveTo(DocCoord(Center.x-CPDist, Center.y+CircleSize),
01014                             DocCoord(Center.x-CircleSize, Center.y+CPDist),
01015                             DocCoord(Center.x-CircleSize, Center.y));
01016     Circle.InsertCurveTo(DocCoord(Center.x-CircleSize, Center.y-CPDist),
01017                             DocCoord(Center.x-CPDist, Center.y-CircleSize),
01018                             DocCoord(Center.x, Center.y-CircleSize));
01019     Circle.InsertCurveTo(DocCoord(Center.x+CPDist, Center.y-CircleSize),
01020                             DocCoord(Center.x+CircleSize, Center.y-CPDist),
01021                             DocCoord(Center.x+CircleSize, Center.y));
01022 
01023     Circle.IsFilled = TRUE;
01024 
01025     Renderer->DrawPath(&Circle);                // and draw it
01026 #endif // WEBSTER
01027 }
01028 
01029 
01030 
01031 /***********************************************************************************************
01032 
01033 >   virtual void SGDisplayColour::HandleRedraw(SGRedrawInfo *RedrawInfo,
01034                                                 SGFormatInfo *FormatInfo)
01035 
01036     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01037     Created:    13/1/95
01038 
01039     Inputs:     RedrawInfo  - The information on the kernel-rendered redraw area
01040                 FormatInfo  - The formatting information structure
01041 
01042                 member variable FormatRect should be set up (before calling this method)
01043                 to be the rectangle in which to draw this item
01044 
01045     Purpose:    SGDisplayColour item redraw method - removed from the main HandleEvent
01046                 method merely to make the code tidier.
01047 
01048     Scope:      private
01049 
01050 ***********************************************************************************************/
01051 
01052 void SGDisplayColour::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo)
01053 {
01054     StartRendering(RedrawInfo, MiscInfo);
01055 
01056     DocRect MyRect(FormatRect);
01057 
01058     RenderRegion *Renderer = RedrawInfo->Renderer;
01059 
01060     INT32 OnePixel  = (INT32) DevicePixels(MiscInfo, 1);
01061     INT32 TwoPixels = (INT32) DevicePixels(MiscInfo, 2);
01062 
01063     DocRect IconRect(MyRect);       // Create a square icon at the left end of our rectangle
01064     IconRect.hi.x = IconRect.lo.x + IconRect.Height();
01065     MyRect.lo.x = IconRect.hi.x + TwoPixels;
01066 
01067     // Redraw the icon
01068     GridLockRect(MiscInfo, &IconRect);  
01069 
01070     Renderer->SetLineWidth(0);
01071     Renderer->SetLineColour(RedrawInfo->Transparent);
01072 
01073     // If selected, we have a 3-pixel-thick selection border
01074     // Otherwise (as is now the case) we have a single-pixel black border
01075     // We draw border "lines" using rectangle fills, else it screws pixel alignment
01076     if (!Flags.Selected)
01077         IconRect.Inflate(-TwoPixels);
01078 
01079     IndexedColour *IxCol = TheColour.FindParentIndexedColour();
01080 
01081     // Draw (selection border and) border
01082     // The patch is normally a square (process colour), but for spot colours
01083     // is drawn as a circle, in order to make the distinction more obvious
01084     //
01085     // WEBSTER - markn 23/1/97
01086     // No Circles required.
01087     //
01088     DocColour black(COLOUR_BLACK);
01089     Renderer->SetFillColour(black);
01090 #ifndef WEBSTER
01091     if (IsASpotColour())
01092     {
01093         IconRect.Inflate(-OnePixel);
01094         DrawCircle(Renderer, IconRect);
01095     }
01096     else
01097 #endif // WEBSTER
01098         Renderer->DrawRect(&IconRect);              // And draw it
01099 
01100     // Now deflate further, to get inside the selection & border...
01101     IconRect.Inflate((Flags.Selected)  ? -(TwoPixels+OnePixel) : -OnePixel);
01102 
01103     // Draw the colour patch (icon)
01104     // Save and restore the context while using TheColour to fill with. This is so that
01105     // the renderer no longer references the IndexedColour, so that GetFullInfoText will
01106     // put the text '(not in use)' on the end of colours which aren't used in the document!
01107     Renderer->SaveContext();
01108     Renderer->SetFillColour(TheColour);         // Fill with colour to display
01109 
01110     // The patch is normally a square (process colour), but for spot colours
01111     // is drawn as a circle, in order to make the distinction more obvious
01112     //
01113     // WEBSTER - markn 23/1/97
01114     // No Circles required.
01115     //
01116 #ifndef WEBSTER
01117     if (IsASpotColour())
01118         DrawCircle(Renderer, IconRect);
01119     else
01120 #endif // WEBSTER
01121         Renderer->DrawRect(&IconRect);              // And draw it
01122     Renderer->RestoreContext();
01123 
01124     // Redraw the name text, if there is room to the right of the icon
01125     if (MyRect.lo.x < MyRect.hi.x)
01126     {
01127         GridLockRect(MiscInfo, &MyRect);
01128 
01129 //      IndexedColour *ParentCol = TheColour.FindParentIndexedColour();
01130 
01131         if (Flags.Selected)
01132         {
01133             // Fill the entire background with the 'selected' colour, so we don't
01134             // get gaps between bits of text or uneven rectangles in multiple selections
01135             Renderer->SetFillColour(RedrawInfo->SelBackground);
01136             Renderer->DrawRect(&MyRect);
01137 
01138             Renderer->SetFixedSystemTextColours(&RedrawInfo->SelForeground, &RedrawInfo->SelBackground);
01139 
01140             if (IxCol != NULL)  // Only do this for IndexedColours (i.e. not derived class Library colours)
01141             {
01142                 // If this item represents the current line colour, then place a vertical line between the icon
01143                 // and the text to indicate this fact.
01144                 DocColour *LineCol;
01145                 ColourManager::GetCurrentLineAndFillColours(&LineCol, NULL);
01146 
01147                 if (LineCol != NULL && LineCol->FindParentIndexedColour() == TheColour.FindParentIndexedColour())
01148                 {
01149                     // This item is selected and is the current line colour. Put a mark in to indicate this
01150                     DocColour black(COLOUR_BLACK);
01151                     Renderer->SetLineColour(black);
01152                     Renderer->SetLineWidth(TwoPixels);
01153                     Renderer->DrawLine(MyRect.lo, DocCoord(MyRect.lo.x, MyRect.hi.y));
01154                 }
01155             }
01156         }
01157         else
01158             Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background);
01159 
01160         MyRect.lo.x += SG_GapBeforeText;    // Leave a small gap before text begins
01161 
01162         String_256 Name;
01163         GetNameText(&Name);                 // Get the name string
01164 
01165         if (MiscInfo->DisplayMode == 1)     // If in Full Info mode...
01166         {
01167             DocRect TextRect(MyRect);
01168 
01169             // Reserve space for the name (clip it if it won't fit)
01170             if (TextRect.hi.x - TextRect.lo.x > SG_ColourNameWidth)
01171                 TextRect.hi.x = TextRect.lo.x + SG_ColourNameWidth;
01172 
01173             // Draw the name text next to the icon
01174             Renderer->DrawFixedSystemText(&Name, TextRect);
01175             
01176             // Move to the right, to fill the remaining space with information
01177             // (Leave a 6-pixel gap in case the name didn't all fit in the available space)
01178             TextRect.lo.x = TextRect.hi.x + DevicePixels(MiscInfo, 6);
01179             TextRect.hi.x = MyRect.hi.x;
01180             if (TextRect.lo.x < TextRect.hi.x)      // If any room left for info...
01181             {
01182                 // Get the full info description, and render it
01183