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                 GetFullInfoText(&Name);
01184                 Renderer->DrawFixedSystemText(&Name, TextRect);
01185             }
01186         }
01187         else
01188         {
01189             // Not full-info mode, so we only render the colour name next to the patch
01190             Renderer->DrawFixedSystemText(&Name, MyRect);
01191         }
01192     }
01193 
01194     StopRendering(RedrawInfo, MiscInfo);
01195 }
01196 
01197 
01198 
01199 
01200 /***********************************************************************************************
01201 
01202 >   virtual void SGDisplayColour::DragWasReallyAClick(SGMouseInfo *Mouse, SGMiscInfo *MiscInfo)
01203 
01204     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01205     Created:    16/2/95
01206 
01207     Inputs:     Mouse - The mouse info passed to the original click handler
01208                 MiscInfo - The misc info passed to the original click handler
01209 
01210     Purpose:    Handles a mouse click event. This is a callback function - drags of
01211                 colours from galleries will call this function back if the drag turns
01212                 out to just be a click.
01213 
01214     SeeAlso:    SGDisplayColour::HandleEvent; GalleryColourDragInfo::OnClick
01215 
01216 ***********************************************************************************************/
01217 
01218 void SGDisplayColour::DragWasReallyAClick(SGMouseInfo *Mouse, SGMiscInfo *MiscInfo)
01219 {
01220     // Just get default selection action to be applied for this click.
01221     // The TRUE indicates that this is a drag-click, and we previously called 
01222     // the DefaultPreDragHandler - we don't want it to do those same actions twice!
01223     DefaultClickHandler(Mouse, MiscInfo, TRUE);
01224 }
01225 
01226 
01227 
01228 /***********************************************************************************************
01229 
01230 >   virtual BOOL SGDisplayColour::HandleEvent(SGEventType EventType, void *EventInfo,
01231                                              SGMiscInfo *MiscInfo)
01232 
01233     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01234     Created:    20/10/94
01235 
01236     Inputs:     EventType - An enumerated value describing what type of event is to be processed
01237 
01238                 EventInfo - A structure describing the event (may be NULL). The exact thing
01239                             pointed at by this pointer depends upon the event type:
01240 
01241                             MonoOn
01242                             Event               Thing EventInfo points at
01243                             SGEVENT_FORMAT      (SGFormatInfo *)
01244                             SGEVENT_REDRAW      (SGRedrawInfo *)
01245                             SGEVENT_MOUSECLICK  (SGMouseInfo *)
01246                             MonoOff
01247                 Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this
01248                 information - they provide useful error/type checking, and hide the cast
01249 
01250                 MiscInfo - always provided. Contains a few useful bits of info that may be
01251                 needed for all event types.
01252 
01253     Outputs:    FormatInfo is updated as appropriate
01254 
01255     Returns:    TRUE if the event was handled successfully
01256                 FALSE if it was not
01257 
01258     Purpose:    Handles a SuperGallery DisplayTree event
01259 
01260     Notes:      This overrides the pure virtual SGDisplayNode::HandleEvent method
01261 
01262                 A node need not handle a specific event - if it does not handle it, it
01263                 should return FALSE.
01264 
01265                 Redraw and Formatting handlers should never return TRUE, as this will
01266                 prevent the event from continuing through the tree.
01267 
01268                 Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order
01269                 to pass the event dow the tree. THIS node is a leaf-node, so it doesn't.
01270 
01271     SeeAlso:    SGDisplayNode::HandleEvent
01272 
01273 ***********************************************************************************************/
01274 
01275 BOOL SGDisplayColour::HandleEvent(SGEventType EventType, void *EventInfo,
01276                                   SGMiscInfo *MiscInfo)
01277 {
01278     switch (EventType)
01279     {
01280         case SGEVENT_FORMAT:
01281             {
01282                 SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo);
01283                 CalculateMyRect(FormatInfo, MiscInfo);      // Cache our FormatRect for later use
01284             }
01285             break;
01286 
01287 
01288         case SGEVENT_REDRAW:
01289             {
01290                 DocRect MyRect(FormatRect);     // Rely on FormatRect being cached from above
01291                 SGRedrawInfo *RedrawInfo = GetRedrawInfo(EventType, EventInfo);
01292 
01293                 if (IMustRedraw(RedrawInfo))
01294                     HandleRedraw(RedrawInfo, MiscInfo);
01295             }
01296             break;      // exit and return FALSE to pass the redraw event on
01297 
01298 
01299         case SGEVENT_MOUSECLICK:
01300             {
01301                 SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo);
01302 
01303                 if (FormatRect.ContainsCoord(Mouse->Position))
01304                 {
01305                     // If the colour is in the selected document, then it is safe to
01306                     // do a colour drag - for now, it will only allow drags for the
01307                     // selected doc.
01308                     // Otherwise, the normal click action takes place.
01309                     // If the drag fails (turns into a click) then the normal click action
01310                     // takes place, passed on by the GalleryColourDragInfo::OnClick handler
01311                     SGDisplayGroup *Parent = (SGDisplayGroup *) GetParent();
01312 
01313                     if (Mouse->DoubleClick) // || Parent->GetParentDocument() != Document::GetSelected())
01314                     {
01315                         // Use the default click handler.
01316                         // However, because we assign a very special meaning to adjust-double-click (apply
01317                         // line colour) we don't want the default action (apply & close gallery) to take
01318                         // effect, so we pass in FALSE as the last parameter.
01319                         DefaultClickHandler(Mouse, MiscInfo, FALSE, FALSE);
01320                     }
01321                     else
01322                     {
01323                         DefaultPreDragHandler(Mouse, MiscInfo);
01324 
01325                         // Start a drag, but only if there are selected documents around
01326                         if (Document::GetSelected() != NULL)
01327                         {
01328                             GalleryColourDragInfo *DragCol;
01329                             DragCol = new GalleryColourDragInfo(Parent->GetParentDocument(),
01330                                                                 this, Mouse, MiscInfo,
01331                                                                 Mouse->MenuClick);
01332 
01333                             if (DragCol != NULL)
01334                                 DragManagerOp::StartDrag(DragCol, GetListWindow());
01335                         }
01336                     }
01337 
01338                     return(TRUE);       // Claim this event - nobody else can own this click
01339                 }
01340             }
01341             break;
01342 
01343 
01344         default:
01345             return(SGDisplayItem::HandleEvent(EventType, EventInfo, MiscInfo));
01346     }
01347 
01348     // Default return value: We do not claim this event, so it will be passed on to others
01349     return(FALSE);
01350 }
01351 
01352 
01353 
01354 /***********************************************************************************************
01355 
01356 >   virtual void SGDisplayColour::MoveAfter(SGDisplayNode *NodeToMove)
01357 
01358     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01359     Created:    14/3/95
01360 
01361     Inputs:     NodeToMove - the node to move
01362 
01363     Purpose:    MOVES the given node (to a different position in the DisplayTree) as the
01364                 previous (left) sibling of this node. If the node is not linked into
01365                 a tree, it is effectively just inserted.
01366 
01367     Notes:      This base class method simply delinks the item and relinks it elsewhere
01368                 in the display tree. However, derived classes will override this method
01369                 so that moving display items can have a further effect of also rearranging
01370                 the displayed "real" items. Before/After moving the real item, the
01371                 derived class can then call this baseclass method to complete the action.
01372         
01373                 Take care when moving items between groups (e.g. if an item is "moved"
01374                 from one docuemnt to another, it could be a bad thing, so be very
01375                 careful in derived classes to take appropriate action)
01376 
01377                 Any attempt to move an item after *itself* is queitly ignored
01378 
01379     Errors:     ERROR3 and quiet exit if NodeToMove == NULL
01380 
01381     SeeAlso:    SuperGallery; SGDisplayColour::InsertAfter; SGDisplayColour::AddItem
01382 
01383 ***********************************************************************************************/
01384 
01385 void SGDisplayColour::MoveAfter(SGDisplayNode *NodeToMove)
01386 {
01387     ERROR3IF(NodeToMove == NULL, "Illegal NULL param");
01388 
01389     if (NodeToMove == this)
01390         return;
01391 
01392     if (IsALibraryColour())
01393         LibraryHasBeenSorted = TRUE;
01394 
01395     DocColour *DocColToMove = ((SGDisplayColour *) NodeToMove)->GetDisplayedColour();
01396     ERROR3IF(DocColToMove == NULL, "NULL displayed colour?!");
01397 
01398     IndexedColour *ColToMove = DocColToMove->FindParentIndexedColour();
01399 
01400     IndexedColour *TargetColour = TheColour.FindParentIndexedColour();
01401     if (ColToMove == NULL || TargetColour == NULL)
01402     {
01403         // If either colour is a library colour, then no need to move colours in the
01404         // document colour list, so just move the display nodes appropriately and return.
01405         SGDisplayNode::MoveAfter(NodeToMove);
01406         return;
01407     }
01408 
01409     Document *ScopeDoc = ((SGDisplayGroup *) GetParent())->GetParentDocument();
01410     ERROR3IF(ScopeDoc == NULL, "No parent document?!");
01411 
01412     if ( ((SGDisplayGroup *) ( ((SGDisplayColour *)NodeToMove)->GetParent() ) )->GetParentDocument() !=
01413             ScopeDoc)
01414     {
01415         ERROR2RAW("Attempt to MOVE a colour between documents!");
01416         InformError();
01417         return;
01418     }
01419 
01420     ColourList *ColList = ScopeDoc->GetIndexedColours();
01421     ERROR3IF(ColList == NULL, "A document with no colour list?!");
01422     
01423     ColList->RemoveItem(ColToMove);
01424     ColList->InsertAfter(TargetColour, ColToMove);
01425 
01426     SGDisplayNode::MoveAfter(NodeToMove);
01427 
01428 // We do not need to do the following - the parent gallery will do it when it is called
01429 // with SuperGallery::AllItemsCopied. This allows us to be called many times in a row
01430 // without generating more than one broadcast.
01431 
01432 //  // Inform the world, and lock out changes in the colour gallery
01433 //  ColourSGallery *ParentGallery = (ColourSGallery *)GetParentGallery();
01434 //  BOOL OldSentState = ParentGallery->ISentTheMessage;
01435 //  ParentGallery->ISentTheMessage = TRUE;
01436 //  
01437 //  ColourManager::ColourListHasChanged(ColList);
01438 //  
01439 //  ParentGallery->ISentTheMessage = OldSentState;
01440 }
01441 
01442 
01443 
01444 /***********************************************************************************************
01445 
01446 >   virtual void SGDisplayColour::MoveBefore(SGDisplayNode *NodeToMove)
01447 
01448     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01449     Created:    14/3/95
01450 
01451     Inputs:     NodeToMove - the node to move
01452 
01453     Purpose:    MOVES the given node (to a different position in the DisplayTree) as the
01454                 previous (left) sibling of this node. If the node is not linked into
01455                 a tree, it is effectively just inserted.
01456 
01457     Notes:      This base class method simply delinks the item and relinks it elsewhere
01458                 in the display tree. However, derived classes will override this method
01459                 so that moving display items can have a further effect of also rearranging
01460                 the displayed "real" items. Before/After moving the real item, the
01461                 derived class can then call this baseclass method to complete the action.
01462         
01463                 Take care when moving items between groups (e.g. if an item is "moved"
01464                 from one docuemnt to another, it could be a bad thing, so be very
01465                 careful in derived classes to take appropriate action)
01466 
01467                 Any attempt to move an item before *itself* is queitly ignored
01468 
01469     Errors:     ERROR3 and quiet exit if NodeToMove == NULL
01470 
01471     SeeAlso:    SuperGallery; SGDisplayColour::InsertBefore; SGDisplayColour::AddItem
01472 
01473 ***********************************************************************************************/
01474 
01475 void SGDisplayColour::MoveBefore(SGDisplayNode *NodeToMove)
01476 {
01477     ERROR3IF(NodeToMove == NULL, "Illegal NULL param");
01478 
01479     if (NodeToMove == this)
01480         return;
01481 
01482     if (IsALibraryColour())
01483         LibraryHasBeenSorted = TRUE;
01484 
01485     DocColour *DocColToMove = ((SGDisplayColour *) NodeToMove)->GetDisplayedColour();
01486     ERROR3IF(DocColToMove == NULL, "NULL displayed colour?!");
01487     IndexedColour *ColToMove = DocColToMove->FindParentIndexedColour();
01488 
01489     IndexedColour *TargetColour = TheColour.FindParentIndexedColour();
01490     if (ColToMove == NULL || TargetColour == NULL)
01491     {
01492         // If either colour is a library colour, then no need to move colours in the
01493         // document colour list, so just move the display nodes appropriately and return.
01494         SGDisplayNode::MoveBefore(NodeToMove);
01495         return;
01496     }
01497 
01498     Document *ScopeDoc = ((SGDisplayGroup *) GetParent())->GetParentDocument();
01499     ERROR3IF(ScopeDoc == NULL, "No parent document?!");
01500 
01501     if ( ((SGDisplayGroup *) ( ((SGDisplayColour *)NodeToMove)->GetParent() ) )->GetParentDocument() !=
01502             ScopeDoc)
01503     {
01504         ERROR2RAW("Attempt to MOVE a colour between documents!");
01505         InformError();
01506         return;
01507     }
01508 
01509     ColourList *ColList = ScopeDoc->GetIndexedColours();
01510     ERROR3IF(ColList == NULL, "A document with no colour list?!");
01511     
01512     ColList->RemoveItem(ColToMove);
01513     ColList->InsertBefore(TargetColour, ColToMove);
01514 
01515     SGDisplayNode::MoveBefore(NodeToMove);
01516 
01517 // We do not need to do the following - the parent gallery will do it when it is called
01518 // with SuperGallery::AllItemsCopied. This allows us to be called many times in a row
01519 // without generating more than one broadcast.
01520 
01521 //  // Inform the world, and lock out changes in the colour gallery
01522 //  ColourSGallery *ParentGallery = (ColourSGallery *)GetParentGallery();
01523 //  BOOL OldSentState = ParentGallery->ISentTheMessage;
01524 //  ParentGallery->ISentTheMessage = TRUE;
01525 //  
01526 //  ColourManager::ColourListHasChanged(ColList);
01527 //  
01528 //  ParentGallery->ISentTheMessage = OldSentState;
01529 }
01530 
01531 
01532 
01533 /********************************************************************************************
01534 
01535 >   virtual BOOL SGDisplayColour::GetBubbleHelp(DocCoord *MousePos, String_256 *Result)
01536 
01537     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01538     Created:    16/4/95
01539 
01540     Inputs:     MousePos - The current mouse position. This will generally be expected
01541                 to lie inside this item's FormatRect. With it, this item can provide
01542                 help on specific areas of an item.
01543 
01544     Outputs:    On exit, if the return value is TRUE, the string pointed at by Result
01545                 will contain a bubble help string for this item
01546 
01547     Returns:    TRUE if it filled in the string, FALSE if it did not
01548                 
01549     Purpose:    Called by the parent gallery when bubble help is needed. The parent
01550                 gallery will do a hit test to determine which node contains the pointer,
01551                 and will then ask that node to supply bubble/status-line help.
01552                 
01553     Notes:      The base class returns FALSE (i.e. provides no help)
01554                 If you can provide help, then override the base class method to do so.
01555 
01556     SeeAlso:    SGDisplayNode::GetStatusLineHelp
01557 
01558 ********************************************************************************************/
01559 
01560 BOOL SGDisplayColour::GetBubbleHelp(DocCoord *MousePos, String_256 *Result)
01561 {
01562     ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params");
01563 
01564     return(FALSE);
01565 }
01566 
01567 
01568     
01569 /********************************************************************************************
01570 
01571 >   virtual BOOL SGDisplayColour::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result)
01572 
01573     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01574     Created:    16/4/95
01575 
01576     Inputs:     MousePos - The current mouse position. This will generally be expected
01577                 to lie inside this item's FormatRect. With it, this item can provide
01578                 help on specific areas of an item.
01579 
01580     Outputs:    On exit, if the return value is TRUE, the string pointed at by Result
01581                 will contain a status line help string for this item
01582 
01583     Returns:    TRUE if it filled in the string, FALSE if it did not
01584                 
01585     Purpose:    Called by the parent gallery when status line help is needed. The parent
01586                 gallery will do a hit test to determine which node contains the pointer,
01587                 and will then ask that node to supply bubble/status-line help.
01588                 
01589     Notes:      The base class returns FALSE (i.e. provides no help)
01590                 If you can provide help, then override the base class method to do so.
01591 
01592     SeeAlso:    SGDisplayNode::GetBubbleHelp
01593 
01594 ********************************************************************************************/
01595 
01596 BOOL SGDisplayColour::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result)
01597 {
01598     ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params");
01599 
01600     *Result = TEXT("");         // Empty the string, just to be safe
01601     GetNameText(Result);        // Start the string with the colour name
01602     *Result += TEXT("; ");
01603 
01604     String_64 Temp;
01605     if (IsSelected())
01606         Temp = _R(IDS_SGCOLOUR_CTRL_CLICK);         // TEXT("Ctrl-click to deselect;");
01607     else
01608         Temp = _R(IDS_SGCOLOUR_CLICK);              // TEXT("Click to select;");
01609 
01610     *Result += Temp;
01611     *Result += String_64(_R(IDS_SGCOLOUR_DOUBLE_CLICK)); // TEXT(" Double-click to apply this colour; Or drag and drop");
01612 
01613     return(TRUE);
01614 }
01615 
01616 
01617 
01618 
01619 
01620 
01621 
01622 
01623 
01624 
01625 
01626 
01627 
01628 /***********************************************************************************************
01629 
01630 >   SGDisplayLibColour::SGDisplayLibColour()
01631 
01632     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01633     Created:    7/8/96
01634 
01635     Purpose:    SGDisplayLibColour constructor
01636                 DON'T call this constructor. It ERROR3's. Call the other constructor
01637 
01638 ***********************************************************************************************/
01639 
01640 SGDisplayLibColour::SGDisplayLibColour()
01641 {
01642     ERROR3("Illegal call on default SGDisplayLibColour constructor - call the other one!");
01643     Flags.Prefix = 0;
01644     Flags.NewlineAfter = FALSE;
01645     Flags.SpotColour = FALSE;
01646 }
01647 
01648 
01649 
01650 /***********************************************************************************************
01651 
01652 >   SGDisplayLibColour::SGDisplayLibColour(DocColour *ColourToDisplay,
01653                                         StringBase *Name, PalettePrefix Prefix,
01654                                         BOOL NewlineAfter = FALSE, IsSpotColour = FALSE);
01655 
01656     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01657     Created:    7/8/96
01658 
01659     Inputs:     ColourToDisplay - The definition of the colour this item will display
01660                 Name    - The name (suffix) of this colour
01661                 Prefix  - ID of a prefix to be prepended to the name
01662                 NewlineAfter - TRUE if this item is the last in a "run" of colours
01663                         and should cause a new-line in the displayed list to produce a
01664                         tidier on screen display. This is only used in "icons only" mode.
01665                 IsSpotColour - FALSE for a normal colour, TRUE if this is a spot colour
01666 
01667     Purpose:    SGDisplayLibColour constructor
01668 
01669 ***********************************************************************************************/
01670 
01671 SGDisplayLibColour::SGDisplayLibColour(DocColour *ColourToDisplay,
01672                                         StringBase *Name, PalettePrefix Prefix,
01673                                         BOOL NewlineAfter, BOOL IsSpotColour)
01674 {
01675     ERROR3IF((INT32)Prefix < 0 || (INT32)Prefix > 0x3f, "Out of range prefix value");
01676     Flags.Prefix = ((UINT32) Prefix) & 0x3f;
01677     Flags.NewlineAfter  = NewlineAfter;
01678     Flags.SpotColour    = IsSpotColour;
01679 
01680     ERROR3IF(ColourToDisplay == NULL || Name == NULL, "Illegal NULL params");
01681     TheColour = *ColourToDisplay;
01682 
01683     // Copy the colour name. Note that we use a StringBase object an explicitly
01684     // allocate exactly the right number of characters, in order to minimise
01685     // memory usage (libraries hold thousands of colours, so even one byte less
01686     // saves kilobytes of storage over an entire library)
01687 //  INT32 Length = Name->Length();
01688     ColourName.Alloc(Name->Length());
01689     ColourName = *Name;
01690 }
01691 
01692 
01693 
01694 /********************************************************************************************
01695 
01696 >   virtual void SGDisplayLibColour::GetNameText(String_256 *Result)
01697 
01698     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01699     Created:    7/8/96
01700 
01701     Outputs:    On exit, the string pointed at by Result will contain either a blank
01702                 string, or the name text associated with this item (if any)
01703 
01704     Purpose:    To determine a name string for this node. Generally, this is used for
01705                 a simple mechanism which searches for display items whose names match
01706                 given search parameters in some way. It is also used in libraries to
01707                 provide default redraw methods.
01708 
01709     SeeAlso:    SGDisplayLibColour::GetFullInfoText
01710 
01711 ********************************************************************************************/
01712 
01713 void SGDisplayLibColour::GetNameText(String_256 *Result)
01714 {
01715     ERROR3IF(Result == NULL, "Illegal NULL param");
01716 
01717     switch((PalettePrefix) Flags.Prefix)
01718     {
01719         case PalettePrefix_Pantone:
01720             *Result = TEXT("PANTONE ");     // NOTE - all these string constants are
01721             *Result += ColourName;          // the same in all languages and changing the
01722 //          *Result += TEXT(" PC");         // exact string used here could affect the
01723             return;                         // Pantone licence
01724 
01725         case PalettePrefix_PantoneSpot:
01726             *Result = TEXT("PANTONE ");     // NOTE - all these string constants are
01727             *Result += ColourName;          // the same in all languages and changing the
01728             *Result += TEXT(" PC");         // exact string used here could affect the
01729             return;                         // Pantone licence
01730 
01731         case PalettePrefix_Focoltone:
01732             *Result = TEXT("Focoltone ");
01733             break;
01734 
01735         case PalettePrefix_Trumatch:
01736             *Result = TEXT("Trumatch ");
01737             break;
01738 
01739         case PalettePrefix_RGB:
01740             *Result = TEXT("RGB ");
01741             break;
01742 
01743         default:
01744             *Result = TEXT("");
01745             break;
01746     }
01747 
01748     *Result += ColourName;
01749 }
01750 
01751 
01752 
01753 /***********************************************************************************************
01754 
01755 >   virtual BOOL SGDisplayLibColour::HandleEvent(SGEventType EventType, void *EventInfo,
01756                                              SGMiscInfo *MiscInfo)
01757 
01758     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01759     Created:    7/8/96
01760 
01761     Inputs:     EventType - An enumerated value describing what type of event is to be processed
01762 
01763                 EventInfo - A structure describing the event (may be NULL). The exact thing
01764                             pointed at by this pointer depends upon the event type:
01765 
01766                             MonoOn
01767                             Event               Thing EventInfo points at
01768                             SGEVENT_FORMAT      (SGFormatInfo *)
01769                             SGEVENT_REDRAW      (SGRedrawInfo *)
01770                             SGEVENT_MOUSECLICK  (SGMouseInfo *)
01771                             MonoOff
01772                 Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this
01773                 information - they provide useful error/type checking, and hide the cast
01774 
01775                 MiscInfo - always provided. Contains a few useful bits of info that may be
01776                 needed for all event types.
01777 
01778     Outputs:    FormatInfo is updated as appropriate
01779 
01780     Returns:    TRUE if the event was handled successfully
01781                 FALSE if it was not
01782 
01783     Purpose:    Handles a SuperGallery DisplayTree event
01784 
01785     Notes:      This overrides the pure virtual SGDisplayNode::HandleEvent method
01786 
01787                 A node need not handle a specific event - if it does not handle it, it
01788                 should return FALSE.
01789 
01790                 Redraw and Formatting handlers should never return TRUE, as this will
01791                 prevent the event from continuing through the tree.
01792 
01793                 Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order
01794                 to pass the event dow the tree. THIS node is a leaf-node, so it doesn't.
01795 
01796     SeeAlso:    SGDisplayNode::HandleEvent
01797 
01798 ***********************************************************************************************/
01799 
01800 BOOL SGDisplayLibColour::HandleEvent(SGEventType EventType, void *EventInfo,
01801                                   SGMiscInfo *MiscInfo)
01802 {
01803     switch (EventType)
01804     {
01805         case SGEVENT_FORMAT:
01806             {
01807                 SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo);
01808                 CalculateMyRect(FormatInfo, MiscInfo);      // Cache our FormatRect for later use
01809 
01810                 // If in display mode 2, and this is the end of a pantone "page", then
01811                 // we special case it to do a "newline" at the end of the line, to
01812                 // keep pages together nicely
01813                 if (!LibraryHasBeenSorted && MiscInfo->DisplayMode == 2)
01814                 {
01815                     if (Flags.NewlineAfter)
01816                         NewLine(FormatInfo, MiscInfo);
01817                 }
01818             }
01819             break;
01820 
01821         case SGEVENT_MOUSECLICK:
01822             {
01823                 SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo);
01824 
01825                 if (FormatRect.ContainsCoord(Mouse->Position))
01826                 {
01827                     // If the colour is in the selected document, then it is safe to
01828                     // do a colour drag - for now, it will only allow drags for the
01829                     // selected doc.
01830                     // Otherwise, the normal click action takes place.
01831                     // If the drag fails (turns into a click) then the normal click action
01832                     // takes place, passed on by the GalleryColourDragInfo::OnClick handler
01833 //                  SGDisplayGroup *Parent = (SGDisplayGroup *) GetParent();
01834 
01835                     if (Mouse->DoubleClick) // || Parent->GetParentDocument() != Document::GetSelected())
01836                     {
01837                         // Use the default click handler.
01838                         // However, because we assign a very special meaning to adjust-double-click (apply
01839                         // line colour) we don't want the default action (apply & close gallery) to take
01840                         // effect, so we pass in FALSE as the last parameter.
01841                         DefaultClickHandler(Mouse, MiscInfo, FALSE, FALSE);
01842                     }
01843                     else
01844                     {
01845                         DefaultPreDragHandler(Mouse, MiscInfo);
01846 
01847                         // Don't start drags when there are no documents about
01848                         if (Document::GetSelected() != NULL)
01849                         {
01850                             GalleryColourDragInfo *DragCol;
01851                             DragCol = new GalleryColourDragInfo(this, Mouse, MiscInfo, Mouse->MenuClick);
01852 
01853                             if (DragCol != NULL)
01854                                 DragManagerOp::StartDrag(DragCol, GetListWindow());
01855                         }
01856                     }
01857 
01858                     return(TRUE);       // Claim this event - nobody else can own this click
01859                 }
01860             }
01861             break;
01862 
01863 
01864         default:
01865             return(SGDisplayColour::HandleEvent(EventType, EventInfo, MiscInfo));
01866     }
01867 
01868     // Default return value: We do not claim this event, so it will be passed on to others
01869     return(FALSE);
01870 }
01871 
01872 
01873 
01874 /***********************************************************************************************
01875 
01876 >   virtual INT32 SGDisplayLibColour::CompareTo(SGDisplayNode *Other, INT32 SortKey)
01877 
01878     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01879     Created:    7/8/96
01880 
01881     Inputs:     Other - the Colour to compare this Colour to
01882                 SortKey - An integer identifying how to compare the items
01883                     0 = No sorting (always returns 0)
01884                     1 = Sort-by-name
01885                     2 = Sort-by-hue
01886                     3 = Sort-by-intensity
01887                     4 = Sort-by-model
01888 
01889     Returns:    negative (I am lesser), 0 (we are equal), or positive (I am greater)
01890 
01891     Purpose:    Compares this Colour to the 'other' Colour, to determine their relative positions
01892                 in the display tree. Returns a value which usually indicates that the other
01893                 Colour should be inserted before (-1, or 0) or after (+1) this item.
01894 
01895     Notes:      Overrides the base Colour class compare for colour names, but otherwise
01896                 relegates control back to the base class function.
01897 
01898     SeeAlso:    SGDisplayNode::CompareTo; SGDisplayColour::CompareTo
01899 
01900 ***********************************************************************************************/
01901 
01902 INT32 SGDisplayLibColour::CompareTo(SGDisplayNode *Other, INT32 SortKey)
01903 {
01904     ERROR3IF(Other == NULL, "Illegal NULL parameter");
01905 
01906     ERROR3IF(!Other->IsKindOf(CC_RUNTIME_CLASS(SGDisplayLibColour)),
01907                 "SGDisplayLibColour::CompareTo - The other item's not a colour!");
01908 
01909     switch (SortKey)
01910     {
01911         case SGSORTKEY_BYNAME:
01912             {
01913                 // We override the base class version to use the specialised name strings that
01914                 // Library colours hold in them
01915                 SGDisplayLibColour *pOther = (SGDisplayLibColour *)Other;
01916 
01917                 return(ColourName.CompareTo( (TCHAR *) pOther->ColourName) );
01918             }
01919             break;
01920     }
01921 
01922     // Apart from sort-by-name, all sorting can be achieved by the base class code
01923     return(SGDisplayColour::CompareTo(Other, SortKey));
01924 }
01925 
01926 
01927 
01928 /***********************************************************************************************
01929 
01930 >   virtual BOOL SGDisplayLibColour::IsALibraryColour(void) const
01931 
01932     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01933     Created:    7/8/96
01934 
01935     Inputs:     -
01936     Returns:    FALSE if this is a base-class SGDisplayColour (IndexedColour)
01937                 TRUE  if this is a derived class SGDisplayLibColour (library DocColour)
01938 
01939     Purpose:    Proper virtual-function method for differentiating between IndexedColour
01940                 and library DocColour gallery display items.
01941 
01942     Notes:      Always returns TRUE
01943 
01944 ***********************************************************************************************/
01945 
01946 BOOL SGDisplayLibColour::IsALibraryColour(void) const
01947 {
01948     return(TRUE);
01949 }
01950 
01951 
01952 
01953 /***********************************************************************************************
01954 
01955 >   virtual BOOL SGDisplayLibColour::IsASpotColour(void)
01956 
01957     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01958     Created:    2/9/96
01959 
01960     Returns:    FALSE if this is a normal colour
01961                 TRUE  if this is a spot colour
01962 
01963     Purpose:    Determine if the display colour is a normal or spot colour
01964 
01965 ***********************************************************************************************/
01966 
01967 BOOL SGDisplayLibColour::IsASpotColour(void)
01968 {
01969     // If spot colours are all forced to be process, this colour is a process colour!
01970     if (IndexedColour::AreSpotsForcedToProcess())
01971         return(FALSE);
01972 
01973     return(Flags.SpotColour);
01974 }
01975 
01976 
01977 
01978 
01979 /***********************************************************************************************
01980 
01981 >   SGDisplayLibColGroup::SGDisplayLibColGroup(SuperGallery *ParentGal,
01982                                                Document *ParentDoc = NULL, Library *ParentLib = NULL)
01983 
01984     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01985     Created:    25/3/97
01986     Inputs:     ParentGal - The parent gallery of this group
01987                 ParentDoc - The parent document
01988                 ParentLib - The parent library
01989     Purpose:    Constructor
01990 
01991 ***********************************************************************************************/
01992 
01993 SGDisplayColourGroup::SGDisplayColourGroup(SuperGallery *ParentGal,
01994                                            Document *ParentDoc, Library *ParentLib)
01995                      : SGDisplayGroup(ParentGal, ParentDoc, ParentLib)
01996 {
01997 }
01998 
01999 /***********************************************************************************************
02000 
02001 >   virtual BOOL SGDisplayColourGroup::DisplayInColourLine()
02002 
02003     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02004     Created:    20/3/97
02005     Returns:    The current state of the ShowOnColourLine flag.
02006     Purpose:    To find out the current state of the showing on Colour Line flag.
02007 
02008 ***********************************************************************************************/
02009 
02010 BOOL SGDisplayColourGroup::DisplayInColourLine()
02011 {
02012     return ColourSGallery::ShowDocumentColours;
02013 }
02014 
02015 /***********************************************************************************************
02016 
02017 >   virtual BOOL SGDisplayColourGroup::SetDisplayInColourLine(BOOL NewState)
02018 
02019     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02020     Created:    25/3/97
02021     Inputs:     New state for the ShowOnColourLine flag.
02022     Returns:    The old state of the ShowOnColourLine flag.
02023     Purpose:    To set a new current state of the ShowOnColourLine flag.
02024 
02025 ***********************************************************************************************/
02026 
02027 BOOL SGDisplayColourGroup::SetDisplayInColourLine(BOOL NewState)
02028 {
02029     BOOL OldState = ColourSGallery::ShowDocumentColours;
02030     ColourSGallery::ShowDocumentColours = NewState;
02031     return OldState;
02032 }
02033 
02034 /***********************************************************************************************
02035 
02036 >   virtual BOOL SGDisplayColourGroup::ToggleDisplayInColourLine()
02037 
02038     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02039     Created:    20/3/97
02040     Returns:    The old state of the ShowOnColourLine flag.
02041     Purpose:    To toggle the current state of the ShowOnColourLine flag.
02042 
02043 ***********************************************************************************************/
02044 
02045 BOOL SGDisplayColourGroup::ToggleDisplayInColourLine()
02046 {
02047     BOOL OldState = ColourSGallery::ShowDocumentColours;
02048     if (ColourSGallery::ShowDocumentColours)
02049         ColourSGallery::ShowDocumentColours = FALSE;
02050     else
02051         ColourSGallery::ShowDocumentColours = TRUE;
02052 
02053     return OldState;
02054 }
02055 
02056 
02057 
02058 
02059 /***********************************************************************************************
02060 
02061 >   SGDisplayLibColGroup::SGDisplayLibColGroup(SuperGallery *ParentGal, PathName *LibraryFile)
02062 
02063     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02064     Created:    9/8/96
02065 
02066     Inputs:     ParentGal - The parent gallery of this group
02067                 LibraryFile - The library palette file to be displayed by this group
02068 
02069     Purpose:    Constructor
02070 
02071 ***********************************************************************************************/
02072 
02073 SGDisplayLibColGroup::SGDisplayLibColGroup(SuperGallery *ParentGal, PathName *LibraryFile)
02074                      : SGDisplayColourGroup(ParentGal)
02075 {
02076     ERROR3IF(LibraryFile == NULL, "Illegal NULL param");
02077 
02078     // Copy the group name into the base class member variable
02079     String_256 TheFile = LibraryFile->GetFileName(FALSE);
02080 
02081     String_256 UpperFile(TheFile);      // Force the name to uppercase to compare, to be safe
02082     UpperFile.toUpper();
02083 
02084     if (UpperFile == String_256(TEXT("PANTSPOT")))
02085         TitleText.MakeMsg(_R(IDS_PANTONESPOTLIB));                      // "PANTONE Spot Colours"
02086     else if (UpperFile == String_256(TEXT("PPROCESSU")))
02087         TitleText.MakeMsg(_R(IDS_PANTONEPROCESSU));                     // "PANTONE Color Name-Uncoated"
02088     else if (UpperFile == String_256(TEXT("PPROCESSC")))
02089         TitleText.MakeMsg(_R(IDS_PANTONEPROCESSC));                     // "PANTONE Color Name-Coated"
02090     else if (UpperFile == String_256(TEXT("WEB")))
02091         TitleText.MakeMsg(_R(IDS_WEBLIBRARY));                          // "Web Colours"
02092     else
02093         TitleText.MakeMsg(_R(IDS_COLOURLIBRARY), (TCHAR *)TheFile);     // "Colour library Fabby.pal"
02094 
02095     // Copy the filename into our member variable
02096     Filename = *LibraryFile;
02097 
02098     Flags.Folded        = TRUE;     // Always default to being folded
02099     Flags.Virtualised   = TRUE;     // And virtualised (we demand-load when we're unfolded)
02100 
02101     Flags.CanSelect     = TRUE;     // The group is selectable (why not?)
02102 
02103     Flags.ReadOnly      = TRUE;     // The group is read-only (won't allow items to be dropped into it)
02104 
02105     // Illegal default value to determine if value is present
02106     m_DisplayInColourLine = -1;
02107 
02108     // read a preference value for that named gallery
02109     /*BOOL ReadOk =*/ Camelot.GetPrefDirect(TEXT("ColourLine"), UpperFile, &m_DisplayInColourLine);
02110     if (m_DisplayInColourLine == -1)
02111     {
02112         // If the value wasn't present then default to TRUE for "WEB" and FALSE for others
02113         m_DisplayInColourLine = (UpperFile == String_256(TEXT("WEB")));
02114     }
02115 }
02116 
02117 
02118 
02119 /***********************************************************************************************
02120 
02121 >   virtual BOOL SGDisplayLibColGroup::CanVirtualise(void)
02122 
02123     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02124     Created:    9/8/96
02125 
02126     Returns:    TRUE
02127 
02128     Purpose:    To deterimine if this group can be virtualised to disk
02129 
02130                 Colour libraries can be virtualised
02131 
02132 ***********************************************************************************************/
02133 
02134 BOOL SGDisplayLibColGroup::CanVirtualise(void)
02135 {
02136     return(TRUE);
02137 }
02138 
02139 
02140 
02141 /***********************************************************************************************
02142 
02143 >   virtual BOOL SGDisplayLibColGroup::CanVirtualise(void)
02144 
02145     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02146     Created:    9/8/96
02147 
02148     Returns:    TRUE for success
02149 
02150     Purpose:    Virtualises this library out to disk (or rather, to be more accurate,
02151                 chucks this library out of memory. Colour libraries are totally read-only,
02152                 although while loaded we let the user reorganise them for convenience)
02153 
02154 ***********************************************************************************************/
02155 
02156 BOOL SGDisplayLibColGroup::Virtualise(void)
02157 {
02158     if(IsVirtualised())
02159         return TRUE;
02160 
02161     // Simply destroy the entire subtree from (but not including- FALSE) this node down
02162     DestroySubtree(FALSE);
02163     SetVirtualisedState(TRUE);
02164 
02165     return(TRUE);
02166 }
02167 
02168 
02169 
02170 /***********************************************************************************************
02171 
02172 >   virtual BOOL SGDisplayLibColGroup::DeVirtualise(void)
02173 
02174     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02175     Created:    9/8/96
02176 
02177     Returns:    TRUE for success
02178 
02179     Purpose:    De-Virtualises this library - loads it back in from disk
02180 
02181 ***********************************************************************************************/
02182 
02183 BOOL SGDisplayLibColGroup::DeVirtualise(void)
02184 {
02185     if(!IsVirtualised())
02186         return TRUE;
02187 
02188     // Try and find the generic palette filter to load whatever type of palette file we're using
02189     Filter *pFilter = Filter::GetFirst();
02190     while (pFilter != NULL && pFilter->FilterID != FILTERID_PALETTE)
02191         pFilter = Filter::GetNext(pFilter);
02192 
02193     CCDiskFile Infile;
02194     if (pFilter == NULL || !Infile.open(Filename, ios::in | ios::binary))
02195         return(FALSE);
02196 
02197     ((ColourSGallery *)GetParentGallery())->SetCurrentImportGroup(this);
02198 
02199     if (!pFilter->DoImport(NULL, &Infile, NULL))
02200         InformError();
02201 
02202     ((ColourSGallery *)GetParentGallery())->SetCurrentImportGroup(NULL);
02203 
02204     if (Infile.isOpen())
02205         Infile.close();
02206 
02207     SetVirtualisedState(FALSE);
02208     return(TRUE);
02209 }
02210 
02211 
02212 
02213 /***********************************************************************************************
02214 
02215 >   virtual void SGDisplayLibColGroup::ReadGroupTitle(void)
02216 
02217     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02218     Created:    9/8/96
02219 
02220     Purpose:    Reads the title for this group.
02221                 This method overrides the base class functionality merely to stop
02222                 it sitting on the TitleText member variable, in which our title is
02223                 always cached.
02224 
02225 ***********************************************************************************************/
02226 
02227 void SGDisplayLibColGroup::ReadGroupTitle(void)
02228 {
02229     // Simply override the function so that it leaves the TitleText member variable alone!
02230 }
02231 
02232 
02233 
02234 /***********************************************************************************************
02235 
02236 >   INT32 SGDisplayLibColGroup::CountChildren()
02237 
02238     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02239     Created:    19/3/97
02240     Returns:    The number of children
02241     Purpose:    Returns the number of children of this group node
02242 
02243 ***********************************************************************************************/
02244 
02245 INT32 SGDisplayLibColGroup::CountChildren()
02246 {
02247     INT32 total = 0;
02248 
02249     SGDisplayNode *pChild = GetChild();
02250     while (pChild)
02251     {
02252         total ++;
02253         pChild = pChild->GetNext();
02254     }
02255 
02256     return total;
02257 }
02258 
02259 /***********************************************************************************************
02260 
02261 >   DocColour *SGDisplayLibColGroup::GetItemColour(UINT32 Index, SGDisplayLibColour **ppLibColour = NULL)
02262 
02263     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02264     Created:    19/3/97
02265     Inputs:     The index of the item required
02266                 An optional SGDisplayLibColour pointer, defaults to null.
02267     Returns:    The DocColour associated with the specified item or NULL 
02268     Purpose:    Returns the DocColour associated with the specified item in this group or NULL.
02269                 If the SGDisplayLibColour pointer is provided it is updated with the found item
02270                 THe called can then interogate the item if so desired.
02271 
02272 ***********************************************************************************************/
02273 
02274 DocColour *SGDisplayLibColGroup::GetItemColour(UINT32 Index, SGDisplayLibColour **ppLibColour)
02275 {
02276     UINT32 item = 0;
02277 
02278     SGDisplayLibColour *pChild = (SGDisplayLibColour *)GetChild();
02279     while (pChild)
02280     {
02281         if (item == Index)
02282         {
02283             // If the caller desired it, return the lib colour item
02284             if (ppLibColour)
02285                 *ppLibColour = pChild;
02286             return pChild->GetDisplayedColour();
02287         }
02288         
02289         item ++;
02290         pChild = (SGDisplayLibColour *)pChild->GetNext();
02291     }
02292 
02293     if (ppLibColour)
02294         *ppLibColour = NULL;
02295 
02296     // we found nothing
02297     return NULL;
02298 }
02299 
02300 /***********************************************************************************************
02301 
02302 >   virtual BOOL SGDisplayLibColGroup::SetDisplayInColourLine(BOOL NewState)
02303 
02304     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02305     Created:    20/3/97
02306     Inputs:     New state for the ShowOnColourLine flag.
02307     Returns:    The old state of the ShowOnColourLine flag.
02308     Purpose:    To set a new current state of the ShowOnColourLine flag.
02309 
02310 ***********************************************************************************************/
02311 
02312 BOOL SGDisplayLibColGroup::SetDisplayInColourLine(BOOL NewState)
02313 {
02314     BOOL OldState = m_DisplayInColourLine;
02315     m_DisplayInColourLine = NewState;
02316     return OldState;
02317 }
02318 
02319 /***********************************************************************************************
02320 
02321 >   virtual BOOL SGDisplayLibColGroup::ToggleDisplayInColourLine()
02322 
02323     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02324     Created:    20/3/97
02325     Returns:    The old state of the ShowOnColourLine flag.
02326     Purpose:    To toggle the current state of the ShowOnColourLine flag.
02327 
02328 ***********************************************************************************************/
02329 
02330 BOOL SGDisplayLibColGroup::ToggleDisplayInColourLine()
02331 {
02332     BOOL OldState = m_DisplayInColourLine;
02333     if (m_DisplayInColourLine)
02334         m_DisplayInColourLine = FALSE;
02335     else
02336         m_DisplayInColourLine = TRUE;
02337 
02338     // If in Camelot mode then save the new state in the preferences
02339     // as this is the only chance that we will get
02340     String_256 TheFile = Filename.GetFileName(FALSE);
02341     TheFile.toUpper();
02342     // read a preference value for that named gallery
02343     /*BOOL SetOk =*/ Camelot.SetPrefDirect(TEXT("ColourLine"), TheFile, &m_DisplayInColourLine);
02344 
02345     return OldState;
02346 }
02347 
02348 
02349 
02350 
02351 
02352 
02353 
02354 
02355 
02356 
02357 
02358 
02359 /********************************************************************************************
02360 
02361 >   ColourSGallery::ColourSGallery()
02362                                                  
02363     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02364     Created:    27/10/94
02365     Purpose:    ColourSGallery default constructor
02366 
02367 ********************************************************************************************/
02368 
02369 ColourSGallery::ColourSGallery()
02370 {
02371     DlgResID = _R(IDD_COLOURSGALLERY);
02372 
02373     ISentTheMessage = FALSE;
02374     CurrentColComp  = NULL;
02375     CurrentTarget   = NULL;
02376 
02377     // Set the display mode up from the default setting
02378     DisplayMode = DefaultDisplayMode;
02379     if (DisplayMode < 0 || DisplayMode > 2)
02380         DisplayMode = 0;
02381 
02382     CurrentImportGroup = NULL;
02383 
02384     // WEBSTER - markn 9/12/96 - Martin 16/07/97 same as Camelot now
02385     // Default gallery size
02386     //CSize Size(256, 256);
02387     //SetGallerySize(Size);
02388 
02389     // Remember a pointer to the global instance of this gallery.
02390     ERROR3IF(m_pTheGallery != NULL, "Gallery already exists in ColourSGallery::ColourSGallery?");
02391     m_pTheGallery = this;
02392 }
02393 
02394 
02395 
02396 /********************************************************************************************
02397 
02398 >   ColourSGallery::~ColourSGallery()
02399 
02400     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02401     Created:    27/10/94
02402     Purpose:    ColourSGallery destructor.
02403 
02404 ********************************************************************************************/
02405 
02406 ColourSGallery::~ColourSGallery()
02407 {
02408     ERROR3IF(CurrentColComp != NULL, "Destructed colour gallery is still doing a component copy?!");
02409 
02410     // Remember the display mode as the default setting for next time we're created (preference)
02411     DefaultDisplayMode = DisplayMode;
02412 
02413     // Make sure nothing is seriously screwed-up.
02414     ERROR3IF(m_pTheGallery == NULL, "No gallery in ColourSGallery::~ColourSGallery?");
02415     m_pTheGallery = NULL;
02416 }
02417 
02418 
02419 
02420 /********************************************************************************************
02421 
02422 >   static BOOL ColourSGallery::Init(void)
02423                                                  
02424     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02425     Created:    20/3/95
02426 
02427     Purpose:    ColourSGallery initialisation - declares preferences etc
02428 
02429 ********************************************************************************************/
02430 
02431 BOOL ColourSGallery::Init(void)
02432 {
02433     // Declare preferences
02434     GetApplication()->DeclareSection(TEXT("Displays"), 8);
02435     GetApplication()->DeclarePref(TEXT("Displays"), TEXT("AutoScrollColours"), &AutoScrollSelection);
02436     GetApplication()->DeclarePref(TEXT("Displays"), TEXT("ColourDisplayMode"), &DefaultDisplayMode);
02437 
02438     GetApplication()->DeclareSection(TEXT("ColourLine"), 4);
02439     GetApplication()->DeclarePref(TEXT("ColourLine"), TEXT("ShowDocumentColours"), &ShowDocumentColours);
02440 
02441     GetApplication()->DeclareSection(TEXT("Palettes"), 2);
02442     GetApplication()->DeclarePref(TEXT("Palettes"), TEXT("Path"), &PalettePath);
02443 
02444     OpBackground::Init();
02445 
02446     return(TRUE);
02447 }
02448 
02449 /********************************************************************************************
02450 
02451 >   static ColourSGallery* ColourSGallery::GetInstance()
02452 
02453     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02454     Created:    19/3/97
02455     Inputs:     -
02456     Outputs:    -
02457     Returns:    A pointer to the program's colour gallery if it exists, or NULL.
02458     Purpose:    Public access function to the colour gallery.
02459     Errors:     -
02460     SeeAlso:    -
02461 
02462 ********************************************************************************************/
02463 
02464 ColourSGallery* ColourSGallery::GetInstance()
02465 {
02466     return m_pTheGallery;
02467 }
02468 
02469 
02470 /********************************************************************************************
02471 
02472 >   void ColourSGallery::CreateNewSubtree(Document *ParentDoc, SGDisplayColourGroup *ExistingGroup)
02473 
02474     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02475     Created:    31/10/94
02476 
02477     Inputs:     ParentDoc - The document to create a display subtree for
02478                 ExistingGroup - NULL (creates a new group for this document), or
02479                 a pointer to the existing group-node for this document (in which case
02480                 it clears all displayitems from the group and rebuilds it in place - this
02481                 stops the display group moving around the tree at random!)
02482 
02483     Purpose:    Internal call. This takes the colour list of the given document and 
02484                 creates a DisplayTree subtree from it. This subtree is then added to
02485                 the DisplayTree. Note that this does not force a redraw of the list - 
02486                 after making this call, you should also call ForceRedrawOfList
02487 
02488     Notes:      Passing in a NULL parent document pointer results in an ERROR3 -
02489                 the function returns without doing anything in retail builds
02490 
02491                 It now scans the existinggroup (if any), and takes no action if it
02492                 exactly matches the parent colour list.
02493 
02494     SeeAlso:    SuperGallery::ForceRedrawOfList
02495 
02496 ********************************************************************************************/
02497 
02498 void ColourSGallery::CreateNewSubtree(Document *ParentDoc, SGDisplayColourGroup *ExistingGroup)
02499 {
02500     ERROR3IF(ParentDoc == NULL, "ColourSGallery::CreateNewSubtree - illegal NULL parameter");
02501     if (ParentDoc == NULL || DisplayTree == NULL)
02502         return;
02503 
02504     // Don't add subtrees for clipboards!
02505     if (ParentDoc->IsAClipboard() || ParentDoc->IsAHiddenDoc())
02506         return;
02507 
02508     SGDisplayColourGroup  *DisplayDocument = NULL;
02509     SGDisplayColour *DisplayColour   = NULL;
02510 
02511     if (ExistingGroup != NULL)
02512     {
02513         ERROR3IF(ExistingGroup->GetParentDocument() != ParentDoc, 
02514                  "This group is not for that document! What's going down, dude?");
02515         DisplayDocument = ExistingGroup;                            // Use existing group
02516 
02517         // Scan the ExistingGroup, to see if we really need to do anything
02518         BOOL DisplayCorrect = TRUE;
02519         ColourList *ColList = ParentDoc->GetIndexedColours();
02520         IndexedColour *TheCol = ColList->GetUndeletedHead();
02521         DisplayColour = (SGDisplayColour *) DisplayDocument->GetChild();
02522 
02523         while (TheCol != NULL && DisplayColour != NULL && DisplayCorrect)
02524         {
02525             if (TheCol != DisplayColour->GetDisplayedColour()->FindParentIndexedColour())
02526                 DisplayCorrect = FALSE;
02527 
02528             TheCol = ColList->GetUndeletedNext(TheCol);
02529             DisplayColour = (SGDisplayColour *) DisplayColour->GetNext();
02530         }
02531 
02532         if (DisplayCorrect && TheCol == NULL && DisplayColour == NULL)
02533         {
02534             // The display is exactly right- we don't need to do anything
02535             return;
02536         }
02537 
02538         DisplayDocument->DestroySubtree(FALSE);     // Wipe any existing colour display items
02539     }
02540     else
02541     {
02542         DisplayDocument = new SGDisplayColourGroup(this, ParentDoc, NULL);// Create new Group
02543 
02544         if (DisplayDocument == NULL)                                // Total failure - abort
02545         {
02546             InformError();
02547             return;
02548         }
02549 
02550         DisplayDocument->Flags.CanSelect = TRUE;                    // Group is selectable
02551 
02552         // Make sure that any library groups stay at the bottom of the gallery
02553         SGDisplayNode *InsertionPos = DisplayTree->GetChild();
02554         while (InsertionPos != NULL)
02555         {
02556             if (InsertionPos->IsKindOf(CC_RUNTIME_CLASS(SGDisplayLibColGroup)))
02557                 break;
02558 
02559             InsertionPos = InsertionPos->GetNext();
02560         }
02561 
02562         // And add the group to the tree
02563         if (InsertionPos != NULL)
02564             InsertionPos->InsertBefore(DisplayDocument);        // Insert in front of libraries
02565         else
02566             DisplayTree->AddItem(DisplayDocument);              // No libraries - just AddTail
02567 
02568         // And ensure it is folded/unfolded as appropriate (but don't bother redrawing)
02569         DisplayDocument->SetFoldedState((ParentDoc != Document::GetSelected()), FALSE);
02570     }
02571 
02572     ColourList *ColList = ParentDoc->GetIndexedColours();
02573     IndexedColour *CurColour = (ColList == NULL) ? NULL : (IndexedColour *) ColList->GetHead();
02574 
02575     while (CurColour != NULL)                                       // For each colour in the doc...
02576     {
02577 //      if (!CurColour->IsDeleted() && CurColour->IsNamed())        // If alive & named...
02578 
02579 // WEBSTER - markn 5/12/96
02580 // New func that decides weather the colour should be added to the gallery
02581 // called CanAddColourToGallery()
02582 
02583         if (CanAddColourToGallery(CurColour,ColList))       // If alive & named...
02584         {
02585             DisplayColour = new SGDisplayColour(CurColour);
02586             if (DisplayColour == NULL)
02587             {
02588                 InformError();
02589                 return;
02590             }
02591 
02592             DisplayDocument->AddItem(DisplayColour);                // Create & add item for it
02593         }
02594 
02595         CurColour = (IndexedColour *) ColList->GetNext(CurColour);  // Next colour
02596     }
02597 }
02598 
02599 
02600 /********************************************************************************************
02601 
02602 >   static BOOL ColourSGallery::CanAddColourToGallery(IndexedColour *pCol,ColourList* pColList)
02603 
02604     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02605     Created:    5/12/96
02606 
02607     Inputs:     pCol = ptr to the index colour in question
02608                 pColList = ptr to the Colour List for the document
02609 
02610     Returns:    TRUE if the colour should be displayed in the gallery
02611                 FALSE otherwise
02612 
02613     Purpose:    Central point where it decides whether the colour should be displayed in the gallery
02614 
02615                 Added for WEBSTER
02616 
02617 ********************************************************************************************/
02618 
02619 BOOL ColourSGallery::CanAddColourToGallery(IndexedColour *pCol,ColourList* pColList)
02620 {
02621     ERROR2IF(pCol == NULL,FALSE,"NULL colour ptr");
02622     ERROR2IF(pColList == NULL,FALSE,"NULL colour list ptr");
02623 
02624 //#ifndef WEBSTER
02625     return (!pCol->IsDeleted() && pCol->IsNamed());     // v1.5 implementation
02626 //#else
02627 //  if (!pCol->IsDeleted() && pCol->IsNamed())
02628 //  {
02629 //      if (pCol->HasLinkedChildren() && pCol->FindLinkedParent() == NULL)
02630 //      {
02631 //          // OK, the colour has a child yet no parent, so it must be a top-level parent colour?
02632 //          // Well, not quite.
02633 //          //
02634 //          // If the colour editor has been opened, it may have created an editing colour
02635 //          // and linked it to one of the colours in the colour list *just in case* you wish to link
02636 //          // it to another colour
02637 //          //
02638 //          // This linking is done so that it can make an intelligent choice on which colour you wish
02639 //          // to link to.
02640 //          //
02641 //          // The following loop checks to see if there is another *real* colour (i.e. one in the document)
02642 //          // that is linked to this colour
02643 //
02644 //          IndexedColour *pColInList = (IndexedColour *) pColList->GetUndeletedHead();
02645 //          while (pColInList != NULL)
02646 //          {
02647 //              if (pColInList != pCol && pColInList->IsADescendantOf(pCol))
02648 //                  return TRUE;
02649 //      
02650 //              pColInList = pColList->GetUndeletedNext(pColInList);
02651 //          }
02652 //      }
02653 //  }
02654 //
02655 //  return FALSE;
02656 //#endif // WEBSTER
02657 }
02658 
02659 
02660 /********************************************************************************************
02661 
02662 >   BOOL ColourSGallery::PreCreate(void)
02663 
02664     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02665     Created:    27/10/94
02666 
02667     Returns:    TRUE if the Gallery initialised successfully
02668                 FALSE if it should not be opened due to a failure to initialise
02669 
02670     Purpose:    The ColourSGallery PreCreate handler. This overrides the base class
02671                 PreCreate function. It is called at the very start of the
02672                 SuperGallery::Create method, before the window has been created.
02673 
02674 ********************************************************************************************/
02675 
02676 BOOL ColourSGallery::PreCreate(void)
02677 {
02678     // If there isn't already one, create a DisplayTree
02679     if (DisplayTree == NULL)
02680     {
02681         DisplayTree = new SGDisplayRootScroll(this);    // New root node, with a scrollbar
02682         if (DisplayTree == NULL)
02683             return(FALSE);
02684     }
02685 
02686     // We're opening the window, so we fold all groups except that for the Selected document
02687     SGDisplayGroup *Group = (SGDisplayGroup *) DisplayTree->GetChild();
02688     while (Group != NULL)
02689     {
02690         // Set the group's folded state, but don't bother trying to redraw, because we know
02691         // that the window is not currently visible, and that we are doing this to multiple groups.
02692         Document *pDoc = Group->GetParentDocument();
02693 
02694         if (pDoc != NULL)   // Leave library groups alone
02695             Group->SetFoldedState((pDoc != Document::GetSelected()), FALSE);
02696 
02697         Group = (SGDisplayGroup *) Group->GetNext();
02698     }
02699 
02700     // And for each document already present, (re)create a display subtree (possibly replacing
02701     // a previous displaytree for it if we had one earlier)
02702     Document *ParentDoc = (Document *) GetApplication()->Documents.GetTail();
02703     while (ParentDoc != NULL)
02704     {
02705         SGDisplayColourGroup *ParentGroup = (SGDisplayColourGroup *)DisplayTree->FindSubtree(this, ParentDoc, NULL);
02706 
02707         CreateNewSubtree(ParentDoc, ParentGroup);
02708         ParentDoc = (Document *) GetApplication()->Documents.GetPrev(ParentDoc);
02709     }
02710 
02711     // Only add the library groups if they're not already in the gallery
02712     SGDisplayNode *Ptr = DisplayTree->GetChild();
02713     while (Ptr != NULL)
02714     {
02715         if (Ptr->IsKindOf(CC_RUNTIME_CLASS(SGDisplayLibColGroup)))
02716             break;
02717 
02718         Ptr = Ptr->GetNext();
02719     }
02720 
02721 PORTNOTE("other", "Colour gallery needs to use the resource system for finding palettes when no path is specified");
02722 #ifndef EXCLUDE_FROM_XARALX
02723     if (Ptr == NULL)
02724     {
02725         SGDisplayLibColGroup *Bob;
02726 
02727         String_256 SearchPath;
02728         // If the user has set a pathname in the preference then use this, otherwise
02729         // use a Palettes directory which is sitting alongside the exe.
02730         if (PalettePath.IsEmpty())
02731         {
02732             // Find the directory path of the .exe file
02733             CResDll::GetExecutablePath((TCHAR *) SearchPath);
02734 
02735             SearchPath += TEXT("\\Palettes\\"); // This is a fixed (non-internationalised) string
02736         }
02737         else
02738         {
02739             SearchPath = PalettePath;
02740             // Add a trailing slash if it hasn't got one
02741             SGLibOil::AppendSlashIfNotPresent(&SearchPath);
02742         }
02743             
02744         // Make up the search string to use so that we see all files.
02745         String_256 SearchSpec(SearchPath);
02746         SearchSpec += TEXT("*.*");  // This is a fixed (non-internationalised) string
02747 
02748         if (FileUtil::StartFindingFiles(&SearchSpec))
02749         {
02750             String_256 LeafName;
02751 
02752             while (FileUtil::FindNextFile(&LeafName))
02753             {
02754                 String_256 FullPath = SearchPath;
02755                 //FullPath += TEXT("\\Palettes\\");
02756                 FullPath += LeafName;
02757 
02758                 PathName Name(FullPath);
02759                 Bob = new SGDisplayLibColGroup(this, &Name);
02760                 if (Bob != NULL)
02761                     DisplayTree->AddItem(Bob);
02762             }
02763             FileUtil::StopFindingFiles();
02764         }
02765     }
02766 #endif
02767 
02768     // Ensure we know we have to reformat before the next redraw
02769     InvalidateCachedFormat();
02770 
02771     return(TRUE);
02772 }
02773 
02774 /********************************************************************************************
02775 
02776 >   BOOL ColourSGallery::MakeSureGroupsHaveBeenCreated()
02777 
02778     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02779     Created:    19/3/97
02780     Inputs:     -
02781     Returns:    True if everything went ok, False otherwise.
02782     Purpose:    This will create the gallery groups (unless they're already there)
02783                 and return TRUE if ok.
02784 
02785 ********************************************************************************************/
02786  
02787 BOOL ColourSGallery::MakeSureGroupsHaveBeenCreated()
02788 {
02789     // We will use the DisplayTree presence or absence to dictate whether the groups are
02790     // there or not. If it is there just return TRUE as everything should be fabby.
02791     if (DisplayTree != NULL)
02792         return TRUE;
02793 
02794     // If not then just call PreCreate to ensure that they are present.
02795     return PreCreate();
02796 }
02797 
02798 
02799 /********************************************************************************************
02800 
02801 >   SGDisplayLibColGroup * ColourSGallery::GetNextLibGroup(SGDisplayLibColGroup * pLibGroup)
02802 
02803     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02804     Created:    19/3/97
02805     Inputs:     -
02806     Returns:    NULL or pointer to the next LibGroup in the list.
02807     Purpose:    Gets the first colour library group node in the colour gallery.
02808 
02809 ********************************************************************************************/
02810 
02811 SGDisplayLibColGroup * ColourSGallery::GetFirstLibGroup()
02812 {
02813     return GetNextLibGroup(NULL);
02814 }
02815 
02816 /********************************************************************************************
02817 
02818 >   SGDisplayLibColGroup * ColourSGallery::GetNextLibGroup(SGDisplayLibColGroup * pLibGroup)
02819 
02820     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
02821     Created:    19/3/97
02822     Inputs:     -
02823     Returns:    NULL or pointer to the next LibGroup in the list.
02824     Purpose:    Gets the next colour library group node in the colour gallery.
02825 
02826 ********************************************************************************************/
02827 
02828 SGDisplayLibColGroup * ColourSGallery::GetNextLibGroup(SGDisplayLibColGroup * pLibGroup)
02829 {
02830     SGDisplayNode *pGroup = NULL;
02831     // If we are passed a null pointer then somebody must want the first item in the list
02832     if (pLibGroup == NULL)
02833     {
02834         if (DisplayTree == NULL)
02835             return NULL;
02836 
02837         // Find the first library groups in the gallery
02838         pGroup = DisplayTree->GetChild();
02839     }
02840     else
02841         pGroup = pLibGroup->GetNext();
02842 
02843     while (pGroup != NULL)
02844     {
02845         if (pGroup->IsKindOf(CC_RUNTIME_CLASS(SGDisplayLibColGroup)))
02846         {
02847             return (SGDisplayLibColGroup*)pGroup;
02848         }
02849 
02850         pGroup = pGroup->GetNext();
02851     }
02852 
02853     // none found
02854     return NULL;
02855 }
02856 
02857 
02858 
02859 
02860 /********************************************************************************************
02861 
02862 >   void ColourSGallery::EditColour(ColourList *ParentList, IndexedColour *TheColour)
02863 
02864     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02865     Created:    18/1/95
02866 
02867     Inputs:     ParentList - The ColourList in which the given colour resides
02868                 TheColour  - the colour to edit, or NULL to just open the editor
02869 
02870     Purpose:    Opens the colour editor, and sets it to edit the given colour
02871 
02872     SeeAlso:    ColourPicker
02873 
02874 ********************************************************************************************/
02875 
02876 void ColourSGallery::EditColour(ColourList *ParentList, IndexedColour *TheColour)
02877 {
02878     ColourPicker ColPicker;
02879     ColPicker.EditColour(ParentList, TheColour);
02880 }
02881 
02882 
02883 
02884 /********************************************************************************************
02885 
02886 >   BOOL ColourSGallery::OKToDeleteSelection(SGDisplayGroup *DocumentGroup)
02887 
02888     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02889     Created:    18/1/95
02890 
02891     Inputs:     DocumentGroup - The subtree in which the selection lies
02892                 This is expected to be the subtree for the selected document
02893 
02894     Returns:    TRUE if it is OK to go ahead and delete, or
02895                 FALSE if the delete action has been cancelled
02896 
02897     Purpose:    To determine if it is OK to go ahead and delete the selected colours,
02898                 and to possibly modify the selection if some colours should not be deleted.
02899 
02900                 This checks with the user - they can either delete all colours, delete
02901                 only those which are not 'in use', or cancel the delete. In the first case,
02902                 this method does nothing (returns TRUE); in the second, it removes in-use
02903                 colours from the selection and returns TRUE; in the third case, it does
02904                 nothing, but returns FALSE.
02905 
02906     SeeAlso:    ColourSGallery::DeleteSelection
02907 
02908 ********************************************************************************************/
02909 
02910 BOOL ColourSGallery::OKToDeleteSelection(SGDisplayGroup *DocumentGroup)
02911 {
02912     ERROR3IF(DocumentGroup == NULL, "Illegal NULL param");
02913 
02914     SGDisplayColour *Item = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(NULL);
02915     IndexedColour *RefColour;
02916     INT32 ItemsInUse = 0;
02917     INT32 TotalItems = 0;
02918     INT32 DeletableItems = 0;
02919 
02920     Document *ParentDoc = DocumentGroup->GetParentDocument();
02921     if (ParentDoc == NULL)
02922         return(FALSE);
02923 
02924     ColourList *ParentColList = ParentDoc->GetIndexedColours();
02925     if (ParentColList == NULL)
02926         return(FALSE);
02927 
02928     // Determine how many items are selected, and how many of these are in use
02929     while (Item != NULL)
02930     {
02931         if (!Item->IsALibraryColour())
02932         {
02933             DeletableItems++;               // Increment number of deletable (non-library) items
02934 
02935             // Check if the colour is in use. NOTE that because it is used in this gallery
02936             // display item, it's usage count will be 1 greater than the 'real' usage
02937             // (i.e. when we delete it, the usage count will be decremented once, so
02938             // it is considered not-in-use if the usagcount is <= 1)
02939             RefColour = Item->GetDisplayedColour()->FindParentIndexedColour();
02940             if (RefColour != NULL && ParentColList->IsColourInUseInDoc(RefColour, TRUE))
02941                 ItemsInUse++;
02942         }
02943 
02944         TotalItems++;                       // Increment number of found items
02945 
02946         Item = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(Item);
02947     }
02948 
02949     if (DeletableItems == 0)
02950         return(FALSE);
02951 
02952     // If some are in use, determine if the user really wants to delete them
02953     INT32 ButtonPressed = 2;
02954     if (ItemsInUse != 0)
02955     {
02956         ButtonPressed = AskQuestion(_R(IDS_COLGAL_COLINUSE),
02957                                     _R(IDS_COLGAL_KILL), _R(IDS_COLGAL_NOKILL), _R(IDS_CANCEL), 0,
02958                                     2, 3);  // NOKILL=default, CANCEL=cancel
02959 
02960         if (ButtonPressed == 3) // Delete was cancelled - return FALSE
02961             return(FALSE);
02962     }
02963 
02964     if (ButtonPressed == 1)     // Force-delete all items, so go ahead and delete
02965         return(TRUE);
02966 
02967     if (ButtonPressed == 2 && DeletableItems - ItemsInUse <= 0)
02968         return(FALSE);          // No items left to delete (all in use) so abort
02969 
02970     // Remove all in-use items from the selection so we only delete 'free' colours
02971     Item = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(NULL);
02972 
02973     while (Item != NULL)
02974     {
02975         RefColour = Item->GetDisplayedColour()->FindParentIndexedColour();
02976         if (RefColour != NULL && ParentColList->IsColourInUseInDoc(RefColour, TRUE))
02977             Item->SetSelected(FALSE);
02978 
02979         Item = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(Item);
02980     }
02981 
02982     return(TRUE);
02983 }
02984 
02985 
02986 
02987 /********************************************************************************************
02988 
02989 >   BOOL ColourSGallery::DeleteSelection(SGDisplayGroup *DocumentGroup,
02990                                          ColourList *ParentList)
02991 
02992     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
02993     Created:    18/1/95
02994 
02995     Inputs:     DocumentGroup - The subtree in which the selection lies
02996                 This is expected to be the subtree for the selected document
02997 
02998                 ParentList - The ColourList in which all these colours reside
02999 
03000     Returns:    TRUE to indicate successful handling of the action, or
03001                 FALSE to indicate failure
03002 
03003     Purpose:    Forcibly deletes all selected colours
03004                 Should be used after OKToDeleteSelection (which confirms the action)
03005 
03006     SeeAlso:    ColourSGallery::OKToDeleteSelection
03007 
03008 ********************************************************************************************/
03009 
03010 BOOL ColourSGallery::DeleteSelection(SGDisplayGroup *DocumentGroup, ColourList *ParentList)
03011 {
03012     if (ParentList == NULL)
03013         return(TRUE);
03014 
03015     INT32 TotalItems = DocumentGroup->GetSelectedItemCount();
03016     if (TotalItems == 0)
03017         return(TRUE);
03018 
03019     IndexedColour **KillList = new IndexedColourPtr[TotalItems+1];
03020     if (KillList == NULL)
03021         return(FALSE);
03022 
03023     DWORD KillIndex = 0;
03024     SGDisplayColour *Item = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(NULL);
03025     SGDisplayColour *NextItem;
03026     IndexedColour *RefColour;
03027 
03028     while (Item != NULL)
03029     {
03030         // Remember the NextItem item, cos we're about to delink/destroy this one
03031         NextItem = (SGDisplayColour *) DocumentGroup->FindNextSelectedItem(Item);
03032 
03033         RefColour = Item->GetDisplayedColour()->FindParentIndexedColour();
03034         if (RefColour != NULL)
03035         {
03036             // Add the colour to the kill list
03037             KillList[KillIndex++] = RefColour;
03038 
03039             // Annihilate this item, so that it no longer references the IndexedColour
03040             Item->DestroySubtree();
03041         }
03042 
03043         // And move on to the NextItem item
03044         Item = NextItem;
03045     }
03046     
03047     KillList[KillIndex] = NULL;     // NULL terminate the list
03048 
03049     // Now cause a redraw of the tree in its new state, before the message broadcast goes around
03050     InvalidateCachedFormat();
03051     ReformatAndRedrawIfNecessary();
03052 
03053     // Delete (hide, with undo actually) the given colours
03054     // Our message handler will cope with redrawing the new list (we must do it this
03055     // way in case the deletion causes other changes to the list, e.g. a new 'black'
03056     // being created if we delete the default one)
03057     ColourManager::HideColours(ParentList, KillList, TRUE);
03058 
03059     // HideColours has made a copy of this list for itself, so we are responsible
03060     // for deleting our original list
03061     delete [] KillList;
03062 
03063 
03064     return(TRUE);
03065 }
03066 
03067 
03068 
03069 /********************************************************************************************
03070 
03071 >   virtual BOOL ColourSGallery::ApplyAction(SGActionType Action)
03072 
03073     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03074     Created:    18/1/95
03075 
03076     Inputs:     Action - Indicates what action to apply
03077 
03078     Returns:    TRUE to indicate successful handling of the action, or
03079                 FALSE to indicate failure
03080 
03081     Purpose:    Applies certain conventional gallery actions (usually associated with
03082                 gallery buttons, for new, edit, delete, etc)
03083 
03084     SeeAlso:    SGActionType
03085 
03086 ********************************************************************************************/
03087 
03088 BOOL ColourSGallery::ApplyAction(SGActionType Action)
03089 {
03090     // No display tree? Or worse, no active docuemnts? Better forget about it then!
03091     if (DisplayTree == NULL || Document::GetSelected() == NULL)
03092         return(FALSE);
03093 
03094     SGDisplayColour *FirstSelected = (SGDisplayColour *)
03095                                         DisplayTree->FindNextSelectedItem(NULL);
03096 
03097     SGDisplayGroup  *DocumentGroup  = NULL;
03098     Document        *ScopeDoc       = NULL;
03099     ColourList      *ColList        = NULL;
03100     IndexedColour   *SelectedColour = NULL;
03101     DocColour       *TheColour      = NULL;
03102 
03103     if (FirstSelected != NULL)
03104     {
03105         DocumentGroup = (SGDisplayGroup *) FirstSelected->GetParent();
03106         ERROR3IF(DocumentGroup == NULL, "SGallery DisplayTree linkage corruption detected");
03107 
03108         ScopeDoc = DocumentGroup->GetParentDocument();
03109         if (ScopeDoc == NULL)       // Must be a library item, so it will affect the selected doc
03110             ScopeDoc = Document::GetSelected();
03111         ERROR3IF(ScopeDoc == NULL, "No scope document for colour gallery operation!");
03112 
03113         ColList = ScopeDoc->GetIndexedColours();
03114         ERROR3IF(ColList == NULL, "A document with no colour list? Now I've seen it all");
03115 
03116         TheColour = FirstSelected->GetDisplayedColour();
03117         ERROR3IF(TheColour == NULL, "SGDisplayColour has no colour in it?");
03118         
03119         SelectedColour = TheColour->FindParentIndexedColour();
03120     }
03121 
03122 
03123     BOOL Adjust = FALSE;
03124 
03125     // Now, process the action
03126     switch(Action)
03127     {
03128         case SGACTION_CREATE:
03129             ColList = Document::GetSelected()->GetIndexedColours();
03130             ERROR3IF(ColList == NULL, "A document with no colour list? Now I've seen it all");
03131             if (ColList != NULL)
03132             {
03133                 BOOL OldSentState = ISentTheMessage;
03134                 ISentTheMessage = TRUE;
03135 
03136                 IndexedColour *NewCol = NULL;
03137 
03138                 if (FirstSelected == NULL || !FirstSelected->IsALibraryColour() || TheColour == NULL)
03139                     NewCol = ColourManager::GenerateNewNamedColour(ColList, SelectedColour);
03140                 else
03141                 {
03142                     // A library doccolour - we must copy it into the document before trying to apply it
03143                     // Make a temporary IndexedColour from the library colour
03144                     NewCol = new IndexedColour(*TheColour);
03145 
03146                     if (NewCol != NULL)
03147                     {
03148                         SGDisplayLibColour *LibCol = (SGDisplayLibColour *) FirstSelected;
03149 
03150                         // Set the colour's name to the same as the library item (but make sure it's unique)
03151                         String_256 Buffer;
03152                         LibCol->GetNameText(&Buffer);
03153                         NewCol->SetName(Buffer);
03154                         if (ColList->GenerateUniqueColourName(NewCol->GetName(), (String_64 *) &Buffer))
03155                             NewCol->SetName(Buffer);
03156 
03157                         // If it's a spot colour, make it so
03158                         if (LibCol->IsASpotColour())
03159                             NewCol->SetLinkedParent(NULL, COLOURTYPE_SPOT);
03160 
03161                         // Copy the colour into the destination document (merging it with existing
03162                         // colours so we won't keep creating new copies of the same colour as it's applied)
03163                         DocColour ColourToApply;
03164                         ColourToApply.MakeRefToIndexedColour(NewCol);
03165                         ColourManager::EnsureColourIsInDocument(NULL, Document::GetSelected(), &ColourToApply);
03166 
03167                         // Delete the temporary IndexedColour we used
03168                         delete NewCol;
03169 
03170                         // And remember the new colour we've just made
03171                         NewCol = ColourToApply.FindParentIndexedColour();
03172                     }
03173                 }
03174 
03175                 // If NewCol == NULL, either an error occured, or more likely, the user cancelled
03176 
03177                 ISentTheMessage = OldSentState;
03178 
03179                 if (NewCol != NULL)
03180                 {
03181                     // Bring up the colour editor on the new colour
03182                     EditColour(ColList, NewCol);
03183 
03184                     // And make the new item the selected one in the list
03185                     SelectItems(FALSE);         // Deselect everything else
03186 
03187                     // Find the item and select it
03188                     SGDisplayGroup *DocGroup = DisplayTree->FindSubtree(this,
03189                                                         Document::GetSelected(), NULL);
03190                     if (DocGroup != NULL)
03191                     {
03192                         // We've found the group for the selected document
03193                         SGDisplayColour *Ptr = new SGDisplayColour(NewCol);
03194                         if (Ptr != NULL)
03195                         {
03196                             // Add the item to the group using the last applied sort mode
03197                             DocGroup->AddItem(Ptr, SortKeys);
03198 
03199                             // And rearrange the real colour item to the same position by inserting
03200                             // it after the colour which is previous in the display list. If there
03201                             // is no display-list-previous-item, then we insert at the head.
03202                             ColourList *ColList = ColourManager::GetColourList();
03203                             ColList->RemoveItem(NewCol);
03204 
03205                             if (ColList->GetHead() == NULL)
03206                             {
03207                                 // Thanks, Mario. If you try to add an item when the list is empty
03208                                 // he just ignores you (no ensure, no useful default behaviour)
03209                                 ColList->AddItem(NewCol);
03210                             }
03211                             else
03212                             {
03213                                 if (Ptr->GetPrevious() == NULL)
03214                                     ColList->InsertBefore(ColList->GetHead(), NewCol);
03215                                 else
03216                                     ColList->InsertAfter(((SGDisplayColour *)Ptr->GetPrevious())->
03217                                                         GetDisplayedColour()->FindParentIndexedColour(), NewCol);
03218                             }
03219 
03220                             ForceGroupFolded(DocGroup, FALSE);  // Ensure group is unfolded and tree reformatted
03221 
03222                             // Select the new node, and remember it as the new selection anchor
03223                             Ptr->SetSelected(TRUE);
03224                             SetLastSelectedNode(Ptr);
03225 
03226                             // Ensure the format is recalculated as a result of adding the new item
03227                             ReformatAndRedrawIfNecessary();
03228 
03229                             // And now we can get its format rect, and scroll to show it
03230                             DocRect ItemFormatRect;
03231                             Ptr->GetFormatRect(&ItemFormatRect);
03232                             ScrollToShow(&ItemFormatRect);
03233                         }
03234                     }
03235                     else
03236                     {
03237                         ERROR3("Colour DisplayGroup not found for Selected Document!");
03238                     }
03239 
03240                     SelectionHasChanged();
03241                 }
03242             }
03243             break;
03244 
03245 
03246         case SGACTION_APPLYADJUST:
03247             Adjust = TRUE;
03248             // Drop through to SGACTION_APPLY handler
03249 
03250         case SGACTION_APPLY:
03251             if (TheColour != NULL && (SelectedColour != NULL || FirstSelected->IsALibraryColour()))
03252             {
03253                 DocColour ColourToApply;
03254 
03255                 if (!FirstSelected->IsALibraryColour())
03256                 {
03257                     // Normal IndexedColour item - just apply it
03258                     ColourToApply.MakeRefToIndexedColour(SelectedColour);
03259 
03260                     // Ensure this colour (or an equivalent) is available in the selected doc
03261                     // (which is where the apply will take place), and modify ColourToApply
03262                     // (if necessary) to reference the safe colour for the dest doc.
03263                     ColourManager::EnsureColourIsInDocument(ScopeDoc, Document::GetSelected(), &ColourToApply);
03264                 }
03265                 else
03266                 {
03267                     // A library doccolour - we must copy it into the document before trying to apply it
03268                     // Make a temporary IndexedColour from the library colour
03269                     IndexedColour *NewCol = new IndexedColour(*TheColour);
03270 
03271                     if (NewCol != NULL)
03272                     {
03273                         SGDisplayLibColour *LibCol = (SGDisplayLibColour *) FirstSelected;
03274 
03275                         // Set the colour's name to the same as the library item
03276                         String_256 Buffer;
03277                         LibCol->GetNameText(&Buffer);
03278                         NewCol->SetName(Buffer);
03279 
03280                         // If it's a spot colour, make it so
03281                         if (LibCol->IsASpotColour())
03282                             NewCol->SetLinkedParent(NULL, COLOURTYPE_SPOT);
03283 
03284                         // Copy the colour into the destination document (merging it with existing
03285                         // colours so we won't keep creating new copies of the same colour as it's applied)
03286                         ColourToApply.MakeRefToIndexedColour(NewCol);
03287                         ColourManager::EnsureColourIsInDocument(NULL, Document::GetSelected(), &ColourToApply);
03288 
03289                         // And delete the temporary IndexedColour we used
03290                         delete NewCol;
03291                         NewCol = NULL;
03292                     }
03293                 }
03294 
03295                 if (ColourToApply.FindParentIndexedColour() != NULL)
03296                 {
03297                     // We've got a colour to apply, so apply it
03298 
03299                     NodeAttribute *Attrib;
03300                     if (Adjust)
03301                     {
03302                         // Adjust-ed, so set the line colour
03303                         Attrib = new AttrStrokeColourChange;
03304                         if (Attrib == NULL)
03305                         {
03306                             InformError();
03307                             return(FALSE);
03308                         }
03309 
03310                         ((AttrStrokeColourChange *)Attrib)->SetStartColour(&ColourToApply);
03311                     }
03312                     else
03313                     {
03314                         // Select-ed so set the fill colour
03315                         Attrib = new AttrColourChange;
03316                         if (Attrib == NULL)
03317                         {
03318                             InformError();
03319                             return(FALSE);
03320                         }
03321 
03322                         ((AttrColourChange *)Attrib)->SetStartColour(&ColourToApply);
03323                     }
03324 
03325                     // AttributeSelected knows what to do with a selected attribute
03326                     AttributeManager::AttributeSelected(NULL, Attrib);
03327                 }
03328             }
03329             break;
03330 
03331 
03332         case SGACTION_REDEFINE:
03333             if (SelectedColour != NULL && TheColour != NULL)
03334             {
03335                 // First, try to find an interesting colour to redefine from
03336                 DocColour SourceColour;
03337                 ColourList *SrcColList;
03338 
03339                 ColourManager::FindColourOfInterestToUser(&SourceColour, &SrcColList);
03340 
03341                 if (SourceColour.FindParentIndexedColour() == SelectedColour)
03342                 {
03343                     // You can't redefine a colour from itself! Don't be daft!
03344                     InformError(_R(IDE_COLGAL_SAMEITEM));
03345                     return(FALSE);
03346                 }
03347 
03348                 // Copy the colour
03349                 IndexedColour *NewCol = new IndexedColour(SourceColour);
03350                 if (NewCol == NULL)
03351                     return(FALSE);
03352 
03353                 if (SrcColList != ColList || NewCol->IsADescendantOf(SelectedColour))
03354                 {
03355                     // We're redefining from a colour in a different document, or attempting to make a
03356                     // recursive parent-pointer loop. Remove the parent linkage to make NewCol a standalone
03357                     // copy of its previous parent.
03358                     NewCol->SetLinkedParent(NULL,
03359                             (NewCol->GetType() == COLOURTYPE_SPOT) ? COLOURTYPE_SPOT : COLOURTYPE_NORMAL);
03360                 }
03361   
03362                 // Compose a new, unique, name for it - e.g. "Red (Redefined)"
03363                 String_128 NewName(_R(IDS_UNNAMEDCOLOUR));
03364                 if (SelectedColour->IsNamed())
03365                     NewName.MakeMsg(_R(IDS_REDEFINEDCOLOUR), (TCHAR *) (*(SelectedColour->GetName())) );
03366 
03367                 // Ensure the new name is unique within the destination colour list
03368                 String_64 UniqueNewName;
03369                 ColList->GenerateUniqueColourName(&NewName, &UniqueNewName);
03370                 NewCol->SetName(UniqueNewName);
03371 
03372                 // And finally, apply the colour change, with UNDO
03373                 // (Note that NewCol is put into the undo system, so we must not delete it)
03374                 return(ColourManager::ChangeColour(ColList, NewCol, SelectedColour));
03375             }
03376             break;
03377 
03378 
03379         case SGACTION_EDIT:
03380             if (ScopeDoc != Document::GetSelected())
03381             {
03382                 // **** BODGE! TO DO !!!!
03383 // This should make the appropriate document selected by chucking its window to the front, and
03384 // then invoke the colour editor on the selected colour
03385 
03386                 InformMessage(_R(IDS_COLGAL_NOTSELDOC), _R(IDS_CANCEL));
03387                 break;
03388             }
03389 
03390             // Always show the editor, and if there is a selection, edit the
03391             // first selected colour
03392             EditColour(ColList, SelectedColour);
03393             break;
03394 
03395 
03396         case SGACTION_DELETE:
03397             {
03398                 while (DocumentGroup != NULL)
03399                 {
03400                     // For each document, if there are selected items in the document, then
03401                     // delete them (after asking the user for each document) TODO : Clean up!!!!
03402 
03403                     ScopeDoc = DocumentGroup->GetParentDocument();
03404                     if (ScopeDoc != NULL)
03405                     {
03406                         ColList = ScopeDoc->GetIndexedColours();
03407                         ERROR3IF(ColList == NULL,
03408                                 "A document with no colour list? Now I've seen it all");
03409 
03410                         if (DocumentGroup->GetSelectedItemCount() > 0)
03411                         {
03412                             if (OKToDeleteSelection(DocumentGroup))
03413                             {
03414                                 if (!DeleteSelection(DocumentGroup, ColList))
03415                                     return(FALSE);
03416                             }
03417                         }
03418                     }
03419 
03420                     DocumentGroup = (SGDisplayGroup *) DocumentGroup->GetNext();
03421                 }
03422 
03423                 SelectionHasChanged();
03424             }
03425             break;
03426 
03427 
03428         case SGACTION_SETOPTIONS:   // Set values in the options/sort dialogue as it is opened
03429             if (CurrentOptionsDlg != NULL)
03430             {                                                                   // Display Modes
03431                 CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_SMALL));     // 0
03432                 CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_FULLINFO));  // 1
03433                 CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_ICONONLY));  // 2
03434             }
03435             break;
03436 
03437         case SGACTION_SETSORTMODE:
03438             if (CurrentSortDlg != NULL)
03439             {                                                               // Sort Modes (0 = none)
03440                 CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_NAME));            // 1 (sort by name)
03441                 CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_HUE));             // 2
03442                 CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_INTENSITY));       // 3
03443                 CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_MODEL));           // 4
03444             }
03445             break;
03446 
03447 
03448         case SGACTION_DISPLAYMODECHANGED:
03449             // Ensure that the display mode is one of the supported values
03450             if (DisplayMode < 0 || DisplayMode > 2)
03451                 DisplayMode = 0;
03452             break;
03453 
03454 
03455         default:
03456             return(FALSE);
03457     }
03458 
03459     return(TRUE);
03460 }
03461 
03462 
03463 
03464 /********************************************************************************************
03465 
03466 >   void ColourSGallery::RedrawColourDisplay(Document *TheDocument, IndexedColour *TheColour)
03467 
03468     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03469     Created:    19/1/95
03470 
03471     Inputs:     TheDocument - The document containing the colour
03472                 TheColour - The colour which needs to be re-displayed
03473 
03474     Purpose:    Redraws the display item for one specific colour, and all of its linked
03475                 descendants (liked/tint colours) (if any) in a given document.
03476 
03477     Notes:      If the specified colo9ur is unnamed, nothing is done
03478 
03479     SeeAlso:    SuperGallery::RedrawDocumentDisplay
03480 
03481 ********************************************************************************************/
03482 
03483 void ColourSGallery::RedrawColourDisplay(Document *TheDocument, IndexedColour *TheColour)
03484 {
03485     if (TheDocument == NULL || TheColour == NULL)
03486         return;
03487 
03488     SGDisplayGroup *Group = DisplayTree->FindSubtree(this, TheDocument, NULL);
03489 
03490     if (Group == NULL)      // Can't find a group for this document
03491         return;
03492 
03493     // Now search the tree for the specific items to redraw
03494     SGDisplayColour *Item = (SGDisplayColour *) Group->GetChild();
03495 
03496     // WEBSTER - markn 28/1/97
03497     // This can be NULL in webster when you edit a non-editable colour (e.g. by double-clicking
03498     // on a colour in the web palette folder)
03499     // In Camelot it expects a colour to be added to the folder containing the doc's colours,
03500     // but for Webster that is not the case. It is now (mab) Martin 15/07/97
03501     if (Item != NULL)
03502     {
03503         ERROR3IF(Item->GetChild() != NULL, "My leaf-item isn't a leaf-item! Help!");
03504 
03505         IndexedColour *RealColour;
03506 
03507         while (Item != NULL)
03508         {
03509             RealColour = Item->GetDisplayedColour()->FindParentIndexedColour();
03510             if (RealColour != NULL && RealColour->IsADescendantOf(TheColour))
03511                 Item->ForceRedrawOfMyself();                // Found it, or a descendant - redraw
03512 
03513             Item = (SGDisplayColour *) Item->GetNext();
03514         }
03515     }
03516 }
03517 
03518 
03519 
03520 /********************************************************************************************
03521 
03522 >   void ColourSGallery::SetSelectionFromDocument(BOOL AlwaysScroll = FALSE)
03523 
03524     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03525     Created:    20/2/95 (copied from old ColourGallery, previously created 11/10/94)
03526 
03527     Inputs:     AlwaysScroll - TRUE if you always want to autoscroll, regardless of the
03528                 preference setting. (This is used when opening the gallery, as there is no
03529                 point in not auto-scrolling somewhere useful)
03530 
03531     Purpose:    Sets the colour gallery listbox selection state based upon the currently
03532                 selected object(s) in the document (to show the current fill/stroke colours)
03533 
03534     Scope:      private
03535 
03536 ********************************************************************************************/
03537 
03538 void ColourSGallery::SetSelectionFromDocument(BOOL AlwaysScroll)
03539 {
03540     if (DisplayTree == NULL || !IsVisible())
03541         return;
03542     
03543     DocColour *SelColour[2];
03544     BOOL AreCurrentAttrs =
03545             ColourManager::GetCurrentLineAndFillColours(&SelColour[0], &SelColour[1]);
03546 
03547     SGDisplayGroup *DocGroup = NULL;
03548     if (Document::GetSelected() != NULL)
03549         DocGroup = DisplayTree->FindSubtree(this, Document::GetSelected(), NULL);
03550     SelectItems(FALSE);                 // Clear the current selection
03551 
03552     DocRect ScrollToRect;
03553     BOOL HaveSelected = FALSE;
03554     BOOL ScrollToBottom = FALSE;    // TRUE if it is more important that the bottom of
03555                                     // ScrollToRect, rather than the top, is visible
03556 
03557     if (DocGroup != NULL)
03558         ForceGroupFolded(DocGroup, FALSE);  // Ensure group is unfolded
03559 
03560     ReformatNow(TRUE);              // Ensure the tree format information is up to date
03561 
03562     if (!AreCurrentAttrs && DocGroup != NULL)
03563     {
03564         // The line/fill colours returned are those of the selection, not the current attrs
03565         IndexedColour *Parent;
03566 
03567         for (INT32 i = 0; i < 2; i++)           // For each colour (line, fill)
03568         {
03569             if (SelColour[i] != NULL)       // If there is a single selected colour
03570             {
03571                 Parent = SelColour[i]->FindParentIndexedColour();       // Find the named IxColour
03572                 if (Parent != NULL && Parent->IsNamed())                // (if any)
03573                 {
03574                     // See if we can find a display item for this colour, and select it
03575                     SGDisplayColour *Ptr = (SGDisplayColour *)DocGroup->GetChild();
03576                     while (Ptr != NULL)
03577                     {
03578                         if (Ptr->GetDisplayedColour()->FindParentIndexedColour() == Parent)
03579                         {
03580                             // determine the rectangle to try to show on screen (the
03581                             // union of both the selected items)
03582                             if (!HaveSelected)
03583                                 Ptr->GetFormatRect(&ScrollToRect);
03584                             else
03585                             {
03586                                 DocRect TempRect;
03587                                 Ptr->GetFormatRect(&TempRect);
03588 
03589                                 // We must be adding the fill colour. If this is below the
03590                                 // line colour, then we'd prefer to scroll to show the
03591                                 // bottom of the rectangle, as it is more important that
03592                                 // the fill rather than line is visible if won't both fit.
03593                                 ScrollToBottom = (TempRect.hi.y <= ScrollToRect.lo.y);
03594 
03595                                 ScrollToRect = ScrollToRect.Union(TempRect);
03596                             }                               
03597 
03598                             // And select the item, and update the selection-anchor
03599                             Ptr->SetSelected(TRUE);
03600                             SetLastSelectedNode(Ptr);
03601 
03602                             HaveSelected = TRUE;
03603                             break;
03604                         }
03605 
03606                         Ptr = (SGDisplayColour *) Ptr->GetNext();
03607                     }
03608                 }
03609             }
03610         }
03611     }
03612 
03613     if (AutoScrollSelection || AlwaysScroll)
03614     {
03615         if (AlwaysScroll && !HaveSelected && DocGroup != NULL)
03616         {
03617             // We didn't select anything in the gallery. In that case, scroll to the top
03618             // of the document display
03619             DocRect TempRect;
03620             DocGroup->GetFormatRect(&TempRect);
03621             DocGroup->GetChildArea(&ScrollToRect);
03622             ScrollToRect = ScrollToRect.Union(TempRect);
03623             HaveSelected = TRUE;
03624             ScrollToBottom = FALSE;
03625         }
03626 
03627         if (HaveSelected)
03628             ScrollToShow(&ScrollToRect, ScrollToBottom);
03629     }
03630                                                 // scroll to make seln visible on screen
03631 
03632     SelectionHasChanged();                      // Update for the new selection
03633 }
03634 
03635 
03636 
03637 /********************************************************************************************
03638 
03639 >   virtual MsgResult ColourSGallery::Message(Msg* Message)
03640 
03641     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03642     Created:    31/10/94
03643     Inputs:     Message - The message to handle
03644 
03645     Purpose:    A standard message handler, really.
03646 
03647     Notes:      Any messages that this does not handle must be passed down to the
03648                 SuperGallery base class message handler.
03649 
03650     SeeAlso:    SuperGallery::Message
03651 
03652 ********************************************************************************************/
03653 
03654 MsgResult ColourSGallery::Message(Msg* Message)
03655 {
03656     if (IS_OUR_DIALOG_MSG(Message))
03657     {
03658         DialogMsg* Msg = (DialogMsg*)Message;
03659 
03660         switch (Msg->DlgMsg)
03661         {
03662             case DIM_CREATE:
03663                 SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYCOLOURGALLERY), TRUE);
03664                 SetSelectionFromDocument(TRUE);
03665                 break;
03666 
03667             case DIM_CANCEL:
03668                 SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYCOLOURGALLERY), FALSE);
03669                 break;
03670 
03671             case DIM_LFT_BN_CLICKED:
03672                 if (DisplayTree == NULL || !IsVisible())
03673                     break;
03674 
03675                 if (FALSE) {}
03676                 else if (Msg->GadgetID == _R(IDC_GALLERY_NAME))
03677                 {
03678                     SGDisplayColour *FirstSelected = (SGDisplayColour *)
03679                                         DisplayTree->FindNextSelectedItem(NULL);
03680                     if (FirstSelected != NULL)
03681                     {
03682                         IndexedColour *ColToEdit = FirstSelected->GetDisplayedColour()->
03683                                                         FindParentIndexedColour();
03684 
03685                         SGDisplayGroup *DocumentGroup = (SGDisplayGroup *) FirstSelected->GetParent();
03686                         ERROR3IF(DocumentGroup == NULL, "SGallery DisplayTree linkage corruption detected");
03687 
03688                         Document *ScopeDoc = DocumentGroup->GetParentDocument();
03689                         ERROR3IF(ScopeDoc == NULL, "SGallery group is not for a document! Unimplemented! Eek!");
03690 
03691                         ColourList *ColList = ScopeDoc->GetIndexedColours();
03692                         ERROR3IF(ColList == NULL, "A document with no colour list? Now I've seen it all");
03693 
03694                         if (ColToEdit != NULL)
03695                             ColourNameDlg::InvokeDialog(ColList, ColToEdit);
03696                     }
03697                 }
03698                 else if (Msg->GadgetID == _R(IDC_GALLERY_HELP))
03699                 {
03700                     TRACEUSER( "Markn", _T("Hello. Do you want help on this gallery?\n"));
03701                     HelpUserTopic(_R(IDS_HELPPATH_Gallery_Colour));
03702                 }
03703                 else if (Msg->GadgetID == _R(IDC_COLGAL_BACKGROUND))    // Set a background layer with the selected colour
03704                 {
03705                     ApplySelectedAsBackground();
03706                 }
03707                 break;
03708 
03709             default:
03710                 break;
03711         }
03712 
03713         return(SuperGallery::Message(Message));
03714     }
03715 
03716 
03717     // If we have no displaytree, then we have not been shown, or something terrible has
03718     // happened, so we don't bother handling any of these messages.
03719     if (DisplayTree == NULL || !IsVisible())
03720         return(SuperGallery::Message(Message));
03721 
03722 
03723     if (MESSAGE_IS_A(Message, DocChangingMsg))
03724     {
03725         DocChangingMsg *TheMsg = (DocChangingMsg *) Message;
03726 
03727         switch ( TheMsg->State )
03728         {
03729             case DocChangingMsg::BORN:          // New document - add to display tree
03730                 {
03731                     CreateNewSubtree(TheMsg->pChangingDoc); // Add a subtree for this doc
03732                     ShadeGallery(FALSE);
03733 
03734                     InvalidateCachedFormat();               // And redraw what is necessary
03735                     ReformatAndRedrawIfNecessary();
03736                 }
03737                 break;      // Pass this message on to the base class as well
03738 
03739 //          case DocChangingMsg::DocState::ABOUTTODIE:      // Document dying - remove from tree
03740 //          case DocChangingMsg::DocState::KILLED:
03741 //          case DocChangingMsg::DocState::SELCHANGED:
03742 //
03743 //              ==== NOTE ====
03744 //              The base sgallery class handles these messages to automatically remove
03745 //              the subtree for the dying doc, and/or shade the gallery if no docs are left
03746             default:
03747                 break;
03748 
03749         }
03750     }
03751     else if (MESSAGE_IS_A(Message, ColourChangingMsg))
03752     {
03753         ColourChangingMsg *TheMsg = (ColourChangingMsg *) Message;
03754 
03755         switch (TheMsg->State)
03756         {
03757             case ColourChangingMsg::LISTUPDATED:
03758                 // A document colour list has been changed. We must recreate its display subtree
03759                 if (!ISentTheMessage && TheMsg->NewColourList != NULL)
03760                 {
03761                     // First, try to find the document which owns the changed list
03762                     Document *ScopeDoc = (Document *)TheMsg->NewColourList->GetParentDocument();
03763 
03764                     // Just check that the bi-directional link is sane!
03765                     ERROR3IF(ScopeDoc == NULL ||
03766                              ScopeDoc->GetIndexedColours() != TheMsg->NewColourList,
03767                              "A Document colour list is somehow screwed up!");
03768 
03769                     // If we found it, recreate the display subtree for it
03770                     if (ScopeDoc != NULL)
03771                     {
03772                         SGDisplayNode *Ptr = DisplayTree->FindSubtree(this, ScopeDoc, NULL);
03773                         CreateNewSubtree(ScopeDoc, (SGDisplayColourGroup *) Ptr);
03774 
03775                         // And force a redraw of the entire list
03776                         //ForceRedrawOfList();
03777                         InvalidateCachedFormat();
03778                         ReformatAndRedrawIfNecessary();
03779                     }
03780                 }               
03781                 break;
03782 
03783 
03784             case ColourChangingMsg::COLOURUPDATED:
03785             case ColourChangingMsg::COLOURUPDATEDINVISIBLE:
03786                 if (TheMsg->NewColourList != NULL)
03787                 {
03788                     Document *ScopeDoc = (Document *)TheMsg->NewColourList->GetParentDocument();
03789                     RedrawColourDisplay(ScopeDoc, TheMsg->ChangedColour);
03790                 }
03791                 break;
03792 
03793             case ColourChangingMsg::SELVIEWCONTEXTCHANGE:
03794                 // Colour separation/correction options for the selected view have
03795                 // changed, so redraw the entire colour list using the new options.
03796                 ForceRedrawOfList();
03797                 break;
03798 
03799             default:
03800                 break;
03801         }
03802     }
03803     // The new CommonAttrsChanged msg replaces this messages. It handles 
03804     // a change in the Current Attribute group associated with a tool, and a change in the
03805     // value of a current attribute.
03806     /*else if (MESSAGE_IS_A(Message, SelChangingMsg))
03807     {
03808         SelChangingMsg *Msg = (SelChangingMsg *) Message;
03809         switch ( Msg->State )
03810         {
03811             case SelChangingMsg::COLOURATTCHANGED:
03812             case SelChangingMsg::SELECTIONCHANGED:
03813             case SelChangingMsg::NODECHANGED:
03814                 if (!AmShaded)          // If we're open & active, set listbox selection
03815                     SetSelectionFromDocument();
03816                 break;
03817         }
03818         // Drop through so the Gallery base class gets to see this message too
03819     }
03820     */
03821     else if (MESSAGE_IS_A(Message, CommonAttrsChangedMsg))
03822     {
03823         if (!AmShaded)          // If we're open & active, set listbox selection
03824             SetSelectionFromDocument();
03825 
03826     }
03827     else if (MESSAGE_IS_A(Message, DocViewMsg))
03828     {
03829         DocViewMsg *Msg = (DocViewMsg *) Message;
03830 
03831         if (Msg->State == DocViewMsg::SELCHANGED)
03832         {
03833             // Selected DocView is changing - redraw to use the new DocView's colour context
03834             BOOL DoRedraw = TRUE;
03835             if (Msg->pOldDocView != NULL && Msg->pNewDocView != NULL)
03836             {
03837                 // If we know the old & new views, then see if they have the same colour
03838                 // context attached - if they do, there's no need to redraw. This eliminates
03839                 // flicker when swapping normal views (the most common view-swap action)
03840                 // We only check the RGB context because we assume the screen is always RGB
03841                 ColourContext *OldCC = Msg->pOldDocView->GetColourContext(COLOURMODEL_RGBT, TRUE);
03842                 ColourContext *NewCC = Msg->pNewDocView->GetColourContext(COLOURMODEL_RGBT, TRUE);
03843 
03844                 if (OldCC == NewCC)
03845                     DoRedraw = FALSE;
03846             }
03847 
03848             if (DoRedraw)
03849                 ForceRedrawOfList();
03850         }
03851     }
03852 
03853     return(SuperGallery::Message(Message));
03854 }
03855 
03856 
03857 
03858 /********************************************************************************************
03859 
03860 >   virtual void ColourSGallery::HandleDragStart(DragMessage *DragMsg)
03861 
03862     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03863     Created:    14/3/95
03864 
03865     Inputs:     DragMsg - The DRAGSTARTED message that we've just recieved, indicating
03866                 the type of drag being started
03867 
03868     Purpose:    Checks a DragMessage to see if it is a colour drag.
03869                 If it is, then it creates a drag target for this gallerys listbox.
03870 
03871     Notes:      Overrides the default base-class action. Calls down to the base class
03872                 if it is not a colour drag, so that dragging of gallery groups is allowed
03873 
03874 ********************************************************************************************/
03875 
03876 void ColourSGallery::HandleDragStart(DragMessage *DragMsg)
03877 {
03878     // If it's a colour drag, add a target for our window. If not, let the base class
03879     // have a look at it (to see if it is a group being dragged)
03880     if (DragMsg->pInfo->IsKindOf(CC_RUNTIME_CLASS(ColourDragInformation)))
03881     {
03882         /*SGColourDragTarget *NewTarget =*/ new SGColourDragTarget(this, GetListGadgetID());
03883     }
03884     else
03885         SuperGallery::HandleDragStart(DragMsg);
03886 }
03887 
03888 
03889 
03890 /********************************************************************************************
03891 
03892 >   virtual SGDisplayItem *ColourSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, 
03893                                     SGDisplayGroup *DestGroup,
03894                                     SGDisplayItem *TargetPosition = NULL)
03895     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03896     Created:    14/3/95
03897 
03898     Inputs:     SourceItem - The item to copy elsewhere in the tree (see below)
03899 
03900                 DestGroup - The group into which the item should be inserted
03901 
03902                 TargetPosition - NULL (to insert at the end of the sibling list), or
03903                 points to an item BEFORE which SourceItem will be copied.
03904 
03905     Returns:    NULL (failed) or a pointer to the new (copied) display item
03906 
03907     Purpose:    "Copies" the existing node in the tree in an appropriate fashion.
03908                 
03909                 This method is normally called when a gallery-organising drag completes,
03910                 and it is discovered that the dragged item(s) have been dragged to a 
03911                 different display group.
03912 
03913     Notes:      This derived class override copies colours between documents.
03914                 
03915                 Currently, this just errors to the user, as copying between docs is
03916                 not possible, due to undo going into the selected doc. **** !!!!
03917 
03918     SeeAlso:    ColourSGallery::InsertCopiedItem; SGDisplayItem::MoveBefore;
03919                 SGDisplayItem::MoveAfter; SGColour::CopyDisplayItem
03920 
03921 ********************************************************************************************/
03922 
03923 SGDisplayItem *ColourSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, 
03924                         SGDisplayGroup *DestGroup, SGDisplayItem *TargetPosition)
03925 {
03926     ERROR3IF(SourceItem == NULL || DestGroup == NULL, "Illegal NULL param");
03927 
03928     if (DestGroup->Flags.ReadOnly)
03929     {
03930         ERROR2RAW("Trying to copy a colour into a read-only (library) group");
03931         InformError();
03932         return(NULL);       // Sanity check - disallow copy into a library group!
03933     }
03934 
03935     Document *DestDoc = DestGroup->GetParentDocument();
03936     if (DestDoc == NULL)
03937     {
03938         ERROR2RAW("No dest doc?!");
03939         InformError();
03940         return(NULL);
03941     }
03942 
03943     // Normal colour drag between 2 documents
03944     DocColour *DocColToCopy = ((SGDisplayColour *) SourceItem)->GetDisplayedColour();
03945     ERROR3IF(DocColToCopy == NULL, "NULL displayed colour?!");
03946 
03947     IndexedColour *ColToCopy = NULL;
03948     BOOL ColIsTemporary = FALSE;
03949 
03950     if (((SGDisplayColour *) SourceItem)->IsALibraryColour())
03951     {
03952         // The dragged item is not resident in any document - it's in a library
03953         // Create a temporary IndexedColour to be copied into the doc
03954         ColToCopy = new IndexedColour(*DocColToCopy);
03955         ColIsTemporary = TRUE;
03956 
03957         if (ColToCopy != NULL)
03958         {
03959             // Set the colour's name to the same as the library item
03960             String_256 Buffer;
03961             ((SGDisplayLibColour *) SourceItem)->GetNameText(&Buffer);
03962             ColToCopy->SetName(Buffer);
03963 
03964             if (((SGDisplayLibColour *) SourceItem)->IsASpotColour())
03965                 ColToCopy->SetLinkedParent(NULL, COLOURTYPE_SPOT);
03966         }
03967         else
03968         {
03969             ERROR3("No memory for copied colour");
03970         }
03971     }
03972     else    
03973     {   
03974         ColToCopy = DocColToCopy->FindParentIndexedColour();
03975         ERROR3IF(ColToCopy == NULL, "NULL displayed colour?!");
03976     }
03977 
03978     if (ColToCopy == NULL)
03979         return(NULL);
03980 
03981     // If we haven't already started a component copy, set one up
03982     if (CurrentColComp == NULL)
03983     {
03984         CurrentColComp = (ColourListComponent *)
03985                                 DestDoc->GetDocComponent(CC_RUNTIME_CLASS(ColourListComponent));
03986         if (CurrentColComp == NULL)
03987         {
03988             if (ColIsTemporary)
03989                 delete ColToCopy;
03990 
03991             ERROR2RAW("Couldn't find a colour list component for the destination document!");
03992             InformError();
03993             return(NULL);
03994         }
03995 
03996         if (!CurrentColComp->StartComponentCopy())  // If this fails, it reports the error itself
03997         {
03998             if (ColIsTemporary)
03999                 delete ColToCopy;
04000 
04001             return(NULL);
04002         }
04003 
04004         CurrentTarget = TargetPosition;
04005     }
04006 
04007     // Create a new display item, referencing the colour to be copied
04008     SGDisplayColour *NewDisplayItem = new SGDisplayColour(ColToCopy);
04009     if (NewDisplayItem == NULL)
04010     {
04011         if (ColIsTemporary)
04012             delete ColToCopy;
04013 
04014         InformError();
04015         return(NULL);
04016     }
04017 
04018     // Remap the display item to reference a safe colour for the destination document
04019     // NOTE that we use a special TRUE flag here to indicate that we know the colour
04020     // is always unique - this stops the ColComp from caching a pointer to our temporary
04021     // colour (which then is reallocated for the next colour, which then causes
04022     // all the colour mapping to get very very confused).
04023     if (CurrentColComp->CopyColourAcross(NewDisplayItem->GetDisplayedColour(), TRUE) != CCCOPY_NEWCOLOUR)
04024     {
04025         // Either the copy failed (we have no colour to display), or it was merged with
04026         // an existing colour (in which case there will already be a display item for it)
04027         delete NewDisplayItem;
04028         
04029         if (ColIsTemporary)
04030             delete ColToCopy;
04031 
04032         return(NULL);
04033     }
04034 
04035     SuperGallery::InsertCopiedItem(NewDisplayItem, DestGroup, TargetPosition);
04036 
04037     // If we copied a library item, then delete the temporary IndexedColour we created
04038     if (ColIsTemporary)
04039     {
04040         delete ColToCopy;
04041         ColToCopy = NULL;
04042     }
04043 
04044     // And update the item selection states, so that the copied item is the selected one
04045     // We poke directly at the selected flag to avoid it trying to redraw itself when we know
04046     // it hasn't had a chance to format itself yet.
04047 //  SourceItem->SetSelected(FALSE);
04048 //  NewDisplayItem->Flags.Selected = TRUE;
04049 
04050     return(NewDisplayItem);
04051 }
04052 
04053 
04054 
04055 /********************************************************************************************
04056 
04057 >   virtual void ColourSGallery::AllItemsCopied(SGDisplayGroup *DestGroup)
04058 
04059     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04060     Created:    27/3/95
04061 
04062     Purpose:    This upcall method is called after one or more items have been copied or
04063                 moved by a gallery drag. It allows the gallery to do update things like
04064                 broadcasting a message or getting a related window (eg colour line) to redraw
04065                 at the end of a move/copy operation. This allows thousands of items to be
04066                 moved/copied with only a single redraw/message-broadcast, etc at the very end.
04067 
04068     Notes:      The caller automatically causes the appropriate things to be redrawn, so we
04069                 just need to update other things.
04070                 e.g. The colour gallery broadcasts a ColourChangingMsg to make sure that the
04071                 colour line and other interested parties all update appropriately.
04072 
04073     SeeAlso:    SuperGallery::CopyDisplayItem; SGDisplayItem::MoveBefore;
04074                 SGDisplayItem::MoveAfter; ColourSGallery::AllItemsCopied
04075 
04076 ********************************************************************************************/
04077 
04078 void ColourSGallery::AllItemsCopied(SGDisplayGroup *DestGroup)
04079 {
04080     ERROR3IF(DestGroup == NULL, "Illegal NULL param");
04081 
04082     BOOL OldSentState = ISentTheMessage;    // Make me ignore any messages triggered by this code
04083     ISentTheMessage = TRUE;
04084 
04085     // This can be called after MoveItems as well as CopyDisplayItem calls
04086     // We only have to do something if the CopyDisplayItem call has started a component copy...
04087     if (CurrentColComp != NULL)
04088     {
04089         // Merge colours, add undo record, etc. Any new colours will be inserted after the
04090         // given target position, and if any colours were merged, the user is informed
04091         IndexedColour *Target = NULL;
04092         if (CurrentTarget != NULL)
04093             Target = ((SGDisplayColour *)CurrentTarget)->GetDisplayedColour()->
04094                                                         FindParentIndexedColour();
04095 
04096         CurrentColComp->EndComponentCopy(Target, TRUE);
04097         CurrentColComp = NULL;
04098         CurrentTarget  = NULL;
04099 
04100         Document *ParentDoc = DestGroup->GetParentDocument();
04101         if (ParentDoc != NULL)
04102         {
04103             CreateNewSubtree(ParentDoc, (SGDisplayColourGroup*)DisplayTree->FindSubtree(this, ParentDoc, NULL));
04104             InvalidateCachedFormat();
04105             ReformatAndRedrawIfNecessary();
04106         }
04107     }
04108     else
04109     {
04110         // Inform the rest of the world that this colour list order has been modified
04111         Document *ParentDoc = DestGroup->GetParentDocument();
04112         if (ParentDoc != NULL)
04113             ColourManager::ColourListHasChanged(ParentDoc->GetIndexedColours());
04114     }
04115 
04116     ISentTheMessage = OldSentState;
04117 }
04118 
04119 
04120 /********************************************************************************************
04121 
04122 >   virtual RenderRegion *ColourSGallery::CreateRenderRegion(DocRect *VirtualSize,
04123                                                             ReDrawInfoType *DlgRedrawInfo)
04124 
04125     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04126     Created:    23/5/96
04127 
04128     Purpose:    An overridable veneer to the DialogOp CreateOSRenderRegion method.
04129                 This can be overriden to use a different type of renderregion for
04130                 all of your rendering.
04131 
04132                 If you override this, you MUST also override DestroyRenderRegion!
04133 
04134     Notes:      This ovverrides the base class to do the same thing, but to make our
04135                 RenderRegion use colour correction/separation options from the selected
04136                 view, so that we display "document colours" correctly for the selview.
04137 
04138     SeeAlso:    ColourSGallery::DestroyRenderRegion
04139 
04140 ********************************************************************************************/
04141 
04142 RenderRegion *ColourSGallery::CreateRenderRegion(DocRect *VirtualSize, ReDrawInfoType *DlgRedrawInfo)
04143 {
04144     return(CreateOSRenderRegion(VirtualSize, DlgRedrawInfo, TRUE));
04145 }
04146 
04147 
04148 
04149 /********************************************************************************************
04150 
04151 >   virtual void ColourSGallery::DestroyRenderRegion(RenderRegion *pRender)
04152 
04153     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04154     Created:    23/5/96
04155 
04156     Purpose:    An overridable veneer to the DialogOp DestroyOSRenderRegion method.
04157                 This can be overriden to use a different type of renderregion for
04158                 all of your rendering.
04159 
04160                 If you override this, you MUST also override CreateRenderRegion!
04161 
04162     SeeAlso:    ColourSGallery::CreateRenderRegion
04163 
04164 ********************************************************************************************/
04165 
04166 void ColourSGallery::DestroyRenderRegion(RenderRegion *pRender)
04167 {
04168     DestroyOSRenderRegion(pRender);
04169 }
04170 
04171 
04172 
04173 
04174 
04175 
04176 /********************************************************************************************
04177 
04178 >   virtual BOOL ColourSGallery::InitMenuCommands(void)
04179                                                  
04180     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04181     Created:    18/9/95
04182 
04183     Returns:    TRUE for success
04184 
04185     Purpose:    Initialises any menu commands that this gallery needs.
04186 
04187     Notes:      Will only create the menu commands once - further calls in the future
04188                 will return TRUE immediately wihtout doing anything.
04189 
04190 ********************************************************************************************/
04191 
04192 BOOL ColourSGallery::InitMenuCommands(void)
04193 {
04194     static BOOL MenusInitialised = FALSE;
04195 
04196     BOOL ok = TRUE;
04197 
04198     if (!MenusInitialised)
04199     {
04200         // Edits to the pop-up menu on the colour gallery
04201 
04202         // Initialise menu command Ops
04203 
04204         // "Standard" entries for options menu
04205         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Find, _R(IDS_SGMENU_FIND));
04206         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Sort, _R(IDS_SGMENU_SORT));
04207         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Properties, _R(IDS_SGMENU_PROPERTIES));
04208 
04209         // "Special" entries for over-list menu
04210         ok = ok && InitMenuCommand((StringBase *) &SGCmd_New, _R(IDS_SGMENU_NEW));
04211         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Edit, _R(IDS_SGMENU_EDIT));
04212         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Delete, _R(IDS_SGMENU_DELETE));
04213         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Redefine, _R(IDS_SGMENU_REDEFINE));
04214         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Rename, _R(IDS_SGMENU_RENAME));
04215 
04216         // "Standard" commands for over-list menu
04217         ok = ok && InitMenuCommand((StringBase *) &SGCmd_FoldGroup, _R(IDS_SGMENU_FOLD));
04218         ok = ok && InitMenuCommand((StringBase *) &SGCmd_UnfoldGroup, _R(IDS_SGMENU_UNFOLD));
04219 
04220         ok = ok && InitMenuCommand((StringBase *) &SGCmd_NextGroup, _R(IDS_SGMENU_NEXTGROUP));
04221         ok = ok && InitMenuCommand((StringBase *) &SGCmd_PrevGroup, _R(IDS_SGMENU_PREVGROUP));
04222 
04223         // Extra new group item
04224         ok = ok && InitMenuCommand((StringBase *) &SGCmd_ShowInColourLine, _R(IDS_SGMENU_SHOWINCOLOURLINE));
04225         ok = ok && InitMenuCommand((StringBase *) &SGCmd_SetBackground, _R(IDS_SGMENU_SETBACKGROUND));
04226 
04227         MenusInitialised = TRUE;
04228     }
04229 
04230     return(ok);
04231 }
04232 
04233 
04234 
04235 /********************************************************************************************
04236 
04237 >   virtual BOOL ColourSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID)
04238 
04239     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04240     Created:    15/9/95
04241 
04242     Inputs:     TheMenu - The menu to add commands to
04243                 MenuID  - The type of menu (over-list or from-options-button) to create
04244 
04245     Returns:    TRUE if it succeeded
04246 
04247     Purpose:    To build a menu of commands to be popped up over the gallery.
04248     
04249     Notes:      Override this method to stop the default menus being built
04250 
04251 ********************************************************************************************/
04252 
04253 BOOL ColourSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID)
04254 {
04255     BOOL ok = TRUE;
04256 
04257     // Edits to the pop-up menu on the colour gallery
04258 
04259     if (MenuID == SGMENU_OPTIONS)
04260     {
04261         // Options menu
04262         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Find);
04263         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Sort);
04264         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Properties);
04265     }
04266     else
04267     {
04268         // Over-list menu
04269         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_New);
04270         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Edit);
04271         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Delete);
04272         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Redefine);
04273         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Rename, TRUE);     // With separator
04274 
04275         SGDisplayGroup *TheGroup = FindCommandGroup();      // Fold or unfold as appropriate
04276         if (TheGroup == NULL || !TheGroup->Flags.Folded)
04277             ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_FoldGroup);
04278         else
04279             ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_UnfoldGroup);
04280 
04281         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_PrevGroup);
04282         // add 'Show in colour line' menu item in Camelot
04283         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_NextGroup, TRUE);      // With separator
04284 
04285         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_ShowInColourLine);
04286         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_SetBackground);
04287     }
04288 
04289     return(ok);
04290 }
04291 
04292 
04293 
04294 /********************************************************************************************
04295 
04296 >   virtual OpState ColourSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason)
04297 
04298     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04299     Created:    15/9/95
04300 
04301     Inputs:     CommandID - TheString ID of the command
04302     Outputs:    ShadeReason - If you return (OpState.Greyed == TRUE) then this should be filled
04303                 ion with the reason that the item is shaded/greyed.
04304 
04305     Returns:    An OpState indicating the current menu item state.
04306 
04307     Purpose:    To determine the state of a given menu item. This method is an exact
04308                 parallel to an Op's GetState method (in fact, it is called by an Op's GetState)
04309     
04310     Notes:      Override this method to provide state info for your special commands
04311                 Call the base class for unknown commands to allow it to handle them for you
04312 
04313                 The base class handles all of these (maybe more - see the base class help)
04314                     Properties, Sort, Find;
04315                     New, Edit, Delete, Redefine;
04316                     NextGroup, PrevGroup, FoldGroup, UnfoldGroup;
04317 
04318 ********************************************************************************************/
04319 
04320 OpState ColourSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason)
04321 {
04322     OpState State;
04323 
04324     if (AmShaded)       // No commands available while the gallery is shaded
04325     {
04326         State.Greyed = TRUE;
04327         return(State);
04328     }
04329 
04330     // Determine if the entire selection consists only of library colours...
04331     BOOL AllSelectionIsLibrary = TRUE;
04332     SGDisplayColour *Col = (SGDisplayColour *) DisplayTree->FindNextSelectedItem(NULL);
04333     SGDisplayColour *pSelectedItem = Col;
04334     if (Col == NULL)
04335         AllSelectionIsLibrary = FALSE;
04336 
04337     while (Col != NULL)
04338     {
04339         if (!Col->IsALibraryColour())
04340             AllSelectionIsLibrary = FALSE;
04341 
04342         Col = (SGDisplayColour *) DisplayTree->FindNextSelectedItem(Col);
04343     }
04344 
04345     // determine the command state...
04346     if (*CommandID == SGCmd_New)                                            // --- New
04347     {
04348         if (GetSelectedItemCount() > 1)
04349         {
04350             State.Greyed = TRUE;
04351             ShadeReason->MakeMsg(_R(IDS_SGSHADE_SINGLE));           
04352         }
04353     }
04354     else if (*CommandID == SGCmd_Rename)                                    // --- Rename
04355     {
04356         if (GetSelectedItemCount() != 1)
04357         {
04358             State.Greyed = TRUE;
04359             ShadeReason->MakeMsg(_R(IDS_SGSHADE_SINGLECOL));
04360         }
04361         else if (AllSelectionIsLibrary)
04362         {
04363             State.Greyed = TRUE;
04364             ShadeReason->MakeMsg(_R(IDS_ITSALIBRARYCOLOUR));
04365         }
04366     }
04367     else if (*CommandID == SGCmd_Edit       ||                              // --- Edit, Redefine, Delete
04368              *CommandID == SGCmd_Redefine   ||
04369              *CommandID == SGCmd_Delete)
04370     {
04371         // Make sure we disallow these options when the selection is a library colour
04372         if (AllSelectionIsLibrary)
04373         {
04374             State.Greyed = TRUE;
04375             ShadeReason->MakeMsg(_R(IDS_ITSALIBRARYCOLOUR));
04376         }
04377         else
04378             return(SuperGallery::GetCommandState(CommandID, ShadeReason));
04379     }
04380     else if (*CommandID == SGCmd_ShowInColourLine)
04381     {
04382         // Make sure we only allow these options when the selection is a library colour
04383         SGDisplayColourGroup *pGroup = (SGDisplayColourGroup *) DisplayTree->FindNextSelectedGroup(NULL);
04384         if (pGroup == NULL && pSelectedItem != NULL)
04385         {
04386             pGroup = (SGDisplayColourGroup *) pSelectedItem->GetParent();
04387         }
04388         if (pGroup)
04389         {
04390             // We have a group item selected so use it
04391             // Only do this on library colour groups at present
04392             //SGDisplayLibColGroup * pLibGroup = (SGDisplayLibColGroup*) pGroup;
04393             State.Ticked = pGroup->DisplayInColourLine();
04394         }
04395         else
04396         {
04397             State.Greyed = TRUE;
04398             ShadeReason->MakeMsg(_R(IDS_ITSNOTALIBRARYCOLOUR));
04399         }
04400     }
04401     else if (*CommandID == SGCmd_SetBackground) // Set the page background colour
04402     {
04403         // Ensure we have a single selected colour and a selected document
04404         Document * pDoc = Document::GetSelected();
04405         if (pSelectedItem == NULL || pDoc == NULL)
04406         {
04407             State.Greyed = TRUE;
04408             ShadeReason->MakeMsg(_R(IDS_SGSHADE_SINGLECOL));
04409         }
04410     }
04411     else
04412         return(SuperGallery::GetCommandState(CommandID, ShadeReason));      // Unknown command- pass to baseclass
04413 
04414     return(State);
04415 }
04416 
04417 
04418 
04419 /********************************************************************************************
04420 
04421 >   virtual void ColourSGallery::DoCommand(StringBase *CommandID)
04422 
04423     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04424     Created:    15/9/95
04425 
04426     Inputs:     CommandID - The String ID of the command
04427 
04428     Purpose:    To apply a given command when it is chosen from the menu.
04429     
04430     Notes:      Override this method to provide handling for your special commands.
04431                 Call the base class if you don't recognise the command, so that it can
04432                 handle standard commands.
04433 
04434                 The base class handles all of these (maybe more - see the base class help)
04435                     Properties, Sort, Find;
04436                     New, Edit, Delete, Redefine; (it calls ApplyAction as appropriate)
04437                     NextGroup, PrevGroup, FoldGroup, UnfoldGroup;
04438 
04439 ********************************************************************************************/
04440 
04441 void ColourSGallery::DoCommand(StringBase *CommandID)
04442 {
04443     if (*CommandID == SGCmd_Rename)
04444     {
04445         SGDisplayColour *FirstSelected = (SGDisplayColour *)        // Invoke name-colour dialogue
04446                             DisplayTree->FindNextSelectedItem(NULL);
04447         if (FirstSelected != NULL && !FirstSelected->IsALibraryColour())
04448         {
04449             IndexedColour *ColToEdit = FirstSelected->GetDisplayedColour()->
04450                                             FindParentIndexedColour();
04451 
04452             SGDisplayGroup *DocumentGroup = (SGDisplayGroup *) FirstSelected->GetParent();
04453             ERROR3IF(DocumentGroup == NULL, "SGallery DisplayTree linkage corruption detected");
04454 
04455             Document *ScopeDoc = DocumentGroup->GetParentDocument();
04456             ERROR3IF(ScopeDoc == NULL, "SGallery group is not for a document! Unimplemented! Eek!");
04457 
04458             ColourList *ColList = ScopeDoc->GetIndexedColours();
04459             ERROR3IF(ColList == NULL, "A document with no colour list? Now I've seen it all");
04460 
04461             if (ColToEdit != NULL)
04462                 ColourNameDlg::InvokeDialog(ColList, ColToEdit);
04463         }
04464     }
04465     else if (*CommandID == SGCmd_ShowInColourLine)                  // Toggle the show in colour line state
04466     {
04467         SGDisplayColour *pFirstSelected = (SGDisplayColour *)DisplayTree->FindNextSelectedItem(NULL);
04468         SGDisplayColourGroup *pGroup = (SGDisplayColourGroup *) DisplayTree->FindNextSelectedGroup(NULL);
04469         if (pGroup == NULL && pFirstSelected != NULL)
04470         {
04471             pGroup = (SGDisplayColourGroup *) pFirstSelected->GetParent();
04472         }
04473         if (pGroup)
04474         {
04475             //SGDisplayLibColGroup * pLibGroup = (SGDisplayColourGroup*) pGroup;
04476             // We have a group item selected so use it
04477             // Only do this on library colour groups at present
04478             pGroup->ToggleDisplayInColourLine();
04479 
04480             // Ensure any colours libraries that are now required are loaded
04481             // This should also send a message to the colour line to force an update
04482             CColourBar::EnsureLibraryColoursPresent();
04483         }
04484     }
04485     else if (*CommandID == SGCmd_SetBackground) // Set the page background colour
04486     {
04487         ApplySelectedAsBackground();
04488     }
04489     else
04490         SuperGallery::DoCommand(CommandID);     // Unknown command- pass to the base class
04491 }
04492 
04493 /********************************************************************************************
04494 
04495 >   BOOL ColourSGallery::ApplySelectedAsBackground()
04496 
04497     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04498     Created:    27/3/97
04499     Inputs:     -
04500     Outputs:    -       
04501     Returns:    True if worked correctly, False otherwise.
04502     Purpose:    Takes the selected item in the gallery and tries to apply this as a new
04503                 background to the spread.
04504 
04505 ********************************************************************************************/
04506 
04507 BOOL ColourSGallery::ApplySelectedAsBackground()
04508 {
04509     SGDisplayColour *pFirstSelected = (SGDisplayColour *)DisplayTree->FindNextSelectedItem(NULL);
04510     if (pFirstSelected != NULL)
04511     {
04512         // Use the first selected colour and ask a page background to be made
04513         // using this.
04514         TRACEUSER( "NEVILLE", _T("SGCmd_SetBackground"));
04515 
04516         Document * pScopeDoc = NULL;
04517         DocColour ColourToApply;
04518         BOOL ok = GetDocColourToApply(pFirstSelected, &ColourToApply, &pScopeDoc);
04519 
04520         // Only apply if we found a valid document and the colour was ok
04521         if (ok && pScopeDoc)
04522         {
04523             OpBackgroundParam Param;
04524             Param.pDocColour = &ColourToApply;
04525             Param.pDoc = pScopeDoc;         
04526             
04527             // Obtain a pointer to the op descriptor for the create operation 
04528             OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_BACKGROUND);
04529 
04530             // Invoke the operation, passing DocView and Pos as parameters
04531             pOpDesc->Invoke(&Param);         
04532         
04533             return TRUE;
04534         }
04535         
04536         return FALSE;
04537     }
04538     
04539     return FALSE;
04540 }
04541 
04542 /********************************************************************************************
04543 
04544 >   BOOL ColourSGallery::GetDocColourToApply(SGDisplayColour *pFirstSelected, DocColour * pColourToApply,
04545                                              Document **ppDoc)
04546 
04547     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04548     Created:    27/3/97
04549     Inputs:     pFirstSelected  selected item in the gallery
04550                 pColourToApply  the DocColour which needs setting up
04551     Outputs:    ppDoc           the document which we need to apply the colour to           
04552     Returns:    True if worked ok, False otherwise.
04553     Purpose:    To create a doc colour which can then be used to apply the colour in the
04554                 currently selected document. Copes with the simple case of the colour being
04555                 a document colour and the more complex case of teh colour being a library
04556                 colour. Whereapon, a new colour must be added to the selected document which
04557                 is this selected library colour.
04558 
04559 ********************************************************************************************/
04560 
04561 BOOL ColourSGallery::GetDocColourToApply(SGDisplayColour *pFirstSelected, DocColour * pColourToApply,
04562                                          Document **pDoc)
04563 {
04564     ERROR2IF(pFirstSelected == NULL || pColourToApply == NULL || pDoc == NULL,FALSE,"GetDocColourToApply bad params!");
04565 
04566     // Try to get the parent item of the selected item and ask it for the associated document
04567     SGDisplayGroup * DocumentGroup = (SGDisplayGroup *) pFirstSelected->GetParent();
04568     ERROR3IF(DocumentGroup == NULL, "SGallery DisplayTree linkage corruption detected");
04569 
04570     Document * pScopeDoc = DocumentGroup->GetParentDocument();
04571     if (pScopeDoc == NULL)      // Must be a library item, so it will affect the selected doc
04572         pScopeDoc = Document::GetSelected();
04573     
04574     // Return this to the caller
04575     *pDoc = pScopeDoc;
04576     
04577     // If we have no document to work with then nothing doing
04578     if (pScopeDoc == NULL)
04579     {
04580         ERROR3("No scope document for colour gallery operation!");
04581         return FALSE;
04582     }
04583 
04584     DocColour * pTheColour = pFirstSelected->GetDisplayedColour();
04585     ERROR3IF(pTheColour == NULL, "SGDisplayColour has no colour in it?");
04586 
04587     IndexedColour *pSelectedColour = pTheColour->FindParentIndexedColour();
04588 
04589     // Check that we have a minimal ensemble of required items
04590     if (pTheColour != NULL && (pSelectedColour != NULL || pFirstSelected->IsALibraryColour()))
04591     {
04592         if (!pFirstSelected->IsALibraryColour())
04593         {
04594             // Normal IndexedColour item - just apply it
04595             pColourToApply->MakeRefToIndexedColour(pSelectedColour);
04596 
04597             // Ensure this colour (or an equivalent) is available in the selected doc
04598             // (which is where the apply will take place), and modify ColourToApply
04599             // (if necessary) to reference the safe colour for the dest doc.
04600             ColourManager::EnsureColourIsInDocument(pScopeDoc, Document::GetSelected(), pColourToApply);
04601         }
04602         else
04603         {
04604             // A library doccolour - we must copy it into the document before trying to apply it
04605             // Make a temporary IndexedColour from the library colour
04606             IndexedColour *pNewCol = new IndexedColour(*pTheColour);
04607 
04608             if (pNewCol != NULL)
04609             {
04610                 SGDisplayLibColour *pLibCol = (SGDisplayLibColour *) pFirstSelected;
04611 
04612                 // Set the colour's name to the same as the library item
04613                 String_256 Buffer;
04614                 pLibCol->GetNameText(&Buffer);
04615                 pNewCol->SetName(Buffer);
04616 
04617                 // If it's a spot colour, make it so
04618                 if (pLibCol->IsASpotColour())
04619                     pNewCol->SetLinkedParent(NULL, COLOURTYPE_SPOT);
04620 
04621                 // Copy the colour into the destination document (merging it with existing
04622                 // colours so we won't keep creating new copies of the same colour as it's applied)
04623                 pColourToApply->MakeRefToIndexedColour(pNewCol);
04624                 ColourManager::EnsureColourIsInDocument(NULL, Document::GetSelected(), pColourToApply);
04625 
04626                 // And delete the temporary IndexedColour we used
04627                 delete pNewCol;
04628                 pNewCol = NULL;
04629             }
04630         }
04631     
04632         return TRUE;
04633     }
04634 
04635     // something was a bit squiffy
04636     return FALSE;
04637 }
04638 
04639 /********************************************************************************************
04640 
04641 >   virtual void ColourSGallery::SelectionHasChanged(void);
04642 
04643     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04644     Created:    7/8/96
04645 
04646     Purpose:    To inform the gallery that the selection has changed in some way.
04647 
04648                 The colour gallery does the same as the base class, but also ensures
04649                 that the selection includes some non-library items for some of the
04650                 "editing" commands (edit, redefine, rename, delete)
04651 
04652 ********************************************************************************************/
04653 
04654 void ColourSGallery::SelectionHasChanged(void)
04655 {
04656     if (DisplayTree == NULL || AmShaded || !IsVisible())
04657         return;
04658 
04659     INT32 Count = DisplayTree->GetSelectedItemCount();
04660 
04661     // Determine if the entire selection consists only of library colours...
04662     BOOL AllSelectionIsLibrary = TRUE;
04663     SGDisplayColour *Col = (SGDisplayColour *) DisplayTree->FindNextSelectedItem(NULL);
04664     if (Col == NULL)
04665         AllSelectionIsLibrary = FALSE;
04666 
04667     while (Col != NULL)
04668     {
04669         if (!Col->IsALibraryColour())
04670             AllSelectionIsLibrary = FALSE;
04671 
04672         Col = (SGDisplayColour *) DisplayTree->FindNextSelectedItem(Col);
04673     }
04674 
04675     EnableGadget(_R(IDC_GALLERY_APPLY),     (Count == 1));  // Apply needs exactly 1 item
04676 
04677     // Redefine, Edit, Name, all need exactly one item, and it cannot be a library item
04678     EnableGadget(_R(IDC_GALLERY_REDEFINE),  (Count == 1 && !AllSelectionIsLibrary));
04679     EnableGadget(_R(IDC_GALLERY_EDIT),      (Count == 1 && !AllSelectionIsLibrary));
04680     EnableGadget(_R(IDC_GALLERY_NAME),      (Count == 1 && !AllSelectionIsLibrary));
04681 
04682     EnableGadget(_R(IDC_GALLERY_NEW),       (Count <= 1));  // New needs 0 or 1 items
04683 
04684     // Delete needs 1 or more items, and some of them must be document colours
04685     EnableGadget(_R(IDC_GALLERY_DELETE),    (Count > 0 && !AllSelectionIsLibrary));
04686 
04687     EnableGadget(_R(IDC_GALLERY_UNDO),      TRUE);          // Undo/menu always available
04688     EnableGadget(_R(IDC_GALLERY_MENU),      TRUE);
04689 
04690     Document *pDoc = Document::GetSelected();
04691     EnableGadget(_R(IDC_COLGAL_BACKGROUND), Count == 1 && pDoc != NULL);
04692 }
04693 
04694 /***********************************************************************************************
04695 
04696 >   void ColourSGallery::DoShadeGallery(BOOL ShadeIt)
04697 
04698     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
04699     Created:    4/7/97
04700     Inputs:     ShadeIt -   TRUE if the gallery is being shaded
04701                             FALSE if the gallery is being unshaded
04702     Purpose:    Called by the base class whenever the shaded status of the gallery
04703                 is changed, to allow derived galleries to shade/unshade any extra
04704                 controls that they provide in the window. ONLY called if the gallery
04705                 is actually open/visible.
04706 
04707     Notes:      Need not be overridden - the default action is to do nothing extra
04708                 to the normal shade/unshade operation.
04709     SeeAlso:    Gallery::ShadeGallery; Gallery::UnshadeGallery
04710 
04711 ***********************************************************************************************/
04712 
04713 void ColourSGallery::DoShadeGallery(BOOL ShadeIt)
04714 {
04715     // Shade any non-standard buttons that we have on the gallery
04716     EnableGadget(_R(IDC_COLGAL_BACKGROUND), !ShadeIt);
04717 }
04718 
04719 
04720 
04721 
04722 
04723 
04724 
04725 
04726 
04727 
04728 
04729 
04730 
04731 
04732 
04733 
04734 
04735 
04736 
04737 /********************************************************************************************
04738 
04739 >   BOOL OpDisplayColourGallery::Init()
04740 
04741     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04742     Created:    9/2/95 (base generated in sgbase.cpp)
04743     Inputs:     -
04744     Outputs:    -
04745     Returns:    TRUE if the operation could be successfully initialised 
04746                 FALSE if no more memory could be allocated 
04747                 
04748     Purpose:    OpDisplayColourGallery initialiser method
04749     Errors:     ERROR will be called if there was insufficient memory to allocate the 
04750                 operation.
04751     SeeAlso:    -
04752 
04753 ********************************************************************************************/
04754 
04755 BOOL OpDisplayColourGallery::Init()
04756 {
04757     return (RegisterOpDescriptor(
04758                                 0,
04759                                 _R(IDS_DISPLAY_COLOUR_GALLERY),
04760                                 CC_RUNTIME_CLASS(OpDisplayColourGallery),
04761                                 OPTOKEN_DISPLAYCOLOURGALLERY,
04762                                 OpDisplayColourGallery::GetState,
04763                                 _R(IDST_COLGAL_OPENGALLERY),
04764                                 _R(IDBBL_DISPLAY_COLOUR_GALLERY),
04765                                 _R(IDC_BTN_SGCOLOUR), // UINT32 resourceID = 0, // resource ID
04766                                 _R(IDC_BTN_SGCOLOUR), // UINT32 controlID = 0,  // control ID
04767                                 SYSTEMBAR_ILLEGAL,    // SystemBarType GroupBarID = SYSTEMBAR_ILLEGAL,  // group bar ID
04768                                 TRUE,     // BOOL ReceiveMessages = TRUE,   // BODGE
04769                                 FALSE,    // BOOL Smart = FALSE,
04770                                 TRUE,     // BOOL Clean = TRUE,   
04771                                 NULL,     // OpDescriptor *pVertOpDesc = NULL,
04772                                 0,    // UINT32 OneOpenInstID = 0,      
04773                                 0,    // UINT32 AutoStateFlags = 0,
04774                                 TRUE      // BOOL fCheckable = FALSE
04775                                 )
04776                                 );
04777 
04778 }               
04779     
04780 /********************************************************************************************
04781 
04782 >   OpState OpDisplayColourGallery::GetState(String_256*, OpDescriptor*)
04783 
04784     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04785     Created:    9/2/95 (base generated in sgbase.cpp)
04786     Inputs:     -
04787     Outputs:    -
04788     Returns:    The state of the OpDisplayColourGallery operation
04789     Purpose:    For finding the OpDisplayColourGallery's state. 
04790     Errors:     -
04791     SeeAlso:    -
04792 
04793 ********************************************************************************************/
04794 
04795 OpState OpDisplayColourGallery::GetState(String_256* UIDescription, OpDescriptor*)
04796 {
04797     OpState OpSt;  
04798 
04799     // If the gallery is currenty open, then the menu item should be ticked
04800     SuperGallery* pSuperGallery = FindGallery();
04801     if (pSuperGallery != NULL)
04802         OpSt.Ticked = pSuperGallery->IsVisible();
04803 
04804     // If there are no open documents, you can't toggle the gallery
04805     OpSt.Greyed = (Document::GetSelected() == NULL);
04806     return(OpSt);   
04807 }
04808 
04809 
04810 
04811 /********************************************************************************************
04812 
04813 >   void OpDisplayColourGallery::Do(OpDescriptor*)
04814 
04815     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04816     Created:    9/2/95 (base generated in sgbase.cpp)
04817     Inputs:     -
04818     Outputs:    -
04819     Returns:    -
04820     Purpose:    Displays the Colours gallery
04821                 Updates the button state for this Op (the button sticks down while the
04822                 gallery is open)
04823     Errors:     -
04824     SeeAlso:    -
04825 
04826 ********************************************************************************************/
04827 
04828 void OpDisplayColourGallery::Do(OpDescriptor*)
04829 {
04830     SuperGallery *pSuperGallery = FindGallery();
04831 
04832     if (pSuperGallery != NULL)
04833     {
04834         // Toggle the visible state of the gallery window
04835         pSuperGallery->SetVisibility( !pSuperGallery->IsVisible() );
04836 
04837         // And update the gallery button state
04838         SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYCOLOURGALLERY), pSuperGallery->IsVisible());
04839     }
04840     
04841     End();
04842 }
04843 
04844 
04845 
04846 /********************************************************************************************
04847 
04848 >   static SuperGallery *OpDisplayColourGallery::FindGallery(void)
04849 
04850     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04851     Created:    9/2/95 (base generated in sgbase.cpp)
04852 
04853     Returns:    NULL or a pointer to the Colour gallery instance
04854 
04855     Purpose:    Finds the Colour gallery class instance
04856 
04857     Notes:      The bars system always keeps one Colour gallery alive for us.
04858                 If one is not found, this usually indicates that it can't be found
04859                 in bars.ini: Check that the 'Name' string *exactly* matches the
04860                 title string given in bars.ini.
04861                 Also check that bars.ini indicates the bar is of the ColourSGallery class
04862 
04863 ********************************************************************************************/
04864 
04865 SuperGallery *OpDisplayColourGallery::FindGallery(void)
04866 {
04867     SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_COLOURSGALLERY));
04868 
04869     if (!pSuperGallery) pSuperGallery = new ColourSGallery;
04870 
04871     if (pSuperGallery != NULL)
04872     {
04873         if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(ColourSGallery))
04874             return(pSuperGallery);
04875 
04876         ERROR3("Got the Colour gallery but it's not of the ColourSGallery class");
04877     }
04878     else
04879     {
04880         ERROR3("Can't find the Colour gallery in bars.ini!\n");
04881     }
04882 
04883     return(NULL);
04884 }
04885 
04886 
04887 
04888 
04889 
04890 
04891 
04892 
04893 
04894 
04895 
04896 const INT32 ColourNameDlg::IDD = _R(IDD_COLOURNAMEDLG);
04897 const CDlgMode ColourNameDlg::Mode = MODAL;
04898 
04899 /********************************************************************************************
04900 
04901 >   ColourNameDlg::ColourNameDlg(): DialogOp(ColourNameDlg::IDD, ColourNameDlg::Mode) 
04902 
04903 
04904     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04905     Created:    1/4/95
04906 
04907     Purpose:    ColourNameDlg constructor.
04908 
04909 ********************************************************************************************/
04910 
04911 ColourNameDlg::ColourNameDlg() : DialogOp(ColourNameDlg::IDD, ColourNameDlg::Mode) 
04912 {
04913 }        
04914 
04915 
04916 
04917 /********************************************************************************************
04918 
04919 >   MsgResult ColourNameDlg::Message( CDlgMessage DlgMsg, CGadgetID Gadget)
04920 
04921     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
04922     Created:    1/4/95
04923     Inputs:     -
04924     Outputs:    -
04925     Returns:    -
04926     Purpose:    Handles all the scale dialog's messages 
04927     Errors:     -
04928     SeeAlso:    -
04929 
04930 ********************************************************************************************/
04931 
04932 MsgResult ColourNameDlg::Message(Msg* Message)
04933 {
04934     if (IS_OUR_DIALOG_MSG(Message))
04935     {
04936         DialogMsg* Msg = (DialogMsg*)Message;
04937 //      BOOL EndDialog = FALSE;
04938 
04939         switch (Msg->DlgMsg)
04940         {
04941             case DIM_CREATE:
04942                 {
04943                     String_256 Name;
04944 
04945                     if (Info->TheName != NULL)          // Must be creating new colour
04946                     {
04947                         Name.MakeMsg(_R(IDS_COLNAME_CREATE));
04948                         SetStringGadgetValue(_R(IDOK), _R(IDS_COLNAME_YCREATE));
04949                         SetStringGadgetValue(_R(IDC_COLNAME_TEXT), *Info->TheName);
04950                     }
04951                     else if (Info->TheColour != NULL)   // Are renaming existing colour
04952                     {
04953                         Name.MakeMsg(_R(IDS_COLNAME_ALTER));
04954                         SetStringGadgetValue(_R(IDOK), _R(IDS_COLNAME_YALTER));
04955                         SetStringGadgetValue(_R(IDC_COLNAME_TEXT), *Info->TheColour->GetName());
04956                     }
04957 
04958                     SetTitlebarName(&Name);
04959                     SetKeyboardFocus (_R(IDC_COLNAME_TEXT));
04960                     HighlightText    (_R(IDC_COLNAME_TEXT));
04961                 }
04962                 break;
04963                 
04964             case DIM_COMMIT:
04965             case DIM_SOFT_COMMIT:
04966                 CommitName();
04967                 break;
04968 
04969             case DIM_CANCEL:
04970                 Close();
04971                 End();
04972                 break;
04973 
04974             case DIM_REDRAW:
04975                 if (Msg->GadgetID == _R(IDC_COLNAME_PATCH))
04976                 {
04977                     ReDrawInfoType *RedrawInfo = (ReDrawInfoType*) Msg->DlgMsgParam;
04978                     DocRect VirtualSize(0, 0, RedrawInfo->dx, RedrawInfo->dy);
04979                     RenderRegion *pRender = CreateOSRenderRegion(&VirtualSize, RedrawInfo);
04980                     if (pRender)
04981                     {
04982                         pRender->SaveContext();
04983 
04984                         DocColour PatchCol(128L, 128L, 128L);
04985                         if (Info->TheColour != NULL)
04986                             PatchCol.MakeRefToIndexedColour(Info->TheColour);
04987 
04988                         pRender->SetLineWidth(0);
04989                         pRender->SetLineColour(PatchCol);
04990                         pRender->SetFillColour(PatchCol);
04991                         pRender->DrawRect(&VirtualSize);
04992 
04993                         pRender->RestoreContext();
04994 
04995                         DestroyOSRenderRegion(pRender);
04996                     }
04997                 }
04998                 break;
04999 
05000             default:
05001                 break;
05002         }
05003 
05004         return (DLG_EAT_IF_HUNGRY(Msg)); 
05005     }
05006 
05007     return OK; 
05008 }  
05009 
05010 
05011 
05012 /********************************************************************************************
05013 
05014 >   void ColourNameDlg::CommitName(void)
05015 
05016     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05017     Created:    2/4/95
05018 
05019     Purpose:    Commits to the current setting for the new name
05020                 Reads the name into the supplied destination, sets the return value to
05021                 TRUE and closes and ends the Dlg Op.
05022 
05023     Notes:      If the result is placed into TheColour, then a ColourChangingMsg broadcast
05024                 will be sent. Thus, if a caller wants only to rename a colour, they need
05025                 only call up the dialogue upon that colour - set and forget.
05026 
05027 ********************************************************************************************/
05028 
05029 void ColourNameDlg::CommitName(void)
05030 {
05031     Info->Result = TRUE;
05032 
05033     String_256 NewName = GetStringGadgetValue(_R(IDC_COLNAME_TEXT));
05034 
05035     if (NewName.Length() < 1)   // User gave NULL name. Use 'Unnamed' instead.
05036         NewName.MakeMsg(_R(IDS_UNNAMEDCOLOUR));
05037 
05038     if (Info->TheList != NULL && Info->TheColour != NULL)
05039     {
05040         // We must set the new name for the colour - first make sure it's unique
05041         String_64 UniqueName;
05042         Info->TheList->GenerateUniqueColourName((const StringBase *) &NewName, &UniqueName);
05043 
05044         IndexedColour *NewCol = new IndexedColour(*Info->TheColour);
05045         if (NewCol == NULL)
05046             InformError();
05047         else
05048         {
05049             NewCol->SetName(UniqueName);
05050             ColourManager::ChangeColour(Info->TheList, NewCol, Info->TheColour, TRUE);
05051         }
05052     }
05053     else if (Info->TheName != NULL)
05054     {
05055         // We just copy the string into the result string, truncating at 63 chars
05056         NewName.Left(Info->TheName, 63);
05057     }
05058 
05059     Close();
05060     End();
05061 }
05062 
05063 
05064 
05065 /********************************************************************************************
05066 
05067 >   OpState ColourNameDlg::GetState(String_256*, OpDescriptor*)
05068 
05069     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05070     Created:    1/4/95
05071     Purpose:    ColourNameDlg GetState method
05072 
05073 ********************************************************************************************/
05074 
05075 OpState ColourNameDlg::GetState(String_256*, OpDescriptor*)
05076 {    
05077     OpState OpSt;
05078     return(OpSt);
05079 }
05080 
05081 
05082          
05083 /********************************************************************************************
05084 
05085 >   BOOL ColourNameDlg::Init(void)
05086 
05087     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05088     Created:    1/4/95
05089 
05090     Purpose:    ColourNameDlg Init method. Called by sginit.cpp
05091 
05092 ********************************************************************************************/
05093 
05094 BOOL ColourNameDlg::Init(void)
05095 {  
05096     return (RegisterOpDescriptor(
05097                                 0,
05098                                 _R(IDS_COLOURNAMEDLG),
05099                                 CC_RUNTIME_CLASS(ColourNameDlg),
05100                                 OPTOKEN_COLOURNAMEDLG,
05101                                 ColourNameDlg::GetState,
05102                                 0,  // help ID
05103                                 0   // bubble ID
05104                                 )
05105             ); 
05106 }   
05107  
05108 
05109 
05110 /********************************************************************************************
05111 
05112 >   BOOL ColourNameDlg::Create()
05113 
05114     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05115     Created:    1/4/95
05116     Returns:    TRUE if successful, else FALSE
05117     Purpose:    ColourNameDlg create method 
05118 
05119 ********************************************************************************************/
05120 
05121 BOOL ColourNameDlg::Create()
05122 {
05123     return(DialogOp::Create());
05124 }
05125 
05126 
05127 
05128 /********************************************************************************************
05129 
05130 >   void ColourNameDlg::DoWithParam(OpDescriptor*,OpParam* pOpParam)
05131 
05132     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05133     Created:    1/4/95
05134     Inputs:     pOpParam = ptr to a ColourNameParam struct
05135 
05136     Purpose:    Creates then opens the dialog 
05137 
05138 ********************************************************************************************/
05139 
05140 
05141 void ColourNameDlg::DoWithParam(OpDescriptor*, OpParam* pOpParam)
05142 {
05143     ERROR3IF(pOpParam == NULL, "Come on, play by the rules");
05144 
05145     Info = (ColourNameParam *) pOpParam;
05146 
05147     if (Info->TheColour == NULL && Info->TheName == NULL)
05148     {
05149         ERROR3("ColourNameDlg parameters are unhelpful to say the least");
05150         End();
05151     }
05152 
05153     if (!Create())
05154     {
05155         InformError();
05156         End();
05157     }
05158 }
05159 
05160 
05161 
05162 /********************************************************************************************
05163 
05164 >   static BOOL ColourNameDlg::InvokeDialog(ColourList *ParentList,
05165                                             IndexedColour *ColourToName)
05166 
05167     vAuthor:    Jason
05168     Created:    1/4/95
05169 
05170     Returns:    TRUE if the OK button was clicked, FALSE if cancel was clicked
05171 
05172     Inputs:     ParentList   - the list in which the colour resides (not NULL)
05173                 ColourToName - the colour whose name should be changed (not NULL)
05174 
05175     Purpose:    Opens the gallery name dialogue on screen, elicits a response, 
05176                 and returns having set the new name. This is a MODAL dlg.
05177 
05178                 This variant renames an existing colour. The window indicates
05179                 that renaming is going to occur, and has 'Apply' and 'Cancel'
05180                 buttons.
05181 
05182                 If the name is changed, the colour name will be set (to a name
05183                 guaranteed to be unique within the colour list), and an appropriate
05184                 ColourChangingMsg willbe broadcast (i.e. it's a set-and-forget mode)
05185 
05186 ********************************************************************************************/
05187 
05188 BOOL ColourNameDlg::InvokeDialog(ColourList *ParentList, IndexedColour *ColourToName)
05189 {
05190     ERROR3IF(ParentList == NULL || ColourToName == NULL, "Come on, play by the rules");
05191 
05192     ColourNameParam Info(ParentList, ColourToName);
05193     OpDescriptor *NameDlg = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(ColourNameDlg));
05194 
05195     ERROR3IF(NameDlg == NULL,
05196             "ColourNameDlg::InvokeDialog is unable to find the Dlg OpDescriptor");
05197 
05198     if (NameDlg != NULL)
05199         NameDlg->Invoke(&Info);
05200 
05201     return(Info.Result);
05202 }
05203 
05204 
05205 
05206 /********************************************************************************************
05207 
05208 >   static BOOL ColourNameDlg::InvokeDialog(String_64 *NameToFill,
05209                                             IndexedColour *DisplayColour)
05210 
05211     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
05212     Created:    1/4/95
05213 
05214     Returns:    TRUE if the OK button was clicked, FALSE if cancel was clicked
05215 
05216     Inputs:     NameToFill - A String_64 containing the default name. This will be
05217                 changed to the new nbame to use.
05218 
05219                 DisplayColour - A colour to be displayed in the dialogue. This is just
05220                 for the user to look at and say "oooh, pretty!"
05221 
05222     Purpose:    Opens the gallery name dialogue on screen, elicits a response, 
05223                 and returns having set the new name. This is a MODAL Dlg.
05224 
05225                 This variant gets the name of a new colour. The window indicates
05226                 that a new colour is being created, and has 'Create' and 'Cancel'
05227                 buttons. Only if it returns TRUE should you create the colour.
05228 
05229                 Note that this variant is not 'set and forget'. You have to do
05230                 something with the returned name.
05231 
05232     Notes:      DO NOT use this method with the result of a call to the
05233                 IndexedColour::GetName() function! See the other variant to do this.
05234 
05235                 If you SetName() a colour already in a colour list, (in which case
05236                 you should be using the other variant of this method) then you MUST
05237                 ensure that the name you set is guaranteed to be unique within the
05238                 list (or export/import will fail).
05239     
05240 ********************************************************************************************/
05241 
05242 BOOL ColourNameDlg::InvokeDialog(String_64 *NameToFill, IndexedColour *DisplayColour)
05243 {
05244     ERROR3IF(NameToFill == NULL, "Come on, play by the rules");
05245 
05246     ColourNameParam Info(NameToFill, DisplayColour);
05247     OpDescriptor *NameDlg = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(ColourNameDlg));
05248 
05249     ERROR3IF(NameDlg == NULL,
05250             "ColourNameDlg::InvokeDialog is unable to find the Dlg OpDescriptor");
05251 
05252     if (NameDlg != NULL)
05253         NameDlg->Invoke(&Info);
05254 
05255     return(Info.Result);
05256 }
05257 

Generated on Sat Nov 10 03:46:51 2007 for Camelot by  doxygen 1.4.4