sglayer.cpp

Go to the documentation of this file.
00001 // $Id: sglayer.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 // SGLayer.cpp - Layer SuperGallery classes - LayerSGallery and SGDisplayLayer
00099 
00100 
00101 #include "camtypes.h"
00102 
00103 // WEBSTER - markn 15/1/97
00104 // Removed all code not needed in Webster
00105 // This is the same as the code removed from RALPH
00106 //#ifdef WEBSTER
00107 //#define EXCLUDE_GALS
00108 //#endif
00109 
00110 //#include "app.h"      // For GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "gallery.h"  // For _R(IDC_GALLERY_LISTBOX)
00112 //#include "galres.h"
00113 //#include "galstr.h"
00114 #include "layergal.h"
00115 #include "sgdrag.h"
00116 #include "sginit.h"
00117 #include "sglayer.h"
00118 #include "sgmenu.h"
00119 
00120 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00121 #include "layer.h"
00122 //#include "markn.h"
00123 //#include "resource.h"
00124 //#include "barsdlgs.h" 
00125 //#include "simon.h"
00126 #include "sprdmsg.h"
00127 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00128 #include "dragmgr.h"
00129 //#include "docvmsg.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00130 
00131 #include "ccdc.h"       // For render-into-dialogue support
00132 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00133 #include "grnddib.h"
00134 #include "guides.h"
00135 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00136 #include "layerprp.h"
00137 #include "layermsg.h"
00138 //#include "richard2.h"
00139 //#include "andy.h"
00140 //#include "sgframe.h"  // SGDisplayFrame
00141 //#include "aprps.h"
00142 //#include "will2.h"        // for _R(IDS_LAYERGAL_GALLNAME)
00143 //#include "sliceres.h"
00144 #include "layermgr.h"
00145 
00146 #include "helpuser.h"
00147 //#include "xshelpid.h"
00148 //#include "helppath.h"
00149 
00150 void Beep();
00151 
00152 #ifndef EXCLUDE_GALS
00153 // Implement the dynamic class bits...
00154 CC_IMPLEMENT_DYNCREATE(LayerSGallery, SuperGallery)
00155 CC_IMPLEMENT_DYNAMIC(SGLayerGroup, SGDisplayGroup)
00156 CC_IMPLEMENT_DYNAMIC(SGDisplayLayer, SGDisplayItem)
00157 #else
00158 CC_IMPLEMENT_DYNCREATE(LayerSGallery, Operation)
00159 #endif
00160 
00161 // This line mustn't go before any CC_IMPLEMENT_... macros
00162 #define new CAM_DEBUG_NEW
00163 
00164 
00165 
00166 #ifdef _DEBUG
00167 // DO_SNAP_BUTTON - set to (1) for a snap-button for each layer, (0) for no snap-button support
00168 #define DO_SNAP_BUTTON (0)
00169 #else
00170 #define DO_SNAP_BUTTON (0)
00171 #endif
00172 
00173 
00174 #ifndef EXCLUDE_GALS
00175 
00176 /***********************************************************************************************
00177 
00178 >   SGLayerGroup::SGLayerGroup(SuperGallery *ParentGal,
00179                     Document *ParentDoc = NULL, Library *ParentLib = NULL, BOOL IsForeground = TRUE);
00180 
00181     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00182     Created:    31/10/94
00183 
00184     Inputs:     ParentGal - points to the SuperGallery object which 'owns' this node
00185                 ParentDoc - NULL, or a pointer to the document this group references
00186                 ParentLib - NULL, or a pointer to the library this group references
00187 
00188     Purpose:    SGLayerGroup constructor. Initialises the Group's parent pointers to
00189                 point at its parent(s). Note that generally speaking, one of ParentDoc,
00190                 ParentLib will be NULL, and the other will be non-NULL.
00191 
00192     Notes:      This constructor does nothing - jusat passes the call on to the baseclass
00193                 constructor of identical proportions.
00194 
00195     SeeAlso:    SGDisplayGroup::SGDisplayGroup
00196 
00197 ***********************************************************************************************/
00198 
00199 SGLayerGroup::SGLayerGroup(SuperGallery *ParentGal,
00200                             Document *ParentDoc, Library *ParentLib,BOOL IsForeground)
00201                 : SGDisplayGroup(ParentGal, ParentDoc, ParentLib)
00202 {
00203     Foreground = IsForeground;
00204 }
00205 
00206 
00207 
00208 /***********************************************************************************************
00209 
00210 >   virtual BOOL SGLayerGroup::HandleEvent(SGEventType EventType, void *EventInfo,
00211                                              SGMiscInfo *MiscInfo)
00212 
00213     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00214     Created:    1/2/95
00215 
00216     Inputs:     See SGDisplayNode::HandleEvent
00217 
00218     Returns:    TRUE if the event was handled successfully
00219                 FALSE if it was not
00220 
00221     Purpose:    Handles a SuperGallery DisplayTree event
00222 
00223     Notes:      This overrides the SGDisplayNGroup::HandleEvent method, to give a group-type
00224                 thing which does wierd stuff for layer galleries (i.e. does not fold,
00225                 and gives column titles in the 'group' display)
00226 
00227     SeeAlso:    SGDisplayGroup::HandleEvent
00228 
00229 ***********************************************************************************************/
00230 
00231 BOOL SGLayerGroup::HandleEvent(SGEventType EventType, void *EventInfo,
00232                                  SGMiscInfo *MiscInfo)
00233 {
00234     // And handle the specific event
00235     switch (EventType)
00236     {
00237         case SGEVENT_REDRAW:
00238             {
00239                 DocRect MyRect(FormatRect); // Rely on cached format info being correct
00240 
00241                 SGRedrawInfo *RedrawInfo = GetRedrawInfo(EventType, EventInfo);
00242 
00243                 if (IMustRedraw(RedrawInfo))
00244                 {
00245                     StartRendering(RedrawInfo, MiscInfo);
00246 
00247                     DocColour Col(192L, 192L, 192L);    //128, 128, 128);
00248 
00249                     RedrawInfo->Renderer->SetLineWidth(0);
00250                     RedrawInfo->Renderer->SetLineColour(RedrawInfo->Transparent);
00251                     RedrawInfo->Renderer->SetFillColour(Col);
00252                     RedrawInfo->Renderer->DrawRect(&MyRect);
00253 
00254                     ReadGroupTitle();       // (Re)Cache the title text
00255 
00256                     // Line up above indented items below
00257                     MyRect.lo.x += IndentWidth + MiscInfo->PixelSize;
00258 
00259                     // Render column titles above the 'locked' and 'invisible' columns
00260                     DocRect VisibleBtn;
00261                     DocRect LockedBtn;
00262                     DocRect SnapBtn;
00263                     SGDisplayLayer::CalculateButtonRects(MiscInfo, &MyRect,
00264                                                          &VisibleBtn, &LockedBtn, &SnapBtn);
00265 
00266                     DrawBitmap(RedrawInfo->Renderer, &VisibleBtn, _R(IDB_LGAL_VISIBLE));
00267                     DrawBitmap(RedrawInfo->Renderer, &LockedBtn,  _R(IDB_LGAL_LOCKED));
00268 #if DO_SNAP_BUTTON
00269                     DrawBitmap(RedrawInfo->Renderer, &SnapBtn,    _R(IDB_LGAL_SNAP));
00270 #endif
00271 
00272                     // And finally, render the title text
00273                     MyRect.lo.x += SG_GapBeforeText;    // Leave a small gap before text
00274                     if (MyRect.lo.x < MyRect.hi.x)      // If still room left, draw title
00275                     {
00276                         RedrawInfo->Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &Col);
00277                         
00278                         String_256 NewTitleText;
00279 
00280                         UINT32 IDS = _R(IDS_LAYERGAL_FOREGROUND);
00281                         if (!IsForeground())
00282                             IDS = _R(IDS_LAYERGAL_BACKGROUND);
00283 
00284                         NewTitleText.MakeMsg(IDS, (TCHAR *)TitleText);
00285                         RedrawInfo->Renderer->DrawFixedSystemText(&NewTitleText, MyRect);
00286                     }
00287 
00288                     StopRendering(RedrawInfo, MiscInfo);
00289                 }
00290 
00291                 // Check if the cliprect overlaps any of our children - if not, then we
00292                 // can return now, passing the event on quickly without bothering to give
00293                 // it to our children.
00294                 if (GetChild() == NULL ||
00295                     !ChildArea.IsIntersectedWith(RedrawInfo->Bounds))
00296                 {
00297                     return(FALSE);
00298                 }
00299             }
00300             break;
00301 
00302 
00303         case SGEVENT_MOUSECLICK:
00304             // Mouse clicks on this group type are ignored - but we claim them so that the
00305             // event is not passed on around the tree unnecessarily.
00306             {
00307                 SGMouseInfo *MouseInfo = GetMouseInfo(EventType, EventInfo);
00308                 if (FormatRect.ContainsCoord(MouseInfo->Position))
00309                     return(TRUE);
00310             }
00311             break;      
00312 
00313 
00314         default:
00315             // For all other purposes (formatting etc), let the base class handle the event
00316             return(SGDisplayGroup::HandleEvent(EventType, EventInfo, MiscInfo));
00317             break;
00318     }
00319 
00320     // Pass the event on to my children, as appropriate, and return the result
00321     return(GiveEventToMyChildren(EventType, EventInfo, MiscInfo));
00322 }
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 // -- Static variables
00333 SGDisplayLayer *SGDisplayLayer::LastClickedLayer = NULL;
00334 
00335 
00336 /***********************************************************************************************
00337 
00338 >   SGDisplayLayer::SGDisplayLayer()
00339 
00340     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00341     Created:    27/1/95 (base generated in sgbase.cpp)
00342 
00343     Purpose:    SGDisplayLayer constructor
00344                 DON'T call this constructor. It ERROR3's. Call the other constructor
00345 
00346 ***********************************************************************************************/
00347 
00348 SGDisplayLayer::SGDisplayLayer()
00349 {
00350     ERROR3("Illegal call on default SGDisplayLayer constructor - call the other one!");
00351     TheLayer = NULL;
00352 }
00353 
00354 
00355 
00356 /***********************************************************************************************
00357 
00358 >   SGDisplayLayer::SGDisplayLayer(Layer *LayerToDisplay)
00359 
00360     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00361     Created:    27/1/95 (base generated in sgbase.cpp)
00362 
00363     Inputs:     LayerToDisplay - The Layer this item will display
00364 
00365     Purpose:    SGDisplayLayer constructor
00366 
00367 ***********************************************************************************************/
00368 
00369 SGDisplayLayer::SGDisplayLayer(Layer *LayerToDisplay)
00370 {
00371     ERROR3IF(LayerToDisplay == NULL,
00372                 "SGDisplayLayer - trying to construct me with a NULL parameter is bad");
00373 
00374     TheLayer = LayerToDisplay;
00375 }
00376 
00377 
00378 
00379 /***********************************************************************************************
00380 
00381 >   SGDisplayLayer::~SGDisplayLayer()
00382 
00383     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00384     Created:    27/1/95 (base generated in sgbase.cpp)
00385 
00386     Purpose:    SGDisplayLayer destructor
00387 
00388     Notes:      Ensures the LastClickedLayer memory is not left pointing at this layer
00389 
00390 ***********************************************************************************************/
00391 
00392 SGDisplayLayer::~SGDisplayLayer()
00393 {
00394     // Make sure LastClickedLayer pointer is not left in an invalid state
00395     if (this == LastClickedLayer)
00396         LastClickedLayer = NULL;
00397 }
00398 
00399 
00400 
00401 /***********************************************************************************************
00402 
00403 >   virtual void SGDisplayLayer::CalculateMyRect(SGFormatInfo *FormatInfo,
00404                                                 SGMiscInfo *MiscInfo)
00405 
00406     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00407     Created:    27/1/95 (base generated in sgbase.cpp)
00408 
00409     Inputs:     FormatInfo - The formatting info from which to calculate my position/size
00410                 MiscInfo - As usual, the useful misc info struct
00411 
00412     Outputs:    member variable FormatRect - is returned filled in with the size/position of
00413                 this Layer item's display area. This is dependent upon the current display
00414                 mode and format state
00415 
00416                 FormatInfo will be updated as a result of the formatting operation
00417 
00418     Purpose:    Shared code for Layer items to calculate where they will appear in the
00419                 grand scheme of things
00420 
00421     Notes:      Layers supply only one display mode ("full info")
00422 
00423     Scope:      private (for use of SGDisplayLayer class only)
00424 
00425 ***********************************************************************************************/
00426 
00427 void SGDisplayLayer::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo)
00428 {
00429     INT32 XSize = SG_InfiniteWidth;
00430     INT32 YSize = SG_DefaultSmallIcon;
00431 
00432     CalculateFormatRect(FormatInfo, MiscInfo, XSize, YSize);
00433 }
00434 
00435 
00436 
00437 /***********************************************************************************************
00438 
00439 >   static void SGDisplayLayer::CalculateButtonRects(INT32 ButtonGap, DocRect *MyRect,
00440                                                     DocRect *VisibleBtn, DocRect *LockedBtn,
00441                                                     DocRect *SnapBtn = NULL)
00442 
00443     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00444     Created:    1/2/95
00445 
00446     Inputs:     ButtonGap - The gap between buttons, in MILLIPOINTS (usually TwoPixels)
00447                 MyRect - A rectangle vbased on FormatRect, from which to carve out 2 buttons
00448 
00449     Outputs:    MyRect - The used portion of MyRect will have been subtracted
00450                 VisibleBtn - Will contain the button rectangle for the 'Visible' button
00451                 LockedBtn - Will contain the button rectangle for the 'Locked' button
00452                 SnapBtn - if non-NULL, will return containing the snap-button position
00453 
00454     Purpose:    Shared method to determine where the visible/locked buttons will be displayed
00455 
00456     Scope:      private
00457 
00458 ***********************************************************************************************/
00459 
00460 void SGDisplayLayer::CalculateButtonRects(SGMiscInfo *MiscInfo, DocRect *MyRect,
00461                                             DocRect *VisibleBtn, DocRect *LockedBtn, DocRect *SnapBtn)
00462 {
00463     INT32 ButtonGap = MiscInfo->PixelSize * 2;
00464     INT32 ButtonSize = MiscInfo->PixelSize * 16;            // The bitmap glyphs are 16x16 pixels
00465 
00466     // First, render the 'visible' and 'locked' buttons at the left end of our rectangle
00467     *VisibleBtn = *MyRect;
00468     VisibleBtn->hi.x = VisibleBtn->lo.x + ButtonSize;   // Make it a square
00469 
00470     INT32 Excess = VisibleBtn->Height() - ButtonSize;   // Center it in the Y axis
00471     Excess = GridLock(MiscInfo, Excess / 2);
00472     VisibleBtn->lo.y += Excess;
00473     VisibleBtn->hi.y = VisibleBtn->lo.y + ButtonSize;
00474 
00475     MyRect->lo.x = VisibleBtn->hi.x + ButtonGap;    // And exclude it from 'MyRect'
00476 
00477 
00478     *LockedBtn = *MyRect;
00479     LockedBtn->hi.x = LockedBtn->lo.x + ButtonSize; // Make it a square
00480     LockedBtn->lo.y = VisibleBtn->lo.y;             // & use same y coords as for visible button
00481     LockedBtn->hi.y = VisibleBtn->hi.y;
00482 
00483     MyRect->lo.x = LockedBtn->hi.x + ButtonGap;     // And exclude it from 'MyRect'
00484 
00485 #if DO_SNAP_BUTTON
00486     if (SnapBtn != NULL)
00487     {
00488         *SnapBtn = *MyRect;
00489         SnapBtn->hi.x = SnapBtn->lo.x + ButtonSize; // Make it a square
00490         SnapBtn->lo.y = VisibleBtn->lo.y;               // & use same y coords as for visible button
00491         SnapBtn->hi.y = VisibleBtn->hi.y;
00492 
00493         MyRect->lo.x = SnapBtn->hi.x + ButtonGap;       // And exclude it from 'MyRect'
00494     }
00495 #else
00496     // If snapbtn is disabled, fill it in with a sensible rect, just to be safe
00497     if (SnapBtn != NULL)
00498         *SnapBtn = *LockedBtn;
00499 #endif
00500 
00501 
00502     // And grid align the 3 resulting rectangles...
00503     GridLockRect(MiscInfo, VisibleBtn);
00504     GridLockRect(MiscInfo, LockedBtn);
00505     if (SnapBtn != NULL)
00506         GridLockRect(MiscInfo, SnapBtn);
00507     GridLockRect(MiscInfo, MyRect);
00508 }
00509 
00510 
00511 
00512 /***********************************************************************************************
00513 
00514 >   virtual void SGDisplayLayer::HandleRedraw(SGRedrawInfo *RedrawInfo,
00515                                                 SGFormatInfo *FormatInfo)
00516 
00517     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00518     Created:    27/1/95 (base generated in sgbase.cpp)
00519 
00520     Inputs:     RedrawInfo  - The information on the kernel-rendered redraw area
00521                 FormatInfo  - The formatting information structure
00522 
00523                 member variable FormatRect should be set up (before calling this method)
00524                 to be the rectangle in which to draw this item
00525 
00526     Purpose:    SGDisplayLayer item redraw method - removed from the main HandleEvent
00527                 method merely to make the code tidier.
00528 
00529     Scope:      private
00530 
00531 ***********************************************************************************************/
00532 
00533 void SGDisplayLayer::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo)
00534 {
00535     StartRendering(RedrawInfo, MiscInfo);
00536 
00537     DocRect MyRect(FormatRect);     // Get my redraw position from the cached FormatRect
00538 
00539     RenderRegion *Renderer = RedrawInfo->Renderer;
00540 
00541 //  INT32 OnePixel  = (INT32) DevicePixels(MiscInfo, 1);
00542 //  INT32 TwoPixels = (INT32) DevicePixels(MiscInfo, 2);
00543 
00544     Renderer->SetLineWidth(0);
00545     Renderer->SetLineColour(RedrawInfo->Transparent);
00546     DocColour fill(191, 191, 191);
00547     Renderer->SetFillColour(fill);
00548 
00549     // Calculate and redraw the buttons
00550     // NOTE:
00551     // The buttons are usually blank grey rectangles, or a rectangle with an eye/lock
00552     // glyph on them. However, to hint at what the buttons are for, the selected layer
00553     // also shows the buttons in a greyed state
00554 
00555     DocRect VisibleBtn;
00556     DocRect LockedBtn;
00557     DocRect SnapBtn;
00558 
00559     CalculateButtonRects(MiscInfo, &MyRect, &VisibleBtn, &LockedBtn, &SnapBtn);
00560 
00561     // Find out the state of the layer's flags
00562     BOOL ActiveAndVisEd = (GetDisplayedLayer()->IsActive() && Layer::ActiveLayerVisibleAndEditable);
00563     BOOL Visible        = GetDisplayedLayer()->IsVisible();
00564     BOOL Locked         = GetDisplayedLayer()->IsLocked();
00565     BOOL Guide          = GetDisplayedLayer()->IsGuide();
00566     Document* pDoc = (Document*)GetDisplayedLayer()->FindOwnerDoc();
00567 
00568     ERROR3IF(pDoc == NULL,"Displayed layer doesn't have an owner doc");
00569     if (pDoc == NULL) return;
00570 
00571     // Draw 'visible' button (The glyph is "on" when the layer is visible)
00572     if (Visible)
00573     {
00574         if (!Guide && (ActiveAndVisEd || pDoc->IsAllVisible()))
00575             DrawBitmap(Renderer, &VisibleBtn, _R(IDB_LGAL_TICKFORCED));
00576         else
00577             DrawBitmap(Renderer, &VisibleBtn, _R(IDB_LGAL_TICKON));
00578     }
00579     else
00580         DrawBitmap(Renderer, &VisibleBtn, _R(IDB_LGAL_TICKOFF));
00581 
00582     // Draw 'Locked' button (Glyph is on if the layer is unlocked)
00583     if (!Locked)
00584     {
00585         if (ActiveAndVisEd || pDoc->IsMultilayer())
00586             DrawBitmap(Renderer, &LockedBtn, _R(IDB_LGAL_TICKFORCED));
00587         else
00588             DrawBitmap(Renderer, &LockedBtn, _R(IDB_LGAL_TICKON));
00589     }
00590     else
00591         DrawBitmap(Renderer, &LockedBtn, _R(IDB_LGAL_TICKOFF));
00592 
00593 #if DO_SNAP_BUTTON
00594     // Draw 'Snap' button
00595     if (Snap)
00596     {
00597         if (FALSE)      // **** MARKN NEEDS TO FIX THIS ****
00598             DrawBitmap(Renderer, &SnapBtn, _R(IDB_LGAL_TICKFORCED));    // Globally "forced to be ticked"
00599         else
00600             DrawBitmap(Renderer, &SnapBtn, _R(IDB_LGAL_TICKON));        // Just ticked normally
00601     }
00602     else
00603         DrawBitmap(Renderer, &SnapBtn, _R(IDB_LGAL_TICKOFF));           // Just ticked normally
00604 #endif
00605 
00606     Layer* pLayer = GetDisplayedLayer();
00607     ERROR3IF(pLayer == NULL, "I'm displaying a NULL layer? Serious screwup has occurred!");
00608     if (pLayer == NULL)
00609         return;
00610 
00611     DocColour Foreground = RedrawInfo->Foreground;
00612     DocColour Background = RedrawInfo->Background;
00613     DocColour SelForeground = RedrawInfo->SelForeground;
00614     DocColour SelBackground = RedrawInfo->SelBackground;
00615 
00616     if (pLayer->IsGuide())
00617     {
00618         Foreground      = DocColour(COLOUR_RED);
00619         SelBackground   = DocColour(COLOUR_RED);
00620     }
00621 
00622     if (pLayer->IsPageBackground())
00623     {
00624         Foreground      = DocColour(COLOUR_MIDGREY);
00625         SelBackground   = DocColour(COLOUR_MIDGREY);
00626     }
00627 
00628     // Set up the colours for rendering our text, and fill the background if selected
00629     if (Flags.Selected)
00630     {
00631         // Fill the entire background with the 'selected' colour, so we don't
00632         // get gaps between bits of text or uneven rectangles in multiple selections
00633         Renderer->SetFillColour(SelBackground);
00634         Renderer->DrawRect(&MyRect);
00635         Renderer->SetFixedSystemTextColours(&SelForeground,&SelBackground);
00636     }
00637     else
00638         Renderer->SetFixedSystemTextColours(&Foreground, &Background);
00639 
00640     MyRect.lo.x += SG_GapBeforeText;    // Leave a small gap before text begins
00641 
00642     // And render the text
00643     String_256 MyText = pLayer->GetLayerID();
00644     Renderer->DrawFixedSystemText(&MyText, MyRect);             
00645 
00646     StopRendering(RedrawInfo, MiscInfo);
00647 }
00648 
00649 
00650 
00651 /***********************************************************************************************
00652 
00653 >   void SGDisplayLayer::ChangeRangeState(SGDisplayLayer *Start, SGDisplayLayer *End,
00654                                             BOOL Range, INT32 WhichButton, SGMiscInfo *MiscInfo)
00655 
00656     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00657     Created:    19/8/95
00658 
00659     Inputs:     Start   - Points to the node, or start of a range of nodes, to set
00660                 End     - NULL or points to the end of the range
00661                 Range   - TRUE to do a whole range, FALSE to do only the Start node
00662                           This is used to override the range description.
00663                 WhichButton -   0 to change VISIBLE state
00664                                 1 to change LOCKED state
00665                                 2 to change SNAP state
00666                 MiscInfo - The usual (see HandleEvent)
00667 
00668     Purpose:    To handle extension-clicks on layers, we set the state of a range of
00669                 layers rather than just the one clicked. The range usually extends to the
00670                 layer which was previously clicked.
00671 
00672     Notes:      This scans the sibling list containing Start, and sets the states of all
00673                 layers it finds between start and end. If End is not found then Start is
00674                 treated as a single item.
00675 
00676     Scope:      private
00677 
00678 ***********************************************************************************************/
00679 
00680 void SGDisplayLayer::ChangeRangeState(SGDisplayLayer *Start, SGDisplayLayer *End,
00681                                         BOOL Range, INT32 WhichButton, SGMiscInfo *MiscInfo)
00682 {
00683     ERROR3IF(Start == NULL || MiscInfo == NULL, "Illegal NULL params");
00684 
00685     SuperGallery *ParentGallery = GetParentGallery();
00686     ERROR3IF(ParentGallery == NULL, "No parent gallery?! Weird!");
00687 
00688     // Determine the new state based on inverting this item's state
00689     BOOL NewState = TRUE;
00690     switch (WhichButton)
00691     {
00692         case 0:     // Visible state
00693             NewState = !(GetDisplayedLayer()->GetVisibleFlagState());
00694             break;
00695         
00696         case 1:     // Locked sate
00697             NewState = !(GetDisplayedLayer()->GetLockedFlagState());
00698             break;
00699 
00700         case 2:     // Snap state
00701 #if DO_SNAP_BUTTON
00702                 // **** MARKN NEEDS TO FIX THIS ****
00703                 NewState = !(GetDisplayedLayer()->GetVisibleFlagState());
00704 #endif
00705             break;
00706 
00707         default:
00708             ERROR3("Illegal WhichButton parameter to SGDisplayLayer::ChangeRangeState (must be 0..2)");
00709             break;
00710     }
00711 
00712     // Scan the sibling list to find the start and end nodes, and determine if end comes
00713     // before start (in which case we'll need to swap them over before continuing)
00714     SGDisplayLayer *Ptr = NULL;
00715 
00716     if (!Range || End == NULL)
00717         End = Start;
00718 
00719     BOOL FoundStart = FALSE;
00720     BOOL FoundEnd   = FALSE;
00721     BOOL MustSwap   = FALSE;
00722 
00723     Ptr = (SGDisplayLayer *) (Start->GetParent()->GetChild());
00724     while (Ptr != NULL)
00725     {
00726         if (Ptr == Start)
00727             FoundStart = TRUE;
00728 
00729         if (Ptr == End)
00730         {
00731             FoundEnd = TRUE;
00732             MustSwap = !FoundStart;     // If not found Start first, then the range is backwards
00733         }
00734 
00735         Ptr = (SGDisplayLayer *) Ptr->GetNext();
00736     }
00737 
00738     if (!FoundStart)        // Couldn't even find the start node!
00739     {
00740         ERROR3("Start node not found");
00741         return;
00742     }
00743 
00744     if (!FoundEnd)          // No end node? Make the range one item only
00745         End = Start;
00746 
00747     if (MustSwap)           // Range is backwards - swap the pointers
00748     {
00749         Ptr = Start;
00750         Start = End;
00751         End = Ptr;
00752     }
00753 
00754 
00755     // Now scan the list from Start to End, setting all the layers (inclusive)
00756     Ptr = Start;    
00757     
00758     while (Ptr != NULL)
00759     {
00760         DocRect MyRect(Ptr->FormatRect);
00761         DocRect VisibleBtn;
00762         DocRect LockedBtn;
00763         DocRect SnapBtn;
00764         Ptr->CalculateButtonRects(MiscInfo, &MyRect, &VisibleBtn, &LockedBtn, &SnapBtn);
00765 
00766         switch (WhichButton)
00767         {
00768             case 0:     // Visible state
00769                 Ptr->DoChangeState(LAYER_VISIBLE, NewState);
00770                 ParentGallery->ForceRedrawOfArea(&VisibleBtn);
00771                 break;
00772 
00773             case 1:     // Locked state
00774                 Ptr->DoChangeState(LAYER_LOCKED, NewState);
00775                 ParentGallery->ForceRedrawOfArea(&LockedBtn);
00776                 break;
00777 
00778             case 2:     // Snap state
00779 #if DO_SNAP_BUTTON
00780                 // **** MARKN NEEDS TO FIX THIS ****
00781                 Ptr->DoChangeState(LAYER_VISIBLE, NewState);
00782                 ParentGallery->ForceRedrawOfArea(&SnapBtn);
00783 #endif
00784                 break;
00785         }
00786 
00787         if (Ptr == End)                 // Slight strangeness to handle (Start==End) case
00788             Ptr = NULL;                                 // Have hit and processed End, so stop
00789         else
00790             Ptr = (SGDisplayLayer *) Ptr->GetNext();    // Have not, so go on to next layer
00791     }
00792 }
00793 
00794 
00795 
00796 /***********************************************************************************************
00797 
00798 >   virtual BOOL SGDisplayLayer::HandleEvent(SGEventType EventType, void *EventInfo,
00799                                              SGMiscInfo *MiscInfo)
00800 
00801     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00802     Created:    27/1/95 (base generated in sgbase.cpp)
00803 
00804     Inputs:     EventType - An enumerated value describing what type of event is to be processed
00805 
00806                 EventInfo - A structure describing the event (may be NULL). The exact thing
00807                             pointed at by this pointer depends upon the event type:
00808 
00809                             MonoOn
00810                             Event               Thing EventInfo points at
00811                             SGEVENT_FORMAT      (SGFormatInfo *)
00812                             SGEVENT_REDRAW      (SGRedrawInfo *)
00813                             SGEVENT_MOUSECLICK  (SGMouseInfo *)
00814                             MonoOff
00815                 Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this
00816                 information - they provide useful error/type checking, and hide the cast
00817 
00818                 MiscInfo - always provided. Contains a few useful bits of info that may be
00819                 needed for all event types.
00820 
00821     Outputs:    FormatInfo is updated as appropriate
00822 
00823     Returns:    TRUE if the event was handled successfully
00824                 FALSE if it was not
00825 
00826     Purpose:    Handles a SuperGallery DisplayTree event
00827 
00828     Notes:      This overrides the pure virtual SGDisplayNode::HandleEvent method
00829 
00830                 A node need not handle a specific event - if it does not handle it, it
00831                 should return FALSE.
00832 
00833                 Redraw and Formatting handlers should never return TRUE, as this will
00834                 prevent the event from continuing through the tree.
00835 
00836                 Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order
00837                 to pass the event dow the tree. THIS node is a leaf-node, so it doesn't.
00838 
00839     SeeAlso:    SGDisplayNode::HandleEvent
00840 
00841 ***********************************************************************************************/
00842 
00843 BOOL SGDisplayLayer::HandleEvent(SGEventType EventType, void *EventInfo,
00844                                   SGMiscInfo *MiscInfo)
00845 {
00846     switch (EventType)
00847     {
00848         case SGEVENT_FORMAT:
00849             {
00850                 SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo);
00851                 CalculateMyRect(FormatInfo, MiscInfo);      // Cache our FormatRect for later use
00852             }
00853             break;
00854 
00855 
00856         case SGEVENT_REDRAW:
00857             {
00858                 DocRect MyRect(FormatRect);     // Rely on FormatRect being cached from above
00859                 SGRedrawInfo *RedrawInfo = GetRedrawInfo(EventType, EventInfo);
00860 
00861                 if (IMustRedraw(RedrawInfo))    // only redraw if we intersect the clip rect
00862                     HandleRedraw(RedrawInfo, MiscInfo);
00863             }
00864             break;      // exit and return FALSE to pass the redraw event on
00865 
00866 
00867         case SGEVENT_MOUSECLICK:
00868             {
00869                 SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo);
00870 
00871                 SuperGallery *ParentGallery = GetParentGallery();
00872                 ERROR3IF(ParentGallery == NULL, "No parent gallery?! Weird!");
00873 
00874                 if (FormatRect.ContainsCoord(Mouse->Position))
00875                 {
00876                     DocRect MyRect(FormatRect);
00877                     DocRect VisibleBtn;
00878                     DocRect LockedBtn;
00879                     DocRect SnapBtn;
00880                     Document* pDoc = (Document*)GetDisplayedLayer()->FindOwnerDoc();
00881                     ERROR2IF(pDoc == NULL,TRUE,"Can't find owner doc for layer");
00882                     ERROR2IF(!IS_A(pDoc,Document),TRUE,"Owner doc is not a Document");
00883 
00884                     Layer* pLayer = GetDisplayedLayer();
00885                     ERROR2IF(pLayer == NULL,TRUE,"GetDisplayedLayer() returned NULL");
00886 
00887                     // Find out the state of the layer's flags
00888                     BOOL ActiveAndVisEd = (pLayer->IsActive() && Layer::ActiveLayerVisibleAndEditable);
00889 //                  BOOL Visible        = pLayer->GetVisibleFlagState();
00890 //                  BOOL Locked         = pLayer->GetLockedFlagState();
00891                     BOOL Guide          = pLayer->IsGuide();
00892                     BOOL PageBackground = pLayer->IsPageBackground();
00893 
00894 
00895                     CalculateButtonRects(MiscInfo, &MyRect, &VisibleBtn, &LockedBtn, &SnapBtn);
00896 
00897                     // Ignore menu clicks on the Visible button
00898                     if (!Mouse->MenuClick && VisibleBtn.ContainsCoord(Mouse->Position))
00899                     {
00900                         // Only change the actual setting if the AllVisible flag is clear
00901                         // and it's not the active layer with the 'active layer is visible and edtable' pref on
00902                         if (Guide || (!pDoc->IsAllVisible() && !ActiveAndVisEd))
00903                         {
00904                             ChangeRangeState(this, LastClickedLayer, Mouse->Extend, 0, MiscInfo);
00905 //                          DoChangeState(LAYER_VISIBLE,!Visible);
00906 //                          ParentGallery->ForceRedrawOfArea(&VisibleBtn);
00907 
00908                             // Remember this as the "anchor" layer for extend-click setting of ranges
00909                             LastClickedLayer = this;
00910                         }
00911                         else
00912                         {
00913                             UINT32 IDS = _R(IDS_LAYER_NOCHANGE_VISIBLE);
00914 
00915                             if (ActiveAndVisEd)
00916                                 IDS = _R(IDS_LAYER_NOCHANGE_VISIBLE_ACTIVE);
00917 
00918                             String_256 msg(IDS);
00919                             GetApplication()->UpdateStatusBarText(&msg);
00920                             Beep();
00921                         }
00922 
00923                         break;
00924                     }
00925 
00926                     // Ignore menu clicks on the Locked button
00927                     if (!Mouse->MenuClick && LockedBtn.ContainsCoord(Mouse->Position))
00928                     {
00929                         // Only change the actual setting if the Multilayer flag is clear
00930                         // and it's not the active layer with the 'active layer is visible and editable' pref on
00931                         // Now disallow the user the edit the page background layer.
00932                         if (!PageBackground && !pDoc->IsMultilayer() && !ActiveAndVisEd)
00933                         {
00934                             ChangeRangeState(this, LastClickedLayer, Mouse->Extend, 1, MiscInfo);
00935 //                          DoChangeState(LAYER_LOCKED,!Locked);
00936 //                          ParentGallery->ForceRedrawOfArea(&LockedBtn);
00937 
00938                             // Remember this as the "anchor" layer for extend-click setting of ranges
00939                             LastClickedLayer = this;
00940                         }
00941                         else
00942                         {
00943                             UINT32 IDS = _R(IDS_LAYER_NOCHANGE_LOCKED);
00944 
00945                             if (PageBackground)
00946                                 IDS = _R(IDS_LAYER_NOCHANGE_BACKGROUND);
00947 
00948                             if (ActiveAndVisEd)
00949                                 IDS = _R(IDS_LAYER_NOCHANGE_LOCKED_ACTIVE);
00950 
00951                             String_256 msg(IDS);
00952                             GetApplication()->UpdateStatusBarText(&msg);
00953                             Beep();
00954                         }
00955 
00956                         break;
00957                     }
00958 
00959 #if DO_SNAP_BUTTON
00960                     // Ignore menu clicks on the Snap button
00961                     if (!Mouse->MenuClick && SnapBtn.ContainsCoord(Mouse->Position))
00962                     {
00963                         // Only change the actual setting if the AllVisible flag is clear
00964                         // and it's not the active layer with the 'active layer is visible and edtable' pref on
00965                         
00966                         // **** MARKN NEEDS TO FIX THIS ****
00967                         // Mark: This currently all sets the visible state of the layer.
00968                         if (!pDoc->IsAllVisible() && !ActiveAndVisEd)
00969                         {
00970                             ChangeRangeState(this, LastClickedLayer, Mouse->Extend, 2, MiscInfo);
00971 //                          DoChangeState(LAYER_VISIBLE,!Visible);
00972 //                          ParentGallery->ForceRedrawOfArea(&VisibleBtn);
00973 
00974                             // Remember this as the "anchor" layer for extend-click setting of ranges
00975                             LastClickedLayer = this;
00976                         }
00977                         else
00978                         {
00979                             UINT32 IDS = _R(IDS_LAYER_NOCHANGE_VISIBLE);
00980 
00981                             if (ActiveAndVisEd)
00982                                 IDS = _R(IDS_LAYER_NOCHANGE_VISIBLE_ACTIVE);
00983 
00984                             String_256 msg(IDS);
00985                             GetApplication()->UpdateStatusBarText(&msg);
00986                             Beep();
00987                         }
00988 
00989                         break;
00990                     }
00991 #endif
00992 
00993                     // Only treat clicks as selection clicks if they are to the right of the tick buttons
00994                     // This is easy, as MyRect excludes the buttons
00995                     if (MyRect.ContainsCoord(Mouse->Position))
00996                     {
00997                         // In the layer gallery the selection can never be more than one item,
00998                         // so all clicks are treated like Select clicks.
00999                         if (!Flags.Selected)
01000                         {
01001                             // Make the layer we're displaying the active one
01002                             Layer* pLayer = GetDisplayedLayer();
01003                             LayerSGallery::MakeActiveLayer(pLayer);
01004 
01005                             // Now update the selection states...
01006                             ParentGallery->SelectItems(FALSE);  // Deselect everything else
01007 
01008                             // Repaint the list box now. This is because if there is a large
01009                             // distance between the old selection and the new one, we get a huge
01010                             // redraw cliprect, so get a (slow) complete redraw, instead of two
01011                             // small redraws. It is thus better to break the redraw into 2 steps
01012                             // so that we are more likely to get 2 fast redraws than one slow one.
01013                             //ParentGallery->PaintGadgetNow(_R(IDC_GALLERY_LISTBOX));
01014                             ParentGallery->PaintListNow();
01015                         
01016                             // And select myself, and the new active layer
01017                             SetSelected(TRUE);
01018 
01019                             // My selection state has changed, so I'd better redraw myself
01020                             ForceRedrawOfMyself();
01021 
01022                             // And inform the parent gallery that the selection has changed, so
01023                             // it can shade/unshade buttons as appropriate, etc
01024                             ParentGallery->SelectionHasChanged();
01025                         }
01026 
01027                         // Remember this as the "anchor" layer for extend-click setting of ranges
01028                         LastClickedLayer = this;
01029 
01030                         // Start a drag on the layer item
01031                         SGListDragInfo* pDragInfo = new SGListDragInfo(ParentGallery,this,Mouse,Mouse->MenuClick);
01032 
01033                         if (pDragInfo != NULL)
01034                             DragManagerOp::StartDrag(pDragInfo, GetParentGallery()->GetReadWriteWindowID());
01035                     }
01036 
01037                     return(TRUE);       // Claim this event - nobody else can own this click
01038                 }
01039             }
01040             break;
01041 
01042 
01043         default:
01044             // Let the base class handle all unknown/unwanted events
01045             return(SGDisplayItem::HandleEvent(EventType, EventInfo, MiscInfo));
01046     }
01047 
01048     // Default return value: We do not claim this event, so it will be passed on to others
01049     return(FALSE);
01050 }
01051 
01052 
01053 
01054 /***********************************************************************************************
01055 
01056 >   void SGDisplayLayer::DoChangeState(OpLayerGalReason Reason,BOOL NewState)
01057 
01058     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01059     Created:    8/8/94
01060     Inputs:     Reason  = reason code definiting what 'NewState' represents
01061                 NewState= boolean that determines the new state of the flag defined by 'Reason'
01062 
01063     Returns:    -
01064     Purpose:    Called when a flag changes for a layer gallery item
01065     
01066     Notes:      Does not redraw the layer in the display list
01067 
01068 ***********************************************************************************************/
01069 
01070 void SGDisplayLayer::DoChangeState(OpLayerGalReason Reason,BOOL NewState)
01071 {
01072     LayerSGallery* pGal = (LayerSGallery*)GetParentGallery();
01073     ERROR3IF(!IS_A(pGal,LayerSGallery),"Parent not a layer gallery");
01074     if (!IS_A(pGal,LayerSGallery)) return;
01075 
01076     Layer* pLayer = GetDisplayedLayer();
01077     pGal->DoChangeLayerState(pLayer,Reason,NewState);
01078 }
01079 
01080 
01081 
01082 /***********************************************************************************************
01083 
01084 >   void SGDisplayLayer::DoChangeLocked(BOOL Locked)
01085 
01086     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Jason, ripped from the LayerGallery, 1/2/95)
01087     Created:    8/8/94
01088     Inputs:     Locked - TRUE means make the displayed layer locked
01089                          FALSE means unlock
01090 
01091     Returns:    -
01092     Purpose:    Called when the Locked button is clicked in a layer gallery item.
01093                 Changes the lockedness of the displayed layer.
01094 
01095     Notes:      Does not redraw the layer in the display list
01096 
01097 ***********************************************************************************************/
01098 /*
01099 void SGDisplayLayer::DoChangeLocked(BOOL Locked)
01100 {
01101     Layer* pLayer = GetDisplayedLayer();
01102 
01103     BOOL PrevLocked = pLayer->IsLocked();
01104     pLayer->SetLocked(Locked);
01105     BOOL PostLocked = pLayer->IsLocked();
01106 
01107     if (PrevLocked != PostLocked)
01108         NodeRenderableInk::DeselectAllOnLayer(pLayer); 
01109 }
01110 
01111 */
01112 
01113 
01114 
01115 /***********************************************************************************************
01116 
01117 >   virtual void SGDisplayLayer::MoveAfter(SGDisplayNode *NodeToMove)
01118 
01119     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (from a Jason func)
01120     Created:    21/3/95
01121 
01122     Inputs:     NodeToMove - the node to move
01123 
01124     Purpose:    MOVES the given node (to a different position in the DisplayTree) as the
01125                 previous (left) sibling of this node. If the node is not linked into
01126                 a tree, it is effectively just inserted.
01127 
01128                 
01129 
01130     Errors:     ERROR3 and quiet exit if NodeToMove == NULL
01131 
01132     SeeAlso:    SuperGallery; SGDisplayNode::MoveAfter; SGDisplayNode::InsertAfter;
01133                 SGDisplayNode::AddItem
01134 
01135 ***********************************************************************************************/
01136 
01137 void SGDisplayLayer::MoveAfter(SGDisplayNode *NodeToMove)
01138 {
01139     ERROR3IF(NodeToMove == NULL, "Illegal NULL param");
01140     if (NodeToMove == this || NodeToMove == NULL)
01141         return;
01142 
01143     // Call base class to shift around the display item
01144     SGDisplayItem::MoveAfter(NodeToMove);
01145 
01146     // And move the associated layer in the docuemnt tree
01147     MoveLayer(NodeToMove,FALSE,FALSE);
01148 }
01149 
01150 
01151 
01152 /***********************************************************************************************
01153 
01154 >   virtual void SGDisplayLayer::MoveBefore(SGDisplayNode *NodeToMove)
01155 
01156     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (from a Jason func)
01157     Created:    21/3/95
01158 
01159     Inputs:     NodeToMove - the node to move
01160 
01161     Purpose:    MOVES the given node (to a different position in the DisplayTree) as the
01162                 previous (left) sibling of this node. If the node is not linked into
01163                 a tree, it is effectively just inserted.
01164 
01165     Notes:      This base class method simply delinks the item and relinks it elsewhere
01166                 in the display tree. However, derived classes will override this method
01167                 so that moving display items can have a further effect of also rearranging
01168                 the displayed "real" items. Before/After moving the real item, the
01169                 derived class can then call this baseclass method to complete the action.
01170         
01171                 Take care when moving items between groups (e.g. if an item is "moved"
01172                 from one docuemnt to another, it could be a bad thing, so be very
01173                 careful in derived classes to take appropriate action)
01174 
01175                 Any attempt to move an item before *itself* is queitly ignored
01176 
01177     Errors:     ERROR3 and quiet exit if NodeToMove == NULL
01178 
01179     SeeAlso:    SuperGallery; SGDisplayNode::MoveBefore; SGDisplayNode::InsertBefore;
01180                 SGDisplayNode::AddItem
01181 
01182 ***********************************************************************************************/
01183 
01184 void SGDisplayLayer::MoveBefore(SGDisplayNode *NodeToMove)
01185 {
01186     ERROR3IF(NodeToMove == NULL, "Illegal NULL param");
01187     if (NodeToMove == this || NodeToMove == NULL)
01188         return;
01189 
01190     // Call base class to shift around the display item
01191     SGDisplayItem::MoveBefore(NodeToMove);
01192 
01193     // And move the associated layer in the docuemnt tree
01194     MoveLayer(NodeToMove,TRUE,FALSE);
01195 }
01196 
01197 
01198 
01199 /***********************************************************************************************
01200 
01201 >   virtual void SGDisplayLayer::MoveLayer(SGDisplayNode *NodeToMove,BOOL Before,BOOL ToggleBackground)
01202 
01203     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01204     Created:    21/3/95
01205 
01206     Inputs:     NodeToMove  = the node to move (which specifies the layer to move)
01207                 Before      = if TRUE the layer is moved previous (before) this layer, otherwise
01208                                 the layer is moved next (after) this layer
01209                 ToggleBacground = TRUE if the background flag should be toggled when moved
01210 
01211     Purpose:    This moves the given layer either before or after this layer, in an undoable way
01212 
01213     Errors:     ERROR3 and quiet exit if NodeToMove == NULL
01214 
01215     SeeAlso:    SuperGallery; SGDisplayNode::MoveAfter; SGDisplayNode::InsertAfter; SGDisplayNode::AddItem
01216 
01217 ***********************************************************************************************/
01218 
01219 void SGDisplayLayer::MoveLayer(SGDisplayNode *NodeToMove,BOOL Before,BOOL ToggleBackground)
01220 {
01221 PORTNOTE("galleries", "disabled frame gallery")
01222 #ifndef EXCLUDE_FROM_XARALX
01223     ERROR3IF((!IS_A(NodeToMove,SGDisplayLayer) && !IS_A(NodeToMove,SGDisplayFrame)),"The node to move is not a SGDisplayLayer");
01224     if (!IS_A(NodeToMove,SGDisplayLayer) && !IS_A(NodeToMove,SGDisplayFrame))
01225         return;
01226 #else
01227     ERROR3IF((!IS_A(NodeToMove,SGDisplayLayer)),"The node to move is not a SGDisplayLayer");
01228     if (!IS_A(NodeToMove,SGDisplayLayer))
01229         return;
01230 #endif
01231 
01232     Layer* pLayerToMove = ((SGDisplayLayer*)NodeToMove)->GetDisplayedLayer();
01233     Layer* pThisLayer   = GetDisplayedLayer();
01234 
01235     Spread* pSpread = pLayerToMove->FindParentSpread();
01236     ERROR3IF(pSpread == NULL,"Parent spread is NULL");
01237     if (pSpread == NULL)
01238         return; 
01239     
01240     OpLayerGalReason Reason;
01241 
01242     if (pLayerToMove == pThisLayer)
01243     {
01244         // if the context node and the layer to move are the same, and we don't have to toggle
01245         // the background flag, just return (give errors in debug mode)
01246         ERROR3IF(!ToggleBackground,"Not moving the layer OR toggling the background flag, so why did you call?");
01247         if (!ToggleBackground)
01248             return;
01249 
01250         Reason = LAYER_TOGGLEBACKGROUND;
01251     }
01252     else
01253         Reason = LAYER_MOVE;
01254     
01255 
01256     OpLayerGalParam Param(Reason,pSpread);
01257 
01258     Param.pLayer            = pLayerToMove;
01259     Param.pContextNode      = pThisLayer;
01260     Param.MoveRedraw        = TRUE;
01261     Param.ToggleBackground  = ToggleBackground;
01262     Param.pLayerSGal        = (LayerSGallery*)GetParentGallery();
01263 
01264     if (Before)
01265         Param.AttDir = NEXT;    // next means insert-before-this
01266     else
01267         Param.AttDir = PREV;    // prev means insert-after-this
01268 
01269     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
01270     if (pOpDesc != NULL)
01271         pOpDesc->Invoke((OpParam*)&Param);
01272     else
01273     {
01274         ENSURE(FALSE,"Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
01275     }
01276 }
01277 
01278 #endif // EXCLUDE_GALS
01279 
01280 /********************************************************************************************
01281 
01282 >   LayerSGallery::LayerSGallery()
01283                                                  
01284     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01285     Created:    27/1/95 (base generated in sgbase.cpp)
01286     Purpose:    LayerSGallery default constructor
01287 
01288 ********************************************************************************************/
01289 
01290 LayerSGallery::LayerSGallery()
01291 {
01292 #ifndef EXCLUDE_GALS
01293     DlgResID = _R(IDD_LAYERSGALLERY);
01294     pSpread = NULL;
01295     pDoc = NULL;
01296     DisplayForeground = NULL;   // Group of foreground layers
01297     DisplayBackground = NULL;   // Group of background layers
01298 
01299     OldGuideLayerState = -1;
01300     NewGuideLayerState = -1;
01301     m_NewDocBorn = FALSE;
01302 #endif
01303 } 
01304 
01305 
01306 
01307 /********************************************************************************************
01308 
01309 >   LayerSGallery::~LayerSGallery()
01310 
01311     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01312     Created:    27/1/95 (base generated in sgbase.cpp)
01313     Purpose:    LayerSGallery destructor.
01314 
01315 ********************************************************************************************/
01316 
01317 LayerSGallery::~LayerSGallery()
01318 {
01319 }
01320 
01321 #ifndef EXCLUDE_GALS
01322 
01323 /********************************************************************************************
01324 
01325 >   void LayerSGallery::CreateNewSubtree(Document *ParentDoc, SGDisplayGroup *ExistingGroup)
01326 
01327     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01328     Created:    27/1/95 (base generated in sgbase.cpp)
01329 
01330     Inputs:     ParentDoc - The document to create a display subtree for
01331                 ExistingGroup - NULL (creates a new group for this document), or
01332                 a pointer to the existing group-node for this document (in which case
01333                 it clears all displayitems from the group and rebuilds it in place - this
01334                 stops the display group moving around the tree at random!)
01335 
01336     Purpose:    Internal call. This takes the Layer list of the given document and 
01337                 creates a DisplayTree subtree from it. This subtree is then added to
01338                 the DisplayTree. Note that this does not force a redraw of the list - 
01339                 after making this call, you should also call ForceRedrawOfList
01340 
01341     Notes:      Passing in a NULL parent document pointer results in an ERROR3 -
01342                 the function returns without doing anything in retail builds
01343 
01344     SeeAlso:    SuperGallery::ForceRedrawOfList
01345 
01346 ********************************************************************************************/
01347 
01348 void LayerSGallery::CreateNewSubtree(Document *ParentDoc, SGDisplayGroup *ExistingGroup)
01349 {
01350     if (DisplayTree == NULL)
01351         return;
01352 
01353 TRACEUSER( "Neville", _T("LayerSGallery::CreateNewSubtree Just about to DestroySubtree\n"));
01354     // The layer gallery only ever shows one document, so destroy the entire tree
01355     // and start again from scratch (note that this doesn't destroy the root node)
01356     DisplayTree->DestroySubtree();
01357 
01358     // All groups will be destroyed by DestroySubtree(), so we'd better forget them
01359     DisplayForeground = NULL;
01360     DisplayBackground = NULL;
01361     
01362 TRACEUSER( "Neville", _T("LayerSGallery::CreateNewSubtree completed DestroySubtree\n"));
01363 
01364     if (ParentDoc == NULL)
01365         return;
01366 
01367     SGDisplayLayer  *DisplayLayer = NULL;
01368 
01369     EnsureActiveLayerIntegrity();
01370 
01371     // Create the foreground layer group
01372     DisplayForeground = new SGLayerGroup(this, ParentDoc,NULL,TRUE);    // Create new Group
01373     if (DisplayForeground == NULL)                                      // Total failure - abort
01374         return;
01375     DisplayTree->AddItem(DisplayForeground);                            // Add new group to tree
01376 
01377     // Create the background layer group
01378     DisplayBackground = new SGLayerGroup(this, ParentDoc,NULL,FALSE);   // Create new Group
01379     if (DisplayBackground == NULL)                                      // Total failure - abort
01380         return;
01381     DisplayTree->AddItem(DisplayBackground);                            // Add new group to tree
01382     
01383 
01384     Spread* pSelSpread = GetSelectedSpread();
01385     ERROR3IF(pSelSpread == NULL,"No selected spread in LayerSGallery");
01386     if (pSelSpread == NULL) return;
01387 
01388     Layer* pLayer       = pSelSpread->FindLastLayer();
01389     Layer* pActiveLayer = NULL;
01390     Layer* pGuideLayer  = NULL;
01391 
01392     while (pLayer != NULL)
01393     {
01394         // Keep a ptr to the guide layer, if there is one
01395         if (pLayer->IsGuide())
01396             pGuideLayer = pLayer;
01397 
01398         DisplayLayer = new SGDisplayLayer(pLayer);
01399 
01400         if (DisplayLayer != NULL)
01401         {
01402             if (pLayer->IsBackground())
01403                 DisplayBackground->AddItem(DisplayLayer);
01404             else
01405                 DisplayForeground->AddItem(DisplayLayer);
01406         }
01407 
01408         if (pLayer->IsActive())
01409         {
01410             ERROR3IF(pActiveLayer != NULL,
01411                         "Found more than one active layer in the selected spread");
01412             pActiveLayer = pLayer;
01413 
01414             DisplayLayer->SetSelected(TRUE);    // Make the active layer selected
01415         }
01416 
01417         pLayer = pLayer->FindPrevLayer();
01418     }
01419 
01420     // The new state of the Guide Layer is now the old state
01421     OldGuideLayerState = NewGuideLayerState;
01422 
01423     if (pGuideLayer == NULL)
01424         NewGuideLayerState = -1;                        // If there's no guide layer, set new state to be -1
01425     else
01426         NewGuideLayerState = pGuideLayer->IsVisible();  // New state is based on the guide layer's visibility
01427 
01428     if (IsVisible())
01429     {
01430         SetBoolGadgetSelected(_R(IDC_BTN_MULTILAYER),!(ParentDoc->IsMultilayer() == 0));
01431         SetBoolGadgetSelected(_R(IDC_BTN_ALLVISIBLE),!(ParentDoc->IsAllVisible() == 0));
01432     }
01433 
01434     TRACEUSER( "Neville", _T("LayerSGallery::CreateNewSubtree exit\n"));
01435 }
01436 
01437 
01438 
01439 /********************************************************************************************
01440 
01441 >   BOOL LayerSGallery::PreCreate(void)
01442 
01443     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Jason)
01444     Created:    2/8/94
01445     Returns:    TRUE if it is successful; FALSE to abort creation of the window
01446 
01447     Purpose:    Layer SuperGallery PreCreate handler
01448 
01449     Notes:      This method is called whenever the gallery window is about to be
01450                 created.
01451 
01452 ********************************************************************************************/
01453 
01454 BOOL LayerSGallery::PreCreate(void)
01455 {
01456     NewSelectedSpread();        // Cache the selected spread info
01457 
01458     // If there isn't already one, create a DisplayTree
01459     if (DisplayTree == NULL)
01460     {
01461         DisplayTree = new SGDisplayRootScroll(this);    // New root node, with a scrollbar
01462         if (DisplayTree == NULL)
01463             return(FALSE);
01464     }
01465 
01466     // The layer sgallery is a splitter, in that it only ever shows information for the
01467     // selected document, so there is no point trying to call this method for loads of
01468     // documents as the other galleries do.
01469     CreateNewSubtree(Document::GetSelected());
01470 
01471     return(TRUE);
01472 }
01473 
01474 
01475 
01476 /********************************************************************************************
01477 
01478 >   BOOL LayerSGallery::PostCreate(void)
01479 
01480     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01481     Created:    27/1/95 (base generated in sgbase.cpp)
01482 
01483     Returns:    TRUE if the Gallery initialised successfully
01484                 FALSE if it should not be opened due to a failure to initialise
01485 
01486     Purpose:    The LayerSGallery PostCreate handler. This overrides the base class
01487                 PostCreate function. It is called at the very end of the
01488                 SuperGallery::Create method, after the window has been created and opened.
01489 
01490 ********************************************************************************************/
01491 
01492 BOOL LayerSGallery::PostCreate(void)
01493 {
01494     Document *ParentDoc = Document::GetSelected();
01495     if (ParentDoc != NULL)
01496     {
01497         SetBoolGadgetSelected(_R(IDC_BTN_MULTILAYER),!(ParentDoc->IsMultilayer() == 0));
01498         SetBoolGadgetSelected(_R(IDC_BTN_ALLVISIBLE),!(ParentDoc->IsAllVisible() == 0));
01499     }
01500 
01501     EnableGadget(_R(IDC_GALLERY_COPY),ParentDoc != NULL && !IsSelectedItemGuideLayer());
01502 
01503     return(TRUE);
01504 }
01505 
01506 
01507 
01508 /********************************************************************************************
01509 
01510 >   virtual BOOL LayerSGallery::ApplyAction(SGActionType Action)
01511 
01512     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01513     Created:    27/1/95 (base generated in sgbase.cpp)
01514 
01515     Inputs:     Action - Indicates what action to apply
01516 
01517     Returns:    TRUE to indicate successful handling of the action, or
01518                 FALSE to indicate failure
01519 
01520     Purpose:    Applies certain conventional gallery actions (usually associated with
01521                 gallery buttons, for new, edit, delete, etc)
01522 
01523     SeeAlso:    SGActionType
01524 
01525 ********************************************************************************************/
01526 
01527 BOOL LayerSGallery::ApplyAction(SGActionType Action)
01528 {
01529     // No display tree? Better forget about it then!
01530     if (DisplayTree == NULL)
01531         return(FALSE);
01532 
01533     // Determine useful info - this is usually needed for most actions, so always get it
01534     Document        *SelectedDoc = Document::GetSelected();
01535     SGDisplayGroup  *DocumentGroup = DisplayTree->FindSubtree(this, SelectedDoc, NULL);
01536     SGDisplayLayer  *FirstSelected = NULL;
01537     
01538     if (DocumentGroup != NULL)
01539         FirstSelected = (SGDisplayLayer *) DocumentGroup->FindNextSelectedItem(NULL);
01540 
01541     // Now, process the action  TO DO! - see Colour gallery for examples
01542     switch(Action)
01543     {
01544         case SGACTION_CREATE:
01545             DoCreateNewItem();
01546             break;
01547 
01548         case SGACTION_EDIT:
01549             DoChangeName();
01550             break;
01551 
01552         case SGACTION_DELETE:
01553             if (PrepareToDelete())
01554                 DoDeleteSelection();
01555             break;
01556 
01557 //      case SGACTION_APPLY:
01558 //      case SGACTION_REDEFINE:
01559 //      case SGACTION_DISPLAYMODECHANGED:
01560 //          These operations are not provided by the layer gallery
01561 //          break;
01562 
01563         default:
01564             return(SuperGallery::ApplyAction(Action));
01565     }
01566 
01567     return(TRUE);
01568 }
01569 
01570 
01571 
01572 /********************************************************************************************
01573 
01574 >   virtual MsgResult LayerSGallery::Message(Msg* Message)
01575 
01576     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
01577     Created:    27/1/95 (base generated in sgbase.cpp)
01578     Inputs:     Message - The message to handle
01579 
01580     Purpose:    A standard message handler, really.
01581 
01582     Notes:      Any messages that this does not handle must be passed down to the
01583                 SuperGallery base class message handler.
01584 
01585                 NOTE WELL that the SuperGallery base class handler does some funky things
01586                 for us - see SuperGallery::Message - such as deleting our display subtree
01587                 for any document which dies (which, uncannily, would explain why they go
01588                 away like that when you close documents ;-), and shading the gallery when
01589                 there are no documents present. [To override this behaviour in these cases,
01590                 you should respond to the message, and return OK rather than calling the
01591                 base class message handler]
01592 
01593     SeeAlso:    SuperGallery::Message
01594 
01595 ********************************************************************************************/
01596 
01597 MsgResult LayerSGallery::Message(Msg* Message)
01598 {
01599     if (IS_OUR_DIALOG_MSG(Message))
01600     {
01601         DialogMsg* Msg = (DialogMsg*)Message;
01602 
01603         switch (Msg->DlgMsg)
01604         {
01605             case DIM_CREATE:
01606                 SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYLAYERGALLERY), TRUE);
01607                 break;
01608 
01609             case DIM_CANCEL:
01610                 SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYLAYERGALLERY), FALSE);
01611                 break;
01612 
01613             default:
01614                 break;
01615         }
01616     }
01617 
01618 
01619     // If we have no displaytree, then we have not been shown, or something terrible has
01620     // happened, so we don't bother handling any of these messages.
01621     if (DisplayTree == NULL)
01622         return(SuperGallery::Message(Message));
01623 
01624 
01625     if (IS_OUR_DIALOG_MSG(Message))
01626     {
01627         DialogMsg* Msg = (DialogMsg*)Message;
01628         INT32 state;
01629 
01630         switch (Msg->DlgMsg)
01631         {
01632             case DIM_LFT_BN_CLICKED:
01633             {
01634                 //TRACE( _T("Gadget %d clicked\n"),Msg->GadgetID);
01635                 if (FALSE) {}
01636                 else if (Msg->GadgetID ==  _R(IDC_BTN_MULTILAYER))
01637                 {
01638                     state = GetLongGadgetValue(_R(IDC_BTN_MULTILAYER),0,1);
01639                     DoChangeLayerState(NULL,LAYER_MULTILAYER,state);
01640                     //DoChangeMultilayer(state);
01641                     //ForceRedrawOfList();
01642                 }
01643                 else if (Msg->GadgetID == _R(IDC_BTN_ALLVISIBLE))
01644                 {
01645                     state = GetLongGadgetValue(_R(IDC_BTN_ALLVISIBLE),0,1);
01646                     DoChangeLayerState(NULL,LAYER_ALLVISIBLE,state);
01647                     //DoChangeAllVisible(state);
01648                     //ForceRedrawOfList();
01649                 }
01650                 else if (Msg->GadgetID == _R(IDC_GALLERY_UPONE))
01651                 {
01652                     DoMoveLayer(MOVELAYER_UPONE);
01653                 }
01654                 else if (Msg->GadgetID == _R(IDC_GALLERY_DOWNONE))
01655                 {
01656                     DoMoveLayer(MOVELAYER_DOWNONE);
01657                 }
01658                 else if (Msg->GadgetID ==  _R(IDC_GALLERY_NAME))
01659                 {
01660                     //DoChangeName();
01661                     //break;
01662                 }
01663                 else if (Msg->GadgetID == _R(IDC_GALLERY_PROPERTIES))
01664                 {
01665                     DoLayerProperties();
01666                 }
01667                 else if (Msg->GadgetID == _R(IDC_GALLERY_COPY))
01668                 {
01669                     DoCopyLayer();
01670                 }
01671                 else if (Msg->GadgetID == _R(IDC_LAYER_MOVE_TO_ACTIVE))
01672                 {
01673                     DoMoveSelectionToActiveLayer();
01674                 }                                           
01675 #ifndef WEBSTER
01676                 else if (Msg->GadgetID == _R(IDC_GALLERY_HELP))
01677                 {
01678                     HelpUserTopic(_R(IDS_HELPPATH_Gallery_Layer));
01679                 }
01680 #endif                  
01681             }
01682             default:
01683                 break;
01684         }
01685     }
01686     else if (MESSAGE_IS_A(Message, OpMsg))
01687     {
01688         switch (((OpMsg*)Message)->MsgType)
01689         {
01690             case OpMsg::AFTER_UNDO:
01691             case OpMsg::AFTER_REDO:
01692                 EnsureSelSpreadSelectionIntegrity();
01693                 break;
01694             default:
01695                 break;
01696         }
01697     }
01698     else if (MESSAGE_IS_A(Message, SpreadMsg))
01699     {
01700         SpreadMsg*  pSpreadMsg = (SpreadMsg*) Message;
01701 
01702         switch (pSpreadMsg->Reason)
01703         {
01704             case SpreadMsg::SELCHANGED:
01705                 NewSelectedSpread(pSpreadMsg->pNewSpread);  // gets selected doc too
01706                 if (pDoc != NULL && IsVisible())
01707                 {
01708 TRACEUSER( "Neville", _T("SpreadMsg::SELCHANGED CreateNewSubtree\n"));
01709                     CreateNewSubtree(pDoc);
01710                     ForceRedrawOfList();
01711                 }
01712                 break;
01713 
01714 
01715             case SpreadMsg::LAYERCHANGES:
01716                 if (IsVisible())
01717                 {
01718                     if (pSpreadMsg->pNewSpread == pSpread)
01719                     {
01720                         if (pSpread->FindFirstLayer() != NULL)
01721                         {
01722                             EnsureActiveLayerIntegrity();
01723                             if (pDoc != NULL && IsVisible())
01724                             {
01725 TRACEUSER( "Neville", _T("SpreadMsg::LAYERCHANGES CreateNewSubtree\n"));
01726                                 CreateNewSubtree(pDoc);
01727                                 ForceRedrawOfList();
01728                             }
01729                         }
01730                     }
01731                 }
01732                 else
01733                 {
01734                     if (pSpreadMsg->pNewSpread->FindFirstLayer() != NULL)
01735                     {
01736                         pSpread = pSpreadMsg->pNewSpread;
01737                         EnsureActiveLayerIntegrity();
01738                     }
01739                 }
01740                 break;
01741             default:
01742                 break;
01743         }
01744     }
01745     else if (MESSAGE_IS_A(Message, DocChangingMsg))
01746     {
01747         DocChangingMsg *Msg = (DocChangingMsg *) Message;
01748         switch (Msg->State)
01749         {
01750                 case DocChangingMsg::TITLECHANGED:
01751 // Showstopper removed, Jason, 28/3/96
01752 // When the doc title changes, we simply need to redraw to update the group titles.
01753 // Calling CreateNewSubtree will destroy the existing tree - this is really really bad
01754 // when the document title changed as a result of us (e.g.) locking a layer, because the
01755 // message broadcats hits us while we're still in the middle of traversing the tree,
01756 // we then delete the tree out from under ourselves, and are then in a highly dodgy state!
01757 //              CreateNewSubtree(Msg->pChangingDoc);
01758                 ForceRedrawOfList();
01759                 break;
01760         
01761             // This message is sent when a new or just opened document is stable.
01762             case DocChangingMsg::SELCHANGED:
01763             {
01764                 if (Msg->pNewDoc == NULL)
01765                 {
01766                     // No documents around any more, so we must wipe the display tree
01767                     // The base class will shade the gallery for us.
01768                     TRACEUSER( "Neville", _T("DocChangingMsg::SELCHANGED CreateNewSubtree\n"));
01769                     CreateNewSubtree(NULL);
01770                     ForceRedrawOfList();
01771                 }
01772                 else 
01773                 {
01774             #ifdef WEBSTER
01775                     // There is an active document, so ensure the gallery is unshaded
01776                     ShadeGallery(FALSE);
01777             #else
01778                     //Do not process the message if it has been sent due to the creation of a new document.
01779                     if ( !GetNewDocBorn() )
01780                     {
01781                         // flag variables.
01782                         BOOL LayerMode = FALSE; 
01783                     
01784                         // Get the changing document pointer.
01785                         Document* pDoc = Msg->pNewDoc;
01786 
01787                         if(pDoc)
01788                         {
01789                             // Determine the document mode.
01790                             LayerMode = IsLayerMode(pDoc);
01791 
01792                             // If we are no longer in Layer mode then
01793                             // close the Layer gallery and open the Frame gallery.
01794                             if( !LayerMode && IsVisible() )
01795                             {
01796                                 // Close the layer gallery.
01797                                 if( CloseLayerGallery() )
01798                                 {
01799                                     // Open the frame gallery.
01800                                     OpenFrameGallery();
01801                                 }
01802                             }
01803                         }
01804                     }
01805                     
01806                     // If the gallery is visible, then ensure the gallery is unshaded.
01807                     if(IsVisible())
01808                     {
01809                         // There is an active document, so ensure the gallery is unshaded
01810                         ShadeGallery(FALSE);
01811                     }
01812                     
01813                 #endif
01814                 }
01815                 break;
01816             }
01817         #ifndef WEBSTER
01818             case DocChangingMsg::BORN:
01819             {
01820                 // When a new document is created, a SELCHANGED
01821                 // message is broadcasted, for Camelot2 frame/layer integration
01822                 // we do not wish to process the message. 
01823                 // We therefore set this flag to notify us when a new document
01824                 // is born.
01825 
01826                 // Ensure we are no longer in Frame mode and the frame gallery is open.
01827                 if( IsVisible() )
01828                 {
01829                     // Set the flag to true.
01830                     // This is set to false in BORNANDSTABLE. 
01831                     SetNewDocBorn(TRUE);
01832                 }
01833                 break;
01834             }
01835 
01836             case DocChangingMsg::BORNANDSTABLE:
01837             {
01838                 // flag variables.
01839                 BOOL LayerMode = FALSE; 
01840 //              BOOL GalleryClosed = FALSE;
01841 
01842                 // Get the changing document pointer.
01843                 Document* pChangingDoc = Msg->pChangingDoc;
01844 
01845                 if(pChangingDoc)
01846                 {
01847                     // Determine the document mode.
01848                     LayerMode = IsLayerMode(pChangingDoc);
01849 
01850                     // If we are no longer in Layer mode then
01851                     // close the Layer gallery and open the Frame gallery.
01852                     if( !LayerMode && IsVisible() )
01853                     {
01854                         // Close the layer gallery.
01855                         if(CloseLayerGallery())
01856                         {
01857                             // Open the frame gallery.
01858                             OpenFrameGallery();
01859 
01860                             // Now we have processed this message, it is safe to process SELCHANGED messages.
01861                             SetNewDocBorn(FALSE);
01862                         }
01863                     }
01864                 }
01865                 break;
01866             }
01867 
01868             case DocChangingMsg::KILLED:
01869             case DocChangingMsg::ABOUTTODIE:
01870             {
01871                 // The doc. is about to die, therefore, set this falg to false.
01872                 SetNewDocBorn(FALSE);
01873             break;
01874             }
01875 
01876         #endif
01877         }
01878     }
01879 
01880 
01881     else if (MESSAGE_IS_A(Message, DocViewMsg))
01882     {
01883         DocViewMsg *Msg = (DocViewMsg *) Message;
01884         switch (Msg->State)
01885         {
01886             case DocViewMsg::SELABOUTTOCHANGE: 
01887                 OldGuideLayerState = GetGuideLayerState(Msg->pNewDocView);
01888                 break;
01889 
01890             case DocViewMsg::SELCHANGED: 
01891             {
01892                 if (IsVisible())
01893                 {
01894                     NewGuideLayerState = GetGuideLayerState(Msg->pNewDocView);
01895                     if (OldGuideLayerState != NewGuideLayerState)
01896                     {
01897                         TRACEUSER( "Neville", _T("DocViewMsg::SELCHANGED CreateNewSubtree\n"));
01898                         CreateNewSubtree(Msg->pNewDocView ? Msg->pNewDocView->GetDoc() : NULL);
01899                         ForceRedrawOfList();
01900                     }
01901                 }
01902             }
01903             break;
01904             default:
01905                 break;
01906         }
01907     }
01908     else if (MESSAGE_IS_A(Message, LayerMsg))
01909     {
01910         LayerMsg *pMsg = (LayerMsg *) Message;
01911 
01912         switch ( pMsg->Reason )
01913         {
01914             // The active layer has changed.
01915             case LayerMsg::ACTIVE_LAYER_CHANGED:
01916             {
01917                 EnableGadget(_R(IDC_GALLERY_COPY),pMsg->pNewLayer != NULL && !pMsg->pNewLayer->IsGuide()); 
01918             }
01919             break;
01920 
01921             // The visibility of a layer has changed, probably by an external source
01922             // so update the display
01923             case LayerMsg::LAYER_VISIBILITY_CHANGED:
01924             {
01925                 ForceRedrawOfList(); 
01926             }
01927             break;
01928 
01929             // The active layer has been changed externally to the gallery.
01930             case LayerMsg::UPDATE_ACTIVE_LAYER:
01931             {
01932                 // We must now check whether the selected layer has been changed externally
01933                 // to us. May happen if an animated GIF is being loaded onto layers
01934                 SGDisplayLayer *pDisplayItem = NULL;
01935                 if (DisplayForeground != NULL)
01936                     pDisplayItem = GetSelectedLayerGalItem();
01937                 if (pDisplayItem != NULL)
01938                 {
01939                     if (pDisplayItem->GetDisplayedLayer() != pMsg->pNewLayer)
01940                     {
01941                         Layer* pNewActiveLayer = pMsg->pNewLayer;
01942                         // Search for the new display item to match this new active layer 
01943                         SGDisplayLayer *pWantedDispLayer = NULL;
01944                         SGDisplayLayer *pDispLayer = ((SGDisplayLayer *) DisplayForeground->GetChild());
01945                         while (pDispLayer != NULL)                      
01946                         {
01947                             if (pDispLayer->GetDisplayedLayer() == pNewActiveLayer)
01948                                 pWantedDispLayer = pDispLayer;
01949                             pDispLayer = (SGDisplayLayer *) pDispLayer->GetNext();
01950                         }
01951                         
01952                         // If we found the required display item then go and select it
01953                         if (pWantedDispLayer)
01954                         {
01955                             // Now update the selection states...
01956                             SelectItems(FALSE); // Deselect everything else
01957                             // Something has changed so we must go and select this new item
01958                             pWantedDispLayer->SetSelected(TRUE);
01959                         }
01960                     }
01961                 }
01962             }
01963             break;
01964             default:
01965                 break;
01966         }
01967     }
01968 
01969     return(SuperGallery::Message(Message));
01970 }    
01971 
01972 /********************************************************************************************
01973 
01974 >   INT32 LayerSGallery::GetGuideLayerState(DocView* pDocView)
01975 
01976     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
01977     Created:    28/9/95
01978     Inputs:     pDocView = ptr to docview (This holds visibility info for guide layers)
01979     Outputs:    -
01980     Returns:     0 = Guide layer is invisible
01981                  1 = Guide layer is visible
01982                 -1 = Guide layer doesn't exist
01983 
01984     Purpose:    This returns the current state of the guide layer.
01985                 It is used to determine whether we need to recreate and redraw the layer gallery
01986                 when the selected view changes.
01987 
01988 ********************************************************************************************/
01989 
01990 INT32 LayerSGallery::GetGuideLayerState(DocView* pDocView)
01991 {
01992     Spread* pSelSpread = GetSelectedSpread();
01993 
01994     if (pSelSpread != NULL)
01995     {
01996         Layer* pLayer = pSelSpread->FindFirstGuideLayer();
01997         if (pLayer != NULL)
01998             return (pLayer->IsVisible(pDocView));
01999     }
02000 
02001     return -1;
02002 }
02003 
02004     
02005 
02006 /********************************************************************************************
02007 
02008 >   void LayerSGallery::NewSelectedSpread(Spread* pNewSelSpread = NULL)
02009 
02010     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02011     Created:    4/8/94
02012     Inputs:     pNewSelSpread = ptr to the spread the layer gal should take as the
02013                 selected one; NULL will read the global Selected spread value.
02014     Outputs:    -
02015     Returns:    -
02016     Purpose:    Central place for setting the layer gal's selected spread.
02017                 Also takes a copy of the selected document
02018 
02019 ********************************************************************************************/
02020 
02021 void LayerSGallery::NewSelectedSpread(Spread* pNewSelSpread)
02022 {
02023     if (pNewSelSpread == NULL)
02024         pSpread = Document::GetSelectedSpread();
02025     else
02026         pSpread = pNewSelSpread;
02027     
02028     pDoc = Document::GetSelected();
02029 }
02030 
02031 
02032 
02033 
02034 /***********************************************************************************************
02035 
02036 >   void LayerSGallery::EnsureSelSpreadSelectionIntegrity()
02037 
02038     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02039     Created:    16/8/94
02040     Inputs:     -
02041     Outputs:    -
02042     Returns:    -
02043     Purpose:    This makes sure that all the invisible and/or locked layers in the spread
02044                 have no selection. It calls NodeRenderableInk::DeselectAllOnLayer() on each 
02045                 layer that should NOT have a selection, just in case.
02046                 Currently only called after an undo or redo op, because it could be quite slow
02047 
02048 ***********************************************************************************************/
02049 
02050 void LayerSGallery::EnsureSelSpreadSelectionIntegrity()
02051 {
02052     if (pSpread == NULL) return;
02053 
02054     // Get the first layer in the spread
02055     Layer* pLayer = pSpread->FindFirstLayer();  
02056 
02057     while (pLayer != NULL)
02058     {
02059         // If the layer is not visible OR the layer is locked, make sure there is no selection
02060         if (!pLayer->IsVisible() || pLayer->IsLocked())
02061             NodeRenderableInk::DeselectAllOnLayer(pLayer);
02062 
02063         pLayer = pLayer->FindNextLayer();
02064     }
02065 }
02066 
02067 #endif // EXCLUDE_GALS
02068 
02069 /***********************************************************************************************
02070 
02071 >   static void LayerSGallery::ForceRedrawLayer(Document* pDoc,Layer* pLayer)
02072 
02073     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02074     Created:    12/8/94
02075     Inputs:     pDoc   = ptr that contains this layer
02076                 pLayer = ptr to the layer you want to redraw
02077     Outputs:    -
02078     Returns:    -
02079     Purpose:    Does a ForceRedraw on the layer in the given doc
02080 
02081 ***********************************************************************************************/
02082 
02083 void LayerSGallery::ForceRedrawLayer(Document* pDoc,Layer* pLayer)
02084 {
02085     Spread* pSpread = pLayer->FindParentSpread();
02086 
02087     if (pSpread != NULL)
02088     {
02089         DocRect rect = pLayer->GetUnionBlobBoundingRect();
02090         pDoc->ForceRedraw(pSpread, rect, FALSE, pLayer);            // Don't allow caches to retain backgrounds
02091 
02092         if (pLayer->IsGuide())
02093         {
02094             Node* pNode = pLayer->FindFirstChild(CC_RUNTIME_CLASS(NodeGuideline));
02095             while (pNode != NULL)
02096             {
02097                 rect = ((NodeGuideline*)pNode)->GetRenderRect();
02098                 pDoc->ForceRedraw(pSpread, rect, FALSE, pLayer);    // Don't allow caches to retain backgrounds
02099                 pNode = pNode->FindNext(CC_RUNTIME_CLASS(NodeGuideline));
02100             }
02101         }
02102     }
02103 }
02104 
02105 
02106 
02107 /***********************************************************************************************
02108 
02109 >   static void LayerSGallery::SetActive(Document* pDoc,Layer* pLayer,BOOL state)
02110 
02111     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02112     Created:    12/8/94
02113     Inputs:     pDoc   = ptr to doc containing layer
02114                 pLayer = ptr that contains this layer
02115                 state  = TRUE means make active, FALSE means make inactive
02116     Outputs:    -
02117     Returns:    -
02118     Purpose:    Calls pLayer->SetActive(state), redrawing and changing the layer's selection
02119                 if necessary.
02120                 DON'T CALL THIS FUNC!! USE MakeActiveLayer() INSTEAD!!!!
02121 
02122 ***********************************************************************************************/
02123 
02124 void LayerSGallery::SetActive(Document* pDoc,Layer* pLayer,BOOL state)
02125 {
02126     // This flag is TRUE if the selection on the layer should be cleared
02127     BOOL ClearSelection = FALSE;
02128 
02129     // get state before active change
02130     BOOL PrevVisibleState = pLayer->IsVisible();
02131     BOOL PrevLockedState  = pLayer->IsLocked();
02132 
02133     // Change active state
02134     pLayer->SetActive(state);
02135 
02136     // get state after active change
02137     BOOL PostVisibleState = pLayer->IsVisible();
02138     BOOL PostLockedState  = pLayer->IsLocked();
02139 
02140     if (PrevVisibleState != PostVisibleState)
02141     {
02142         // If the visible state has changed, redraw the layer
02143         LayerSGallery::ForceRedrawLayer(pDoc,pLayer);
02144 
02145         // If it has just become invisible, clear the selection
02146         ClearSelection = (ClearSelection || !PostVisibleState);
02147     }
02148 
02149     // if it has just become locked, clear the selection
02150     if (PrevLockedState != PostLockedState)
02151         ClearSelection = (ClearSelection || PostLockedState);
02152 
02153     // Clear the selection if needed
02154     if (ClearSelection)
02155         NodeRenderableInk::DeselectAllOnLayer(pLayer); 
02156 }
02157 
02158 
02159 
02160 /***********************************************************************************************
02161 
02162 >   static void LayerSGallery::MakeActiveLayer(Layer* pNewActiveLayer)
02163 
02164     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02165     Created:    9/8/94
02166     Inputs:     pNewActiveLayer = ptr to the layer you want to be active
02167     Outputs:    -
02168     Returns:    -
02169     Purpose:    Makes the layer active.
02170                 Firstly it will inactivate any other active layers, forcing it to redraw if necessary
02171                 Then it will set this layer to be active, again forcing a redraw if necessary
02172 
02173                 If the given new layer is already active, nothing happens
02174 
02175                 Note: pNewActiveLayer must be in the currect doc
02176 
02177 ***********************************************************************************************/
02178 
02179 void LayerSGallery::MakeActiveLayer(Layer* pNewActiveLayer, BOOL TellAll)
02180 {
02181     Spread* pSpread = pNewActiveLayer->FindParentSpread();
02182     ERROR3IF(pSpread == NULL,"Eh up, the layer has no parent spread");
02183     if (pSpread == NULL) return;
02184 
02185     Document *pDoc = pSpread->FindParentDocument();
02186     if (pDoc == NULL) return;
02187         
02188     {
02189         // Remove any other active layers, redrawing if necessary.
02190         Layer* pLayer = pSpread->FindFirstLayer();
02191         while (pLayer != NULL)
02192         {
02193             if (pLayer->IsActive() && pLayer != pNewActiveLayer)
02194                 LayerSGallery::SetActive(pDoc,pLayer,FALSE);
02195 
02196             pLayer = pLayer->FindNextLayer();
02197         }
02198     }
02199 
02200     // Make sure the new layer is active, redrawing if necessary
02201     if (!pNewActiveLayer->IsActive())
02202         LayerSGallery::SetActive(pDoc,pNewActiveLayer,TRUE);
02203 
02204 #if defined(EXCLUDE_FROM_RALPH)
02205     //ERROR3("LayerSGallery::MakeActiveLayer supressed broadcast - bad !");
02206 #else
02207     if (TellAll)
02208         BROADCAST_TO_ALL(LayerMsg(pNewActiveLayer,LayerMsg::ACTIVE_LAYER_CHANGED));
02209 #endif
02210 }
02211 
02212 
02213 
02214 
02215 /***********************************************************************************************
02216 
02217 >   static void LayerSGallery::EnsureActiveLayerIntegrity(Spread* pSpread,Layer** ppActiveLayer = NULL)
02218 
02219     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02220     Created:    22/3/95
02221     Inputs:     pSpread = ptr to spread
02222     Outputs:    -
02223     Returns:    -
02224     Purpose:    This checks that there is one and only one active layer in the given spread.
02225                 If there isn't an active layer, the first layer is made active.
02226                 If there is more than on active layer, all but the first active layer are
02227                 made inactive.
02228 
02229 ***********************************************************************************************/
02230 
02231 void LayerSGallery::EnsureActiveLayerIntegrity(Spread* pSpread,Layer** ppActiveLayer)
02232 {
02233     if (pSpread == NULL) return;
02234 
02235     // Get the first layer in the spread
02236     Layer* pFirstLayer = pSpread->FindFirstLayer(); 
02237 
02238     // Not found an active layer yet
02239     Layer* pActiveLayer = NULL;
02240 
02241     // Start the search from the first layer
02242     Layer* pLayer = pFirstLayer;
02243 
02244     INT32 ActiveLayers = 0;
02245 
02246     while (pLayer != NULL && pActiveLayer == NULL)
02247     {
02248         if (pLayer->IsActive())
02249         {
02250             ActiveLayers++;
02251             pActiveLayer = pLayer;  // Found the active layer, so make a note of it
02252         }
02253 
02254         pLayer = pLayer->FindNextLayer();
02255     }
02256 
02257     // If we haven't found any active layers, make the last (top) one active
02258     // WEBSTER - markn 23/1/97
02259     // In Webster, always pick the top layer to be the active layer
02260 //#ifndef WEBSTER
02261     if (pActiveLayer == NULL)
02262 //#endif // WEBSTER
02263         pActiveLayer = pSpread->FindLastLayer(); // In this instance ActiveLayers must be 0
02264 
02265     // If we have an active layer, ensure that it really is the one and only active layer
02266     // AMB20060416 - only make the call if did not have exactly one active layer before
02267     // to save an unnecessary layer change message when the layer gallery is brought up
02268     if ((pActiveLayer != NULL) /*&& (ActiveLayers != 1)*/)
02269         LayerSGallery::MakeActiveLayer(pActiveLayer);
02270 
02271     // If caller wants the ptr to the active layer
02272     if (ppActiveLayer != NULL)
02273         *ppActiveLayer = pActiveLayer;
02274 }
02275 
02276             
02277 
02278 /***********************************************************************************************
02279 
02280 >   static void LayerSGallery::MakeTopLayerActive(Spread* pSpread)
02281 
02282     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02283     Created:    9/1/95
02284     Inputs:     pSpread = Spread which should have its top layer made active
02285     Outputs:    -
02286     Returns:    -
02287     Purpose:    Makes the layer active.
02288                 Firstly it will inactivate any other active layers, forcing it to redraw if necessary
02289                 If the new layer is already active, nothing else happens
02290                 Then it will set this layer to be active, again forcing a redraw if necessary
02291 
02292 ***********************************************************************************************/
02293 
02294 void LayerSGallery::MakeTopLayerActive(Spread* pSpread)
02295 {
02296     // Check for NULL spread
02297     if (pSpread == NULL)
02298         return;
02299 
02300     // The top layer is the last layer in the spread's child list
02301     // so find the last layer and make it active
02302     Layer* pLayer = pSpread->FindLastLayer();
02303     if (pLayer != NULL)
02304         MakeActiveLayer(pLayer);
02305 }
02306 
02307 
02308 /********************************************************************************************
02309 
02310 >   static String_256 LayerSGallery::CreateUniqueLayerID()
02311 
02312     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (based on a Simon routine)
02313     Created:    4/8/94
02314     Inputs:     -
02315     Outputs:    -
02316     Returns:    A LayerID which is unique for the layer galleries spread. 
02317     Purpose:    Used to generate a LayerID which is unique for the spread. The name 
02318                 generated is normally of the form "Layer n", where n is the number of layers 
02319                 in the spread + 1. If "Layer n" already exists on the spread then 
02320                 "Layer m" is generated where m is the smallest integer greater than n such 
02321                 that the id is unique.     
02322     Errors:     -
02323     SeeAlso:    -
02324 
02325 ********************************************************************************************/
02326 
02327 String_256 LayerSGallery::CreateUniqueLayerID(Spread* pSpread)
02328 {
02329     if (pSpread == NULL) return String_256("");
02330 
02331     String_256 UniqueLayerID; 
02332     INT32 NumLayers = 0; 
02333 
02334     Layer* pLayer = pSpread->FindFirstLayer();
02335 
02336     // Calculate how many layers are on the current spread
02337     while (pLayer != NULL)
02338     {
02339         // Don't cound the guide layer - it's LayerID (aka Name) is "Guides"
02340         if(!pLayer->IsGuide())
02341         {
02342             NumLayers++;
02343         }
02344         pLayer = pLayer->FindNextLayer();
02345     }
02346 
02347     INT32 NewLayerNum = NumLayers+1; 
02348 
02349     BOOL Unique;  // Flag used to indicate if the id generated is unique or not 
02350     do 
02351     {
02352         // Construct a first attempt at a unique layer id 'Layer n' 
02353         // where n = the number of layers on the current spread + 1  
02354         UniqueLayerID.MakeMsg(_R(IDS_SGLAYER_LAYER_NUM), /*TEXT("Layer #1%ld"),*/NewLayerNum);
02355     
02356         // Check that UniqueLayerID is indeed unique 
02357         Unique = TRUE; // Until we know better 
02358         pLayer = pSpread->FindFirstLayer();
02359         while (pLayer != NULL)
02360         {   
02361             if (UniqueLayerID == pLayer->GetLayerID())
02362             {
02363                 Unique = FALSE; 
02364 
02365                 // UniqueLayerID is not unique so increment NewLayerNum and try again 
02366                 NewLayerNum++;      
02367                 break; 
02368             }
02369             pLayer = pLayer->FindNextLayer();
02370         }
02371         
02372     } while (!Unique); 
02373 
02374     return(UniqueLayerID); 
02375 }
02376 
02377 #ifndef EXCLUDE_GALS
02378 
02379 /***********************************************************************************************
02380 
02381 >   BOOL LayerSGallery::CheckVarsAreValid()
02382 
02383     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02384     Created:    8/8/94
02385     Inputs:     -
02386     Outputs:    -
02387     Returns:    TRUE  - the vars are ok
02388                 FALSE - one or more of the vars is invalid 
02389     Purpose:    A routine that checks to see if critical vars are OK.
02390                 All it does at the mo is check that pSpread and pDoc are not NULL.
02391                 In debug builds, an ENSURE will go off if something goes wrong
02392 
02393 ***********************************************************************************************/
02394 
02395 BOOL LayerSGallery::CheckVarsAreValid()
02396 {
02397     return ((pSpread != NULL) && (pDoc != NULL));
02398 }
02399 
02400 
02401 /***********************************************************************************************
02402 
02403 >   void LayerSGallery::EnsureActiveLayerIntegrity()
02404 
02405     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02406     Created:    9/8/94
02407     Inputs:     -
02408     Outputs:    -
02409     Returns:    -
02410     Purpose:    This checks that there is one and only one active layer in the gallery's spread.
02411     SeeAlso:    LayerSGallery::EnsureActiveLayerIntegrity(Spread* pSpread)
02412 
02413 ***********************************************************************************************/
02414 
02415 void LayerSGallery::EnsureActiveLayerIntegrity()
02416 {
02417     LayerSGallery::EnsureActiveLayerIntegrity(pSpread);
02418 }
02419 
02420 
02421 /***********************************************************************************************
02422 
02423 >   SGDisplayLayer *LayerSGallery::GetSelectedLayerGalItem()
02424 
02425     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02426     Created:    8/8/94
02427     Inputs:     -
02428     Outputs:    -
02429     Returns:    A ptr to the selected layer gallery item.
02430                 NULL if there is no selectet item
02431     Purpose:    Gets the selected layer gallery item
02432                 In debug builds, an ENSURE will go off if there is no selected gal item
02433 
02434 ***********************************************************************************************/
02435 
02436 SGDisplayLayer *LayerSGallery::GetSelectedLayerGalItem()
02437 {
02438     SGDisplayLayer* pDispLayer = NULL;
02439 
02440     if (CheckVarsAreValid())
02441     {
02442         ERROR3IF(DisplayForeground == NULL || DisplayBackground == NULL,"Fore and/or background group(s) are/is NULL");
02443         if (DisplayForeground == NULL || DisplayBackground == NULL)
02444             return NULL;
02445 
02446         // Look in the foreground group first
02447         pDispLayer = ((SGDisplayLayer *) DisplayForeground->FindNextSelectedItem(NULL));
02448 
02449         // If no joy, have a look in the background group
02450         if (pDispLayer == NULL)
02451             pDispLayer = ((SGDisplayLayer *) DisplayBackground->FindNextSelectedItem(NULL));
02452 
02453         ERROR3IF(pDispLayer == NULL,"Can't find the selected layer item in the layer gallery");
02454 
02455 //      SGDisplayGroup  *DocumentGroup = DisplayTree->FindSubtree(this, pDoc, NULL);
02456 //      if (DocumentGroup != NULL)
02457 //          return((SGDisplayLayer *) DocumentGroup->FindNextSelectedItem(NULL));
02458     }
02459 
02460     return(pDispLayer);
02461 }
02462 
02463 
02464 
02465 /***********************************************************************************************
02466 
02467 >   BOOL LayerSGallery::HasLayerGotChildren(Layer* pLayer)
02468 
02469     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02470     Created:    10/8/94
02471     Inputs:     pLayer = the layer you want to check
02472     Outputs:    -
02473     Returns:    TRUE  - The layer has children the user may be interested in - i.e. children
02474                         that actually render something.
02475                 FALSE - The layer has no rendering children
02476     Purpose:    Scans the layer for children that render something on the screen.
02477                 It ignores attributes, hidden nodes, etc - nodes that don't render anything themselves.
02478                 
02479                 Code moved into Layer::HasLayerGotRenderableChildren 21/7/97
02480 
02481 ***********************************************************************************************/
02482 
02483 BOOL LayerSGallery::HasLayerGotChildren(Layer* pLayer)
02484 {
02485     ERROR2IF(pLayer == NULL,FALSE,"HasLayerGotChildren bad param!");
02486     return pLayer->HasLayerGotRenderableChildren();
02487 }
02488 
02489 /***********************************************************************************************
02490 
02491 >   BOOL LayerSGallery::PrepareToDelete(void)
02492 
02493     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02494     Created:    2/8/94
02495     Purpose:    Scans the current Gallery selection. Possibly asks the user for
02496                 confirmation about the delete. Possibly adjusts the selection as
02497                 appropriate. Then returns a value to indicate whether the remaining
02498                 selection should be deleted.
02499     SeeAlso:    LayerSGallery::DoDeleteSelection
02500 
02501 ***********************************************************************************************/
02502  
02503 BOOL LayerSGallery::PrepareToDelete(void)
02504 {
02505     SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
02506 
02507     if (pLayerGalItem != NULL)
02508     {
02509         if (HasLayerGotChildren(pLayerGalItem->GetDisplayedLayer()) != FALSE)
02510         {
02511             // If some are in use, determine if the user really wants to delete them
02512             INT32 ButtonPressed = AskQuestion(_R(IDS_LAYER_CONSTAINSOBJECTS),
02513                                             _R(IDS_LAYER_DELETE), _R(IDB_CANCEL), 0, 0,
02514                                             2, 2);
02515                                           
02516             if (ButtonPressed == 1)     // Force-delete all items, so go ahead and delete
02517                 return(TRUE);
02518 
02519             // Delete was cancelled (or Help pressed) - return FALSE
02520             return(FALSE);
02521         }
02522         else
02523             return(TRUE);
02524     }
02525     
02526     return (pLayerGalItem != NULL);
02527 }
02528 
02529 
02530 
02531 /***********************************************************************************************
02532 
02533 >   BOOL LayerSGallery::DoDeleteSelection(void)
02534 
02535     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02536     Created:    2/8/94
02537     Returns:    FALSE if it couldn't delete the selection. (This should, if at all possible
02538                 leave the entire selection undeleted in this case)
02539 
02540     Purpose:    FORCIBLY deletes the current gallery selection. By the time this function
02541                 is called, PrepareToDelete has made sure that it is safe to continue.
02542                 This must simply invoke a forced delete upon the selection.
02543                 Deletion of colours occurs by hiding (with undo)
02544 
02545     SeeAlso:    LayerSGallery::PrepareToDelete; ColourManager::HideColours
02546 
02547 ***********************************************************************************************/
02548  
02549 BOOL LayerSGallery::DoDeleteSelection(void)
02550 {
02551     SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
02552 
02553     if (pLayerGalItem != NULL)
02554     {
02555         OpLayerGalParam Param(LAYER_DELETE,pSpread);
02556         Param.pLayer = pLayerGalItem->GetDisplayedLayer();
02557 
02558         OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
02559         if (pOpDesc != NULL)
02560             pOpDesc->Invoke((OpParam*)&Param);
02561         else
02562         {
02563             ERROR3("Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
02564         }
02565         return (TRUE);
02566     }
02567 
02568     return (pLayerGalItem != NULL);
02569 }
02570 
02571 
02572 
02573 
02574 
02575 /***********************************************************************************************
02576 
02577 >   void LayerSGallery::DoCreateNewItem(void)
02578 
02579     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02580     Created:    2/8/94
02581 
02582     Purpose:    This function is meant to be overridden in derived classes
02583                 It creates a new item and adds it to the Gallery DisplayList
02584                 The item may be created by cloning/deriving/basing-on the
02585                 selected item, depending on the type of Gallery concerned.
02586 
02587 ***********************************************************************************************/
02588 
02589 void LayerSGallery::DoCreateNewItem(void)
02590 {
02591     if (!CheckVarsAreValid())
02592         return;
02593     LayerDlgParam Param(LAYER_NEW,pSpread,NULL);
02594     LayerNameDlg::StartUp(&Param);
02595 
02596 }
02597 
02598 /***********************************************************************************************
02599 
02600 >   void LayerSGallery::DoChangeName()
02601 
02602     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02603     Created:    9/8/94
02604     Inputs:     -
02605     Returns:    -
02606     Purpose:    Pops up the name changing dialog for the selected layer
02607 
02608 ***********************************************************************************************/
02609 
02610 void LayerSGallery::DoChangeName()
02611 {
02612     SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
02613 
02614     if (pLayerGalItem != NULL)
02615     {
02616         LayerDlgParam Param(LAYER_CHANGE_NAME,NULL,pLayerGalItem->GetDisplayedLayer());
02617         LayerNameDlg::StartUp(&Param);
02618     }
02619 }
02620 
02621 
02622 
02623 
02624 /***********************************************************************************************
02625 
02626 >   void LayerSGallery::DoCopyLayer()
02627 
02628     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02629     Created:    9/8/94
02630     Inputs:     -
02631     Returns:    -
02632     Purpose:    Pops up the name changing dialog for the selected layer, and if OK is clicked
02633                 a copy of the layer is made with the new name.
02634 
02635 ***********************************************************************************************/
02636 
02637 void LayerSGallery::DoCopyLayer()
02638 {
02639     SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
02640 
02641     if (pLayerGalItem != NULL)
02642     {
02643         LayerDlgParam Param(LAYER_COPY,NULL,pLayerGalItem->GetDisplayedLayer());
02644         LayerNameDlg::StartUp(&Param);
02645     }
02646 }
02647 
02648 
02649 /***********************************************************************************************
02650 
02651 >   void LayerSGallery::DoLayerProperties()
02652 
02653     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02654     Created:    3/10/95
02655     Inputs:     -
02656     Returns:    -
02657     Purpose:    Opens the layer properties dlg
02658 
02659 ***********************************************************************************************/
02660 
02661 void LayerSGallery::DoLayerProperties()
02662 {
02663 #ifndef STANDALONE
02664     // layer property tabs not present in viewer
02665     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERPROPERTYTABS);
02666 
02667     if (pOpDesc != NULL)
02668     {
02669         String_256 Str;
02670         OpState State = pOpDesc->GetOpsState(&Str);
02671         if (!State.Greyed)
02672             pOpDesc->Invoke();
02673         else
02674         {
02675 // Changed for Frame/Layer integration - RanbirR
02676 //#ifdef WEBSTER
02677 //          GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs();
02678 //#else
02679             LayerPropertyTabs * pTabHandler = LayerPropertyTabsDlg::GetLayerPropertiesTabs();   
02680 //#endif // webster -RanbirR
02681             if (pTabHandler)
02682             {
02683                 DialogTabOp* pDlg =  pTabHandler->GetTabbedDlg();
02684                 if (pDlg != NULL)
02685                     pDlg->Open();
02686             }
02687         }
02688     }
02689 #endif
02690 }
02691 
02692 /***********************************************************************************************
02693 
02694 >   void LayerSGallery::DoCreateGuideLayer()
02695 
02696     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02697     Created:    4/10/95
02698     Inputs:     -
02699     Returns:    -
02700     Purpose:    Creates a guide layer
02701 
02702 ***********************************************************************************************/
02703 
02704 void LayerSGallery::DoCreateGuideLayer()
02705 {
02706 #ifndef WEBSTER
02707     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GUIDELINE);
02708     ERROR3IF(pOpDesc == NULL,"FindOpDescriptor(OPTOKEN_GUIDELINE) failed");
02709 
02710     if (pOpDesc != NULL)
02711     {
02712         OpGuidelineParam GuidelineParam;
02713 
02714         GuidelineParam.Method = GUIDELINEOPMETHOD_CREATE_GUIDE_LAYER;
02715 
02716         pOpDesc->Invoke(&GuidelineParam);
02717     }
02718 #endif // WEBSTER
02719 }
02720 
02721 /***********************************************************************************************
02722 
02723 >   void LayerSGallery::DoChangeAllVisible(BOOL AllVisible)
02724 
02725     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02726     Created:    11/8/94
02727     Inputs:     AllVisible - TRUE  means all layers become visible
02728                               FALSE means only visible layers are visible
02729 
02730     Returns:    -
02731     Purpose:    Called when the AllVisible button is clicked in the layers gallery.
02732                 Effects the visibility of all layers, regardless of their visibility
02733 
02734 ***********************************************************************************************/
02735 
02736 void LayerSGallery::DoChangeAllVisible(BOOL AllVisible)
02737 {
02738     if (!CheckVarsAreValid()) return;
02739 
02740     // Get the state prior to the change
02741     BOOL PrevAllVisible = pDoc->IsAllVisible();
02742 
02743     // If no change, return
02744     if (PrevAllVisible == AllVisible) return;
02745 
02746     Layer* pLayer = pSpread->FindFirstLayer();
02747 
02748     while (pLayer != NULL)
02749     {
02750         // Do not include the page background layer in this process as this is very bad!
02751         if (!pLayer->IsPageBackground())
02752         {
02753             pDoc->SetAllVisible(PrevAllVisible);
02754             BOOL PrevVisible = pLayer->IsVisible();
02755 //          BOOL PrevLocked  = pLayer->IsLocked();
02756 
02757             pDoc->SetAllVisible(AllVisible);
02758             BOOL PostVisible = pLayer->IsVisible();
02759 //          BOOL PostLocked  = pLayer->IsLocked();
02760 
02761             if (PrevVisible != PostVisible)
02762             {
02763                 LayerSGallery::ForceRedrawLayer(pDoc,pLayer);
02764 
02765                 if (!PostVisible)
02766                     NodeRenderableInk::DeselectAllOnLayer(pLayer); 
02767             }
02768         }
02769 
02770         pLayer = pLayer->FindNextLayer();
02771     }
02772 
02773     pDoc->SetAllVisible(AllVisible);
02774 
02775     // inform that visible layers have changed
02776     BROADCAST_TO_ALL(LayerMsg(pLayer, LayerMsg::LAYER_VISIBILITY_CHANGED));
02777 }
02778 
02779 
02780 
02781 /***********************************************************************************************
02782 
02783 >   void LayerSGallery::DoChangeMultilayer(BOOL Multilayer)
02784 
02785     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02786     Created:    11/8/94
02787     Inputs:     Multilayer - TRUE  means all layers become unlocked
02788                              FALSE means only locked layers are locked
02789 
02790     Returns:    -
02791     Purpose:    Called when the Multilayer button is clicked in the layers gallery.
02792                 Effects the locked state of all layers, regardless of their individual locked state
02793 
02794 ***********************************************************************************************/
02795 
02796 void LayerSGallery::DoChangeMultilayer(BOOL Multilayer)
02797 {
02798     if (!CheckVarsAreValid()) return;
02799 
02800     // Get the state prior to the change
02801     BOOL PrevMultilayer = pDoc->IsMultilayer();
02802 
02803     // If no change, return
02804     if (PrevMultilayer == Multilayer) return;
02805 
02806     Layer* pLayer = pSpread->FindFirstLayer();
02807     BOOL PrevLocked;
02808     BOOL PostLocked;
02809 
02810     while (pLayer != NULL)
02811     {
02812         // Do not include the page background layer in this process as this is very bad!
02813         if (!pLayer->IsPageBackground())
02814         {
02815             pDoc->SetMultilayer(PrevMultilayer);
02816             PrevLocked = pLayer->IsLocked();
02817             pDoc->SetMultilayer(Multilayer);
02818             PostLocked = pLayer->IsLocked();
02819 
02820             if ((PrevLocked != PostLocked) && PostLocked)
02821                 NodeRenderableInk::DeselectAllOnLayer(pLayer); 
02822         }
02823 
02824         pLayer = pLayer->FindNextLayer();
02825     }
02826 
02827     pDoc->SetMultilayer(Multilayer);
02828 }
02829 
02830 
02831 
02832 /***********************************************************************************************
02833 
02834 >   static void LayerSGallery::DoChangeVisible(Layer* pLayer,BOOL Visible)
02835 
02836     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Jason, ripped from the LayerGallery, 1/2/95)
02837     Created:    8/8/94
02838     Inputs:     pLayer = the layer to change
02839                 Visible - TRUE means make the displayed layer visible
02840                           FALSE means make invisiblr
02841 
02842     Returns:    -
02843     Purpose:    Called when the visible button is clicked in a layer gallery item.
02844                 Changes the visibility of the displayed layer.
02845 
02846     Notes:      Does not redraw the layer in the display list
02847 
02848 ***********************************************************************************************/
02849 
02850 void LayerSGallery::DoChangeVisible(Layer* pLayer,BOOL Visible)
02851 {
02852     ERROR3IF(pLayer == NULL,"pLayer == NULL");
02853     if (pLayer == NULL) return;
02854 
02855     BOOL PrevVisible = pLayer->IsVisible();
02856     pLayer->SetVisible(Visible);
02857     BOOL PostVisible = pLayer->IsVisible();
02858 
02859     if (PrevVisible != PostVisible)
02860     {
02861         // Force a redraw if the layer's visibility has changed
02862         LayerSGallery::ForceRedrawLayer(pLayer->FindDocument(), pLayer);
02863 
02864         // inform that visible layers have changed
02865         BROADCAST_TO_ALL(LayerMsg(pLayer, LayerMsg::LAYER_VISIBILITY_CHANGED));
02866 
02867         // If layer has just become invisible, remove the selections on the layer 
02868         if (!PostVisible)
02869             NodeRenderableInk::DeselectAllOnLayer(pLayer); 
02870     }
02871 }
02872 
02873 /***********************************************************************************************
02874 
02875 >   static void LayerSGallery::DoChangeLocked(Layer* pLayer,BOOL Locked)
02876 
02877     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (Jason, ripped from the LayerGallery, 1/2/95)
02878     Created:    8/8/94
02879     Inputs:     pLayer = the layer to change
02880                 Locked - TRUE means make the displayed layer locked
02881                          FALSE means unlock
02882 
02883     Returns:    -
02884     Purpose:    Called when the Locked button is clicked in a layer gallery item.
02885                 Changes the lockedness of the displayed layer.
02886 
02887     Notes:      Does not redraw the layer in the display list
02888 
02889 ***********************************************************************************************/
02890 
02891 void LayerSGallery::DoChangeLocked(Layer* pLayer,BOOL Locked)
02892 {
02893     ERROR3IF(pLayer == NULL,"pLayer == NULL");
02894     if (pLayer == NULL) return;
02895 
02896     BOOL PrevLocked = pLayer->IsLocked();
02897     pLayer->SetLocked(Locked);
02898     BOOL PostLocked = pLayer->IsLocked();
02899 
02900     if (PrevLocked != PostLocked)
02901         NodeRenderableInk::DeselectAllOnLayer(pLayer); 
02902 }
02903 
02904 
02905 /***********************************************************************************************
02906 
02907 >   void LayerSGallery::DoChangeLayerStatus(Layer* pLayer,const LayerStatus& NewStatus)
02908 
02909     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02910     Created:    8/8/94
02911     Inputs:     pLayer = ptr to the layer to change
02912                 NewStatus = reference to the status that the selected layer should
02913                             take on board.
02914     Returns:    -
02915     Purpose:    General undoable way of changing the selected layer's status
02916 
02917 ***********************************************************************************************/
02918 
02919 void LayerSGallery::DoChangeLayerStatus(Layer* pLayer, const LayerStatus& NewStatus)
02920 {
02921     if (!CheckVarsAreValid()) return;
02922 
02923     OpLayerGalParam Param(LAYER_CHANGE, pSpread);
02924 
02925     Param.pLayer = pLayer;
02926     Param.Status = NewStatus;
02927 
02928     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
02929     if (pOpDesc != NULL)
02930         pOpDesc->Invoke((OpParam*)&Param);
02931     else
02932     {
02933         ENSURE(FALSE,"Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
02934     }
02935 }
02936 
02937 /***********************************************************************************************
02938 
02939 >   void LayerSGallery::DoChangeLayerState(Layer* pLayer,OpLayerGalReason Reason,BOOL NewState)
02940 
02941     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02942     Created:    7/3/95
02943     Inputs:     pLayer = ptr to the layer to change
02944                 Reason = the flag which to change
02945                 NewState = The new state of the flag to change
02946     Returns:    -
02947     Purpose:    Undoable way of changing the layer's state
02948 
02949 ***********************************************************************************************/
02950 
02951 void LayerSGallery::DoChangeLayerState(Layer* pLayer,OpLayerGalReason Reason,BOOL NewState)
02952 {
02953     if (!CheckVarsAreValid()) return;
02954 
02955     OpLayerGalParam Param(Reason, pSpread);
02956 
02957     Param.pLayer    = pLayer;
02958     Param.NewState  = NewState;
02959     Param.pLayerSGal= this;
02960 
02961     OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
02962     if (pOpDesc != NULL)
02963         pOpDesc->Invoke((OpParam*)&Param);
02964     else
02965     {
02966         ERROR3("Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
02967     }
02968 }
02969 
02970 
02971 
02972 
02973 /***********************************************************************************************
02974 
02975 >   void LayerSGallery::DoMoveLayer(MoveLayerType Reason)
02976 
02977     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
02978     Created:    9/8/94
02979     Inputs:     Reason = how the layer should be moved
02980     Returns:    -
02981     Purpose:    Called when the Locked button is clicked in the layers gallery.
02982                 Changes the lockedness of the selected layer, if there is one.
02983 
02984 ***********************************************************************************************/
02985 
02986 void LayerSGallery::DoMoveLayer(MoveLayerType Reason)
02987 {
02988     SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
02989 
02990     if (pLayerGalItem != NULL)
02991     {
02992         OpLayerGalParam Param(LAYER_MOVE, pSpread);
02993 
02994         Param.pLayer = pLayerGalItem->GetDisplayedLayer();
02995 
02996         switch (Reason)
02997         {
02998             case (MOVELAYER_UPONE) :
02999                 Param.pContextNode  = Param.pLayer->FindNextLayer();
03000                 Param.AttDir        = NEXT;
03001                 break;
03002 
03003             case (MOVELAYER_DOWNONE) :
03004                 Param.pContextNode  = Param.pLayer->FindPrevLayer();
03005                 Param.AttDir        = PREV;
03006                 break;
03007 
03008             default:
03009                 ENSURE(FALSE,"Unrecognised MoveLayer reason");
03010                 break;
03011         }
03012 
03013         if (Param.pContextNode != NULL)
03014         {
03015             // Redraw after the op if both this layer and the one it's moving in front/behind
03016             // is also visible
03017             Param.MoveRedraw = ((Layer*)Param.pContextNode)->IsVisible() &&
03018                                     Param.pLayer->IsVisible();
03019 
03020             // The above won't work in an undo or redo, so always redraw
03021             Param.MoveRedraw = TRUE;
03022 
03023             OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_LAYERGALCHANGE); 
03024             if (pOpDesc != NULL)
03025                 pOpDesc->Invoke((OpParam*)&Param);
03026             else
03027             {
03028                 ENSURE(FALSE,"Couldn't find OPTOKEN_LAYERGALCHANGE op descriptor");
03029             }
03030         }
03031     }
03032 }
03033 
03034 
03035 /***********************************************************************************************
03036 
03037 >   BOOL LayerSGallery::IsSelectedItemGuideLayer()
03038 
03039     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
03040     Created:    6/10/95
03041     Inputs:     -
03042     Returns:    TRUE if the selected layer is a guide layer or no selected layer, FALSE otherwise
03043     Purpose:    General function for finding out if the selected item is a guide layer
03044     Notes:      Need not be overridden - the default action is to do nothing extra
03045                 to the normal shade/unshade operation.
03046     SeeAlso:    Gallery::ShadeGallery; Gallery::UnshadeGallery
03047 
03048 ***********************************************************************************************/
03049 
03050 BOOL LayerSGallery::IsSelectedItemGuideLayer()
03051 {
03052     SGDisplayLayer* pItem = GetSelectedLayerGalItem();
03053     Layer* pLayer = NULL;
03054 
03055     if (pItem != NULL)
03056         pLayer = pItem->GetDisplayedLayer();
03057 
03058     if (pLayer != NULL)
03059         return (pLayer->IsGuide());
03060 
03061     return TRUE;
03062 }
03063 
03064 /***********************************************************************************************
03065 
03066 >   void LayerSGallery::DoShadeGallery(BOOL ShadeIt)
03067 
03068     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03069     Created:    6/9/94
03070     Inputs:     ShadeIt -   TRUE if the gallery is being shaded
03071                             FALSE if the gallery is being unshaded
03072     Purpose:    Called by the base class whenever the shaded status of the gallery
03073                 is changed, to allow derived galleries to shade/unshade any extra
03074                 controls that they provide in the window. ONLY called if the gallery
03075                 is actually open/visible.
03076 
03077     Notes:      Need not be overridden - the default action is to do nothing extra
03078                 to the normal shade/unshade operation.
03079     SeeAlso:    Gallery::ShadeGallery; Gallery::UnshadeGallery
03080 
03081 ***********************************************************************************************/
03082 
03083 void LayerSGallery::DoShadeGallery(BOOL ShadeIt)
03084 {
03085     BOOL fEnableMove = FALSE;
03086     OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_MOVE_SEL_TO_ACTIVE_LAYER);
03087     if (pDesc != 0)
03088     {
03089         String_256 str;
03090         OpState os = pDesc->GetOpsState(&str);
03091         fEnableMove = !os.Greyed;
03092     }
03093 
03094     EnableGadget(_R(IDC_LAYER_MOVE_TO_ACTIVE),  !ShadeIt && fEnableMove);
03095     EnableGadget(_R(IDC_GALLERY_UPONE),         !ShadeIt);
03096     EnableGadget(_R(IDC_GALLERY_DOWNONE),       !ShadeIt);
03097     EnableGadget(_R(IDC_GALLERY_PROPERTIES),    !ShadeIt);
03098     EnableGadget(_R(IDC_GALLERY_COPY),          !ShadeIt && !IsSelectedItemGuideLayer());
03099 
03100     EnableGadget(_R(IDC_BTN_MULTILAYER),        !ShadeIt);
03101     EnableGadget(_R(IDC_BTN_ALLVISIBLE),        !ShadeIt);
03102 
03103     //EnableGadget(_R(IDC_GALLERY_NAME),        !ShadeIt);
03104 }
03105 
03106 
03107 /********************************************************************************************
03108 
03109 >   virtual SGDisplayItem *LayerSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, 
03110                                     SGDisplayGroup *DestGroup,
03111                                     SGDisplayItem *TargetPosition = NULL)
03112 
03113     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> (from a Jason func)
03114     Created:    21/3/95
03115 
03116     Inputs:     SourceItem - The item to copy elsewhere in the tree (see below)
03117 
03118                 DestGroup - The group into which the item should be inserted
03119 
03120                 TargetPosition - NULL (to add to the end of the sibling list), or
03121                 points to the item BEFORE which the SourceItem will be copied.
03122 
03123     Returns:    NULL (failed) or a pointer to the new (copied) display item
03124 
03125     Purpose:    "Copies" the existing node in the tree in an appropriate fashion.
03126                 
03127                 This method is normally called when a gallery-organising drag completes,
03128                 and it is discovered that the dragged item(s) have been dragged to a 
03129                 different display group.
03130 
03131     Notes:      This method should be overridden by derived galleries to provide
03132                 appropriate behaviour (some galleries (e.g colour) will copy the real-item
03133                 that the given display-item references to the new group (document), while
03134                 other galleries (layer) may just move the item after all).
03135 
03136                 Note the handy InsertCopiedItem and MoveBefore/After methods which
03137                 are available to take all of the hard work out of copying/moving items!
03138 
03139                 See the body of this method in the source code for example pseudocode.
03140                 For real code, see the Colour Gallery (sgcolour.cpp)
03141 
03142     SeeAlso:    SuperGallery::InsertCopiedItem; SGDisplayItem::MoveBefore;
03143                 SGDisplayItem::MoveAfter; SGColour::CopyDisplayItem
03144 
03145 ********************************************************************************************/
03146 
03147 SGDisplayItem *LayerSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, 
03148                         SGDisplayGroup *DestGroup, SGDisplayItem *TargetPosition)
03149 {
03150     ERROR3IF(SourceItem == NULL || DestGroup == NULL, "Illegal NULL param");
03151     if (SourceItem == NULL || DestGroup == NULL)
03152         return(NULL);
03153 
03154     ERROR3IF(!IS_A(DestGroup,SGLayerGroup),"DestGroup is not a SGLayerGroup");
03155     ERROR3IF(!IS_A(SourceItem,SGDisplayLayer),"SourceItem is not a SGDisplayLayer");
03156     if (!IS_A(DestGroup,SGLayerGroup) || !IS_A(SourceItem,SGDisplayLayer))
03157         return(NULL);
03158 
03159     SGLayerGroup*   pDestLayerGroup  = (SGLayerGroup*)DestGroup;
03160     SGDisplayLayer* pSourceLayerItem = (SGDisplayLayer*)SourceItem;
03161 
03162     SGDisplayItem*  pDestItem   = TargetPosition;
03163     BOOL            Before      = TRUE;
03164 
03165     if (pDestItem == NULL)
03166     {
03167         pDestItem = (SGDisplayItem*) pDestLayerGroup->GetChild();
03168         Before = TRUE;
03169 
03170         if (pDestItem == NULL)
03171         {
03172             SGDisplayNode* pNode = SourceItem;
03173             while (pNode != NULL)
03174             {
03175                 pDestItem = (SGDisplayItem*) pNode;
03176                 if (pDestLayerGroup->IsForeground())
03177                     pNode = pNode->GetPrevious();
03178                 else
03179                     pNode = pNode->GetNext();
03180             }
03181 
03182             Before = pDestLayerGroup->IsForeground();
03183         }
03184         else
03185         {
03186             SGDisplayItem* pLastDestItem = NULL;
03187             while (pDestItem != NULL)
03188             {
03189                 pLastDestItem = pDestItem;
03190                 pDestItem = (SGDisplayItem*)(pDestItem->GetNext());
03191             }
03192 
03193             pDestItem = pLastDestItem;
03194             Before = FALSE;
03195         }
03196     }
03197 
03198     ERROR3IF(pDestItem == NULL,"pDestItem is still NULL");
03199     if (pDestItem == NULL)
03200         return(NULL);
03201 
03202     // Move the display item around
03203     SourceItem->RemoveFromTree();       // Delink from current displaytree position
03204     SuperGallery::InsertCopiedItem(SourceItem, DestGroup, TargetPosition);
03205 
03206     if (pDestItem != NULL)
03207     {
03208         ERROR3IF(!IS_A(pDestItem,SGDisplayLayer),"SourceItem is not a SGDisplayLayer");
03209         if (!IS_A(pDestItem,SGDisplayLayer))
03210             return(NULL);
03211 
03212         SGDisplayLayer* pDestLayerItem = (SGDisplayLayer*)pDestItem;
03213         pDestLayerItem->MoveLayer(pSourceLayerItem,Before,TRUE);
03214     }
03215 
03216     return(SourceItem);
03217 }
03218 
03219 
03220 
03221 /********************************************************************************************
03222 
03223 >   virtual BOOL LayerSGallery::InitMenuCommands(void)
03224                                                  
03225     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03226     Created:    18/9/95
03227 
03228     Returns:    TRUE for success
03229 
03230     Purpose:    Initialises any menu commands that this gallery needs.
03231 
03232     Notes:      Will only create the menu commands once - further calls in the future
03233                 will return TRUE immediately wihtout doing anything.
03234 
03235 ********************************************************************************************/
03236 
03237 BOOL LayerSGallery::InitMenuCommands(void)
03238 {
03239     static BOOL MenusInitialised = FALSE;
03240 
03241     BOOL ok = TRUE;
03242 
03243     if (!MenusInitialised)
03244     {
03245         // Initialise menu command Ops
03246         // "Special" entries for over-list menu
03247         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Copy,      _R(IDS_SGMENU_COPY));
03248         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Delete,    _R(IDS_SGMENU_DELETE));
03249         ok = ok && InitMenuCommand((StringBase *) &SGCmd_New,       _R(IDS_NEW_LAYER));
03250         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Create,    _R(IDS_CREATE_GUIDE_LAYER));
03251         ok = ok && InitMenuCommand((StringBase *) &SGCmd_Properties,_R(IDS_SGMENU_PROPERTIES));
03252 
03253         MenusInitialised = TRUE;
03254     }
03255 
03256     return(ok);
03257 }
03258 
03259 
03260 
03261 /********************************************************************************************
03262 
03263 >   virtual BOOL LayerSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID)
03264 
03265     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03266     Created:    15/9/95
03267 
03268     Inputs:     TheMenu - The menu to add commands to
03269                 MenuID  - The type of menu (over-list or from-options-button) to create
03270 
03271     Returns:    TRUE if it succeeded
03272 
03273     Purpose:    To build a menu of commands to be popped up over the gallery.
03274     
03275     Notes:      The Layer gallery provides only a simple item-pop-up menu
03276 
03277 ********************************************************************************************/
03278 
03279 BOOL LayerSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID)
03280 {
03281     BOOL ok = TRUE;
03282 
03283     if (MenuID == SGMENU_OVERITEM)
03284     {
03285         // Over-list menu
03286         SGDisplayLayer* pLayerGalItem = GetSelectedLayerGalItem();
03287 
03288 #ifndef STANDALONE
03289 // no layer properties tab present on standalone version
03290         if (pLayerGalItem != NULL)
03291         {
03292 // Changed for Frame/Layer integration.
03293 //#ifdef WEBSTER
03294 //          GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs();
03295 //#else
03296             LayerPropertyTabs * pTabHandler = LayerPropertyTabsDlg::GetLayerPropertiesTabs();
03297 //#endif //webster
03298             if (pTabHandler)
03299             {
03300                 pTabHandler->SetCurrentLayer(pLayerGalItem->GetDisplayedLayer());
03301             }
03302         }
03303 #endif
03304         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_New);
03305         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Copy);
03306         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Delete,TRUE);
03307         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Create);
03308 #ifndef STANDALONE
03309         ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Properties);
03310 #endif
03311     }
03312 
03313     return(ok);
03314 }
03315 
03316 
03317 
03318 /********************************************************************************************
03319 
03320 >   virtual OpState LayerSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason)
03321 
03322     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03323     Created:    15/9/95
03324 
03325     Inputs:     CommandID - TheString ID of the command
03326     Outputs:    ShadeReason - If you return (OpState.Greyed == TRUE) then this should be filled
03327                 ion with the reason that the item is shaded/greyed.
03328 
03329     Returns:    An OpState indicating the current menu item state.
03330 
03331     Purpose:    To determine the state of a given menu item. This method is an exact
03332                 parallel to an Op's GetState method (in fact, it is called by an Op's GetState)
03333     
03334     Notes:      Override this method to provide state info for your special commands
03335                 Call the base class for unknown commands to allow it to handle them for you
03336 
03337                 The base class handles all of these (maybe more - see the base class help)
03338                     Properties, Sort, Find;
03339                     New, Edit, Delete, Redefine;
03340                     NextGroup, PrevGroup, FoldGroup, UnfoldGroup;
03341 
03342 ********************************************************************************************/
03343 
03344 OpState LayerSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason)
03345 {
03346     OpState State;
03347 
03348     if (AmShaded)       // No commands available while the gallery is shaded
03349     {
03350         State.Greyed = TRUE;
03351         return(State);
03352     }
03353 
03354     if (*CommandID == SGCmd_Copy    || // --- Copy/Delete/Properties
03355         *CommandID == SGCmd_Delete  ||
03356         *CommandID == SGCmd_Properties) 
03357     {
03358         SGDisplayLayer* pItem = GetSelectedLayerGalItem();
03359 
03360         if (pItem == NULL)
03361         {
03362             State.Greyed = TRUE;
03363             ShadeReason->MakeMsg(_R(IDS_SGSHADE_SINGLECOL));
03364         }
03365         else if (*CommandID == SGCmd_Copy)          // Can't copy Guide layers
03366             State.Greyed = IsSelectedItemGuideLayer();
03367 #ifndef STANDALONE
03368         else if (*CommandID == SGCmd_Properties)    // Shade when dlg is open
03369         {
03370             //State.Greyed = (LayerPropertyTabs::GetTabbedDlg() != NULL);
03371 //#ifdef WEBSTR
03372 //          GIFAnimationPropertyTabs * pTabHandler = GIFAnimationPropertyTabsDlg::GetGIFAnimationPropertiesTabs();
03373 //#else
03374             LayerPropertyTabs * pTabHandler = LayerPropertyTabsDlg::GetLayerPropertiesTabs();
03375 //#endif //webster RanbirR
03376             if (pTabHandler)
03377                 State.Greyed = (pTabHandler->GetTabbedDlg() != NULL);
03378             else
03379                 State.Greyed = TRUE;    
03380         }
03381 #endif
03382     }
03383     else if (*CommandID == SGCmd_Create)
03384     {
03385         Spread* pSpread = Document::GetSelectedSpread();
03386         Layer* pGuideLayer = NULL;
03387 
03388         if (pSpread != NULL)
03389             pGuideLayer = pSpread->FindFirstGuideLayer();
03390 
03391         State.Greyed = (pGuideLayer != NULL);
03392     }
03393 
03394 
03395     // Don't call the base class 'cos we don't want any other commands
03396 
03397     return(State);
03398 }
03399 
03400 
03401 
03402 /********************************************************************************************
03403 
03404 >   virtual void LayerSGallery::DoCommand(StringBase *CommandID)
03405 
03406     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
03407     Created:    15/9/95
03408 
03409     Inputs:     CommandID - The String ID of the command
03410 
03411     Purpose:    To apply a given command when it is chosen from the menu.
03412     
03413     Notes:      Override this method to provide handling for your special commands.
03414                 Call the base class if you don't recognise the command, so that it can
03415                 handle standard commands.
03416 
03417                 The base class handles all of these (maybe more - see the base class help)
03418                     Properties, Sort, Find;
03419                     New, Edit, Delete, Redefine; (it calls ApplyAction as appropriate)
03420                     NextGroup, PrevGroup, FoldGroup, UnfoldGroup;
03421 
03422 ********************************************************************************************/
03423 
03424 void LayerSGallery::DoCommand(StringBase *CommandID)
03425 {
03426     if (*CommandID == SGCmd_Copy)
03427         DoCopyLayer();
03428     else if (*CommandID == SGCmd_New)
03429         DoCreateNewItem();
03430     else if (*CommandID == SGCmd_Delete)
03431     {
03432         if (PrepareToDelete())
03433             DoDeleteSelection();
03434     }
03435     else if (*CommandID == SGCmd_Properties)
03436         DoLayerProperties();
03437     else if (*CommandID == SGCmd_Create)
03438         DoCreateGuideLayer();
03439 
03440     // Don't call the base class 'cos we don't want any other commands
03441 }
03442 
03443 /********************************************************************************************
03444 
03445 >   BOOL LayerSGallery::CloseLayerGallery()
03446 
03447     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03448     Created:    21/10/97
03449     Inputs:     -
03450     Returns:    TRUE if sucessful, else FALSE.
03451     
03452 ********************************************************************************************/
03453 
03454 BOOL LayerSGallery::CloseLayerGallery()
03455 {
03456     SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_LAYERSGALLERY));
03457 
03458     // Ensure a valid ptr.
03459     if (pSuperGallery == NULL)
03460         return FALSE;
03461     
03462     if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(LayerSGallery))
03463     {
03464 PORTNOTE("galleries", "Disabled frame gallery")
03465 #ifndef EXCLUDE_FROM_XARALX
03466         GIFAnimationPropertyTabs::SetFrameGalleryOpen(FALSE);
03467 #endif
03468         // Toggle the visible state of the gallery window
03469         pSuperGallery->SetVisibility( FALSE );
03470     }
03471     else
03472     {
03473         ERROR3("Got the frame gallery but it's not of the LayerSGallery class");
03474     }
03475 
03476     SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAYLAYERGALLERY), FALSE);
03477 
03478     // Everything ok.
03479     return TRUE;
03480 }
03481 
03482 /********************************************************************************************
03483 
03484 >   BOOL LayerSGallery::OpenFrameGallery()
03485 
03486     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03487     Created:    21/10/97
03488     Inputs:     -
03489     Returns:    TRUE if the document is Frame based, else FALSE.
03490 
03491 ********************************************************************************************/
03492 
03493 BOOL LayerSGallery::OpenFrameGallery()
03494 {
03495     // Find the OP. for the Layer gallery.
03496     OpDescriptor* OpDesc;
03497     OpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_DISPLAYFRAMEGALLERY);
03498 
03499     // Ensure we get a ptr to the OP.
03500     if(!OpDesc)
03501         return FALSE;
03502 
03503     // ok, now open the layergallery.
03504     OpDesc->Invoke();        
03505 
03506     // Lets go back.
03507     return TRUE;
03508 }
03509 
03510 
03511 /********************************************************************************************
03512 
03513 >   BOOL LayerSGallery::IsLayerMode()
03514 
03515     Author:     Ranbir_Rana (Xara Group Ltd) <camelotdev@xara.com>
03516     Created:    21/10/97
03517     Inputs:     Pointer to the document.
03518     Returns:    TRUE if the document is Frame based, else FALSE.
03519 
03520 ********************************************************************************************/
03521 
03522 BOOL LayerSGallery::IsLayerMode(Document* pDoc)
03523 {
03524     ERROR3IF(pDoc == NULL,"pDoc == NULL");
03525 
03526     // flag to determine the document mode.
03527     BOOL LayerMode = TRUE;
03528 
03529     // Get a ptr to the selected spread
03530     Spread* pSpread = pDoc->GetSelectedSpread();
03531 
03532     // Ensure a valid spread ptr.
03533     if(pSpread)
03534     {
03535         // Are there any frame layers?
03536         Layer* pFrameLayer = pSpread->FindFirstFrameLayer();    
03537 
03538         //If a frame layer exists, then this is an animation doc.
03539         if (pFrameLayer)
03540             LayerMode = FALSE;
03541     }
03542 
03543     // return the document mode.
03544     return LayerMode;
03545 }
03546 
03547 
03548 
03549 
03550 
03551 
03552 /********************************************************************************************
03553 
03554 >   BOOL LayerSGallery::DoMoveSelectionToActiveLayer()
03555 
03556     Author:     Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
03557     Created:    3/5/00
03558     Inputs:     -
03559     Returns:    TRUE if op exists
03560 
03561 ********************************************************************************************/
03562 BOOL LayerSGallery::DoMoveSelectionToActiveLayer()
03563 {
03564     // Find the OP. for the Layer gallery.
03565     OpDescriptor* OpDesc;
03566     OpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_MOVE_SEL_TO_ACTIVE_LAYER);
03567 
03568     // Ensure we get a ptr to the OP.
03569     if(!OpDesc)
03570         return FALSE;
03571 
03572     // ok, now open the layergallery.
03573     OpDesc->Invoke();        
03574 
03575     // Lets go back.
03576     return TRUE;
03577 }
03578 
03579 
03580 
03581 
03582 #endif // EXCLUDE_GALS

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