sgframe.cpp

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

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