// $Id: sglfills.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // SGLFills.cpp - LibFills SuperGallery classes #include "camtypes.h" #include "sglfills.h" //#include "app.h" // For GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED] //#include "galstr.h" //#include "pathname.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "sginit.h" #include "sglfills.h" // This .cpp file's corresponding header #include "sglib.h" #include "sgmenu.h" //#include "thumb.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "thumbmsg.h" //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "grnddib.h" //#include "galres.h" //#include "richard.h" #include "sgliboil.h" //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "selop.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "progress.h" #include "camelot.h" #include "dragmgr.h" //#include "viewrc.h" // FOR _R(IDC_CANDROPONPAGE) //#include "resource.h" // FOR _R(IDC_CANDROPONPAGE) //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodebmp.h" // For LibraryGallery #include "sglbase.h" //#include "sgscan.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "sgscanf.h" //#include "richard2.h" #include "keypress.h" #include "backgrnd.h" // OpBackground #include #include "inetop.h" #include "helpuser.h" //#include "xshelpid.h" //#include "helppath.h" #include "resdll.h" // Implement the dynamic class bits... CC_IMPLEMENT_DYNCREATE(LibFillsSGallery, LibraryGallery) CC_IMPLEMENT_DYNCREATE(OpDisplayLibFillsGallery, Operation) CC_IMPLEMENT_DYNCREATE(SGFillsItem, SGLibDisplayItem) CC_IMPLEMENT_DYNCREATE(GalleryFillsDragInfo, BitmapDragInformation) CC_IMPLEMENT_DYNAMIC(SGFillsDragTarget, SGListDragTarget) // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW using namespace InetUtils; // Static variables #ifdef _DEBUG //String_256 LibFillsSGallery::DefaultLibraryPath = TEXT("\\\\deepthought\\camelotcd\\cd\\fills"); //String_256 LibFillsSGallery::DefaultLibraryPath = TEXT("\\\\jimpc\\corelxra\\fills"); String_256 LibFillsSGallery::DefaultLibraryPath = TEXT("D:\\fills"); #else String_256 LibFillsSGallery::DefaultLibraryPath = TEXT("D:\\fills"); #endif // display mode setting for ini file INT32 LibFillsSGallery::DefaultDisplayMode = 0; // For keeping the sort keys constant when next loaded (default == sort alphabetically) // 1st sort key = DefaultSortKeys & 0x8f // 2nd sort key = ((DefaultSortKeys>>8) & 0x8f) // 1st sort key reversed = ((DefaultSortKeys>>7) & 0x01)==1 // 2nd sort key reversed = ((DefaultSortKeys>>15) & 0x01)==1 // So 0 means no sorting at all // and 1 means sort the gallery alphabetically UINT32 LibFillsSGallery::DefaultSortKeys = 1; // Pointer to the gallery itself... LibFillsSGallery *LibFillsSGallery::ThisGallery = NULL; // Quiet status of gallery BOOL LibFillsSGallery::QuietStatus = FALSE; /******************************************************************************************** > LibFillsSGallery::LibFillsSGallery() Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Purpose: LibFillsSGallery default constructor ********************************************************************************************/ LibFillsSGallery::LibFillsSGallery() { LibFillsSGallery::ThisGallery = this; // Default gallery size CSize Size(((333 * 2) - 32) - 32, 256); SetGallerySize(Size); } /******************************************************************************************** > LibFillsSGallery::~LibFillsSGallery() Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Purpose: LibFillsSGallery destructor. ********************************************************************************************/ LibFillsSGallery::~LibFillsSGallery() { OpenLibFiles.DeleteAll(); // Ensure all open libraries are closed LibFillsSGallery::ThisGallery = NULL; } /******************************************************************************************** > static BOOL LibFillsSGallery::Init(void) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Returns: TRUE if the sgallery initialised successfully FALSE if it failed to initialise Purpose: ********************************************************************************************/ BOOL LibFillsSGallery::Init(void) { return(TRUE); } /******************************************************************************************** > BOOL LibFillsSGallery::PreCreate(void) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Returns: TRUE if the Gallery initialised successfully FALSE if it should not be opened due to a failure to initialise Purpose: The LibFillsSGallery PreCreate handler. This overrides the base class PreCreate function. It is called at the very beginning of the SuperGallery::Create method, before the window has been created. Notes: As this is called before the window is open, it must not attempt to touch any of the button gadgets in the window, or force redraws, etc. Also, events cannot be passed to the tree, as the tree formatting relies on knowing the window size - however, the tree will be reformatted and redrawn automatically when the window is opened - this will happen shortly. ********************************************************************************************/ BOOL LibFillsSGallery::PreCreate(void) { // If there isn't already one, create a DisplayTree if (DisplayTree == NULL) { DisplayTree = new SGDisplayRootScroll(this); // New root node, with a scrollbar if (DisplayTree == NULL) return(FALSE); } // Add the library groups to the gallery if they're not there already if(OpenLibFiles.IsEmpty()) { String_256 sLoc = DefaultLibraryPath; // Set DefaultLibraryPath to \Fills - the user might have installed // the fills to his hard disk: if(CResDll::GetExecutablePath((TCHAR*)DefaultLibraryPath)) { // Look for the resources in the main Xara X folder first String_256 LibDirName; GetLibraryDirectoryName(&LibDirName); DefaultLibraryPath += "\\"; DefaultLibraryPath += LibDirName; PathName ThisPath(DefaultLibraryPath); if(!SGLibOil::FileExists(&ThisPath)) // will also work for paths (not just paths with a filename on the end) { // Fills not on hard disk. Try the CD location if(!ScanForLocation(SGLib_Texture, NULL)) { // hard drive and CD location not found // put the original path back DefaultLibraryPath = sLoc; } } } LibraryGallery::AddLibraryGroups(SGLib_Texture, &DefaultLibraryPath); } // Use last time's display mode DisplayMode = LibFillsSGallery::DefaultDisplayMode; return TRUE; } /******************************************************************************************** > void LibFillsSGallery::SortGallery(void) Author: Richard_Millican (Xara Group Ltd) Created: 2/5/95 Inputs: Returns: Purpose: Sorts the contents of the gallery in an alphabetical fashion, whilst keeping the old sort key status... Notes: SeeAlso: ********************************************************************************************/ void LibFillsSGallery::SortGallery(void) { LibraryGallery::SortGallery(); } /******************************************************************************************** > BOOL LibFillsSGallery::BrowseClicked(void) Author: Richard_Millican (Xara Group Ltd) Created: 2/5/95 Inputs: Returns: TRUE if the gallery has new stuff in it (FALSE if cancel clicked, etc)... Purpose: Pops up the browse box and lets a new location be set for the data ********************************************************************************************/ BOOL LibFillsSGallery::BrowseClicked(void) { return (LibraryGallery::BrowseClicked(&DefaultLibraryPath, SGLib_Texture, _R(IDS_REMOVE_OLD_GOUPS_FILLS))); } /******************************************************************************************** > virtual BOOL LibFillsSGallery::CanCreateIndexes(void) Author: Richard_Millican (Xara Group Ltd) Created: 18/12/95 Returns: TRUE to if index generation is possible Purpose: To determine if this gallery can generate indexes or not ********************************************************************************************/ BOOL LibFillsSGallery::CanCreateIndexes(void) { return TRUE; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::GetDefaults(String_256 *DefaultIndex, String_256 *IndexDesc, SGLibType *Type) Author: Richard_Millican (Xara Group Ltd) Created: 18/12/95 Outputs: DefaultIndex - The filename for the default index file (Xaraclip.txt) IndexDesc - Description of the index / gallery (Clipart) Type - Default library type associated with this gallery Returns: TRUE if this was overridden successfully Purpose: To determine various library gallery default properties ********************************************************************************************/ BOOL LibFillsSGallery::GetDefaults(String_256 *DefaultIndex, String_256 *IndexDesc, SGLibType *Type) { if(DefaultIndex != NULL) *DefaultIndex = _R(IDS_LIBRARIES_FILLS_FILENAME); // "XaraText.txt"; if(IndexDesc != NULL) *IndexDesc = _R(IDS_LIBRARIES_FILLS_DESC); // "Fills"; if(Type != NULL) *Type = SGLib_Texture; return TRUE; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::GetLibraryDirectoryName(String_256 *LibDirName) Author: Richard_Millican (Xara Group Ltd) Created: 19/12/95 Outputs: LibDirName - Returns the Default directory (on the clipart CD) for the gallery Returns: TRUE if overridden and directory obtained... Purpose: Get the default CD directory name for the gallery ********************************************************************************************/ BOOL LibFillsSGallery::GetLibraryDirectoryName(String_256 *LibDirName) { LibDirName->MakeMsg(_R(IDS_LIBRARIES_FILLS_DIRNAME)); return TRUE; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::GetQuietStatus(void) Author: Richard_Millican (Xara Group Ltd) Created: 19/12/95 Returns: TRUE if Quiet has been pressed (SetQuiet status called with TRUE) Purpose: Get the Quiet status of the gallery ********************************************************************************************/ BOOL LibFillsSGallery::GetQuietStatus(void) { return LibFillsSGallery::QuietStatus; } /******************************************************************************************** > virtual void LibFillsSGallery::SetQuietStatus(BOOL Status) Author: Richard_Millican (Xara Group Ltd) Created: 19/12/95 Inputs: Status - Set to TRUE and call if Quiet has just been pressed on an 'adding indexes' dialog Purpose: Set the Quiet status of the gallery ********************************************************************************************/ void LibFillsSGallery::SetQuietStatus(BOOL Status) { LibFillsSGallery::QuietStatus = Status; } /*********************************************************************************************** > virtual BOOL LibFillsSGallery::ScanForLocation(SGLibType Type, StringBase *Result = NULL); Author: Richard_Millican (Xara Group Ltd) Created: 19/12/95 Inputs: Type of library to scan for Outputs: (We assume the library static strings exist and use them - bit yucky) If a Result pointer if given then we copy this into there as well.. Returns: FALSE if it fails; TRUE if we got a path Purpose: Searches all the drives for a CDROM drive. If it finds the Camelot CD mount here at Xara HQ, we point to that instead. Notes: ***********************************************************************************************/ BOOL LibFillsSGallery::ScanForLocation(SGLibType Type, StringBase *Result) { #ifndef STANDALONE // Search for a CD ROM drive String_256 DriveName; BOOL AreWeXara = FALSE; String_256 XaraDrive; BOOL Adjust = KeyPress::IsAdjustPressed(); #ifndef _DEBUG Adjust = FALSE; #endif if(SGLibOil::LocateCDROMDrive(this, Type, &DriveName, &AreWeXara, &XaraDrive, Adjust)) { if(AreWeXara) DriveName = XaraDrive; switch(Type) { case SGLib_Texture: case SGLib_Fractal: LibFillsSGallery::DefaultLibraryPath = DriveName; #ifdef _DEBUG if(Adjust) { LibFillsSGallery::DefaultLibraryPath += TEXT("Graphics\\Fills"); } else #endif { String_256 LibDirName; GetLibraryDirectoryName(&LibDirName); LibFillsSGallery::DefaultLibraryPath += LibDirName; } if(Result) *Result = LibFillsSGallery::DefaultLibraryPath; return TRUE; } } #endif return FALSE; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::CheckForIndexMatch(StringBase *Txt) Author: Richard_Millican (Xara Group Ltd) Created: 18/12/95 Inputs: Kind - Last column entry in the index.txt file (" T") Returns: TRUE if this signifies the gallery in question... Purpose: To see whether we should add this line of the index.txt file to this gallery ********************************************************************************************/ BOOL LibFillsSGallery::CheckForIndexMatch(StringBase *Txt) { BOOL Match = FALSE; // Textures (fills) if(((Txt->Sub(String_8("T"))!=-1) || (Txt->Sub(String_8("t"))!=-1)) ) Match = TRUE; return Match; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::ApplyAction(SGActionType Action) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: Action - Indicates what action to apply Returns: TRUE to indicate successful handling of the action, or FALSE to indicate failure Purpose: Applies certain conventional gallery actions (usually associated with gallery buttons, for new, edit, delete, etc) SeeAlso: SGActionType ********************************************************************************************/ BOOL LibFillsSGallery::ApplyAction(SGActionType Action) { // No display tree? Better forget about it then! if (DisplayTree == NULL) return(FALSE); // Now, process the action TO DO! - see Colour gallery for examples switch(Action) { case SGACTION_APPLYADJUST: // Drop through to SGACTION_APPLY handler case SGACTION_APPLY: // Import the current selection and apply it as a fill if(Document::GetSelected() == NULL) return FALSE; if(!FillUsingFillGallerySelection(ApplyToObject)) return FALSE; break; case SGACTION_SETOPTIONS: // Set values in the options dialogue as it is opened { if (CurrentOptionsDlg == NULL) return(FALSE); CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_LARGE)); // 0 CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_FULLINFO)); // 1 CurrentOptionsDlg->AddDisplayModeName(_R(IDS_GALLERYDM_SMALL)); // 2 } break; case SGACTION_SETSORTMODE: { if (CurrentSortDlg == NULL) return(FALSE); CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_NAME)); CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_MEMORY)); CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_NAMELENGTH)); CurrentSortDlg->AddSortKeyName(_R(IDS_SORTBY_FILETYPE)); } break; case SGACTION_DISPLAYMODECHANGED: if(DisplayMode >= 3) DisplayMode = 0; DefaultDisplayMode = DisplayMode; InvalidateCachedFormat(); ReformatAndRedrawIfNecessary(); break; default: return(SuperGallery::ApplyAction(Action)); break; } return(TRUE); } /******************************************************************************************** > virtual MsgResult LibFillsSGallery::Message(Msg* Message) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: Message - The message to handle Purpose: A standard message handler, really. Notes: Any messages that this does not handle must be passed down to the SuperGallery base class message handler. NOTE WELL that the SuperGallery base class handler does some funky things for us - see SuperGallery::Message - such as deleting our display subtree for any document which dies (which, uncannily, would explain why they go away like that when you close documents ;-), and shading the gallery when there are no documents present. [To override this behaviour in these cases, you should respond to the message, and return OK rather than calling the base class message handler] SeeAlso: SuperGallery::Message ********************************************************************************************/ MsgResult LibFillsSGallery::Message(Msg* Message) { // Added by Craig Hamilton 18/1/01. static HANDLE handle = NULL; CString mutexName = "autorunMutex"; // End added. // If we have no displaytree, then we have not been shown, or something terrible has // happened, so we don't bother handling any of these messages. if (DisplayTree == NULL) return(LibraryGallery::Message(Message)); KernelBitmap *SelectedBitmap = NULL; if (IS_OUR_DIALOG_MSG(Message)) { DialogMsg* Msg = (DialogMsg*)Message; switch (Msg->DlgMsg) { case DIM_CREATE: // Added by Craig Hamilton 18/1/01. // This and the section of code of the same date in the DIM_CANCEL handler below // deal with the creation and destruction of a kernel object that is recognised by // the autorun. If this object exists then the autorun does not run. This is so // that the user can enter their resources cd while the gallery is open and not be // annoyed by the autorun appearing. handle = CreateMutex(NULL,TRUE,mutexName); // End added. SGInit::UpdateGalleryButton(OPTOKEN_DISPLAYFILLSGALLERY, TRUE); LibFillsSGallery::ThisGallery->GalleryAboutToReOpen(); break; case DIM_CANCEL: // Added by Craig Hamilton 18/1/01. if(handle != NULL) { CloseHandle(handle); } // End added. SGInit::UpdateGalleryButton(OPTOKEN_DISPLAYFILLSGALLERY, FALSE); // Flush the thumbnail cache BROADCAST_TO_CLASS(ThumbMessage(ThumbMessage::ThumbState::KILLCACHE, SGLib_Texture), DialogOp); BROADCAST_TO_CLASS(ThumbMessage(ThumbMessage::ThumbState::KILLCACHE, SGLib_Fractal), DialogOp); GalleryAboutToClose(); break; case DIM_LFT_BN_CLICKED: switch (Msg->GadgetID) { case _R(IDC_LIBGAL_OPEN): if(Document::GetSelected() != NULL) FillUsingFillGallerySelection(AddToPage); break; case _R(IDC_LIBGAL_IMPORT): FillUsingFillGallerySelection(AddToPage); break; case _R(IDC_LIBGAL_BROWSE): case _R(IDC_LIBGAL_ADD_FILLS): BrowseClicked(); break; case _R(IDC_BMPGAL_FILL): if(!FillUsingFillGallerySelection(ApplyToObject)) { return(SuperGallery::Message(Message)); } break; case _R(IDC_BMPGAL_TEXTURE): if(Document::GetSelected() != NULL) if(!FillUsingFillGallerySelection(ApplyToObjectAsTransp)) { return(SuperGallery::Message(Message)); } break; case _R(IDC_BMPGAL_BACKGROUND): if(Document::GetSelected() != NULL) if(!FillUsingFillGallerySelection(SetBackground)) { return(SuperGallery::Message(Message)); } break; case _R(IDC_BMPGAL_SAVE): #ifdef _DEBUG { SGDisplayNode *Item = DisplayTree->FindNextSelectedItem(NULL); if(Item != NULL && Item->IsKindOf(CC_RUNTIME_CLASS(SGLibDisplayItem))) { SGLibDisplayItem *LibItem = (SGLibDisplayItem *)Item; Library *Parent = LibItem->GetParentLibrary(); if(Parent != NULL) { PathName *Source = Parent->ReturnIndexLocation(); PathName Dest(*Source); Dest.SetType((String_256)"BAK"); SGLibOil::FileCopy(Source, &Dest); Parent->SaveIndexInDisplayedOrder(Source, TRUE); } } } #endif break; case _R(IDC_GALLERY_HELP): // Show help page HelpUserTopic(_R(IDS_HELPPATH_Gallery_Fill)); break; default: break; } } } else if (MESSAGE_IS_A(Message, DocChangingMsg)) { DocChangingMsg *Msg = (DocChangingMsg *) Message; switch (Msg->State) { case DocChangingMsg::DocState::SELCHANGED: if (Msg->pNewDoc == NULL) { // There is no selected doc - this can only mean there are no docs // at all, so we had better shade the gallery DoShadeGallery(TRUE); SuperGallery::ShadeGallery(TRUE); } else { // Possibly a new document DoShadeGallery(FALSE); SuperGallery::ShadeGallery(FALSE); SelectionHasChanged(); } break; } } else if (MESSAGE_IS_A(Message, ThumbMessage) && DisplayTree != NULL) { ThumbMessage *Msg = (ThumbMessage *) Message; // If a library Thumb message comes around, flush the redraw stuff, etc if(Msg->State == ThumbMessage::ThumbState::CACHESIZECHANGED) { FlushBackgroundRedraws(); ForceRedrawOfList(); } } return(LibraryGallery::Message(Message)); } /******************************************************************************************** > void LibFillsSGallery::SelectionHasChanged(void) Author: Richard_Millican (Xara Group Ltd) (based on Jason code) Created: 28/3/95 Purpose: To inform the gallery that the selection has changed in some way. We need to grey different buttons on different occasions Notes: ********************************************************************************************/ void LibFillsSGallery::SelectionHasChanged(void) { if (DisplayTree == NULL) return; // As we now allow the gallery to be closed and all the groups to remain, we must now // also check to see if the gallery is visible i.e. open or not. If not then get out now. // Required as SetStringGadgetValue will ERROR and memory leak if called when dialog closed. if (!IsVisible()) return; INT32 Count = DisplayTree->GetSelectedItemCount(); BOOL Documents = (Document::GetSelected() != NULL); // Set up button states // Enable the import button if there is a selection and valid documents EnableGadget(_R(IDC_LIBGAL_IMPORT), (Count > 0) && Documents); String_256 strCommand, strDummy; BOOL bEnable = Count == 1 && Documents; // Import button strCommand = SGCmd_Import; EnableGadget(_R(IDC_LIBGAL_IMPORT), bEnable && !((GetCommandState(&strCommand, &strDummy)).Greyed)); // Fill button strCommand = SGCmd_Fill; EnableGadget(_R(IDC_BMPGAL_FILL), bEnable && !((GetCommandState(&strCommand, &strDummy)).Greyed)); // Transp button strCommand = SGCmd_Transp; EnableGadget(_R(IDC_BMPGAL_TEXTURE), bEnable && !((GetCommandState(&strCommand, &strDummy)).Greyed)); // Background button strCommand = SGCmd_SetBackground; EnableGadget(_R(IDC_BMPGAL_BACKGROUND), bEnable && !((GetCommandState(&strCommand, &strDummy)).Greyed)); EnableGadget(_R(IDC_LIBGAL_ADD_FILLS), TRUE); LibraryGallery::SelectionHasChanged(); } /******************************************************************************************** > void LibFillsSGallery::DoShadeGallery(BOOL ShadeIt) Author: Richard_Millican (Xara Group Ltd) (based on Jason code) Created: 28/3/95 Purpose: To un-grey the options... button when there are no docs Notes: ********************************************************************************************/ void LibFillsSGallery::DoShadeGallery(BOOL ShadeIt) { if (DisplayTree == NULL) return; // Keep this here always EnableGadget(_R(IDC_GALLERY_MENU), TRUE); EnableGadget(_R(IDC_LIBGAL_IMPORT), !ShadeIt); EnableGadget(_R(IDC_BMPGAL_FILL), !ShadeIt); EnableGadget(_R(IDC_BMPGAL_TEXTURE), !ShadeIt); EnableGadget(_R(IDC_BMPGAL_BACKGROUND), !ShadeIt); EnableGadget(_R(IDC_LIBGAL_ADD_FILLS), TRUE); LibraryGallery::DoShadeGallery(ShadeIt); } /******************************************************************************************** > BOOL LibFillsSGallery::FillUsingFillGallerySelection(FillTypeEnum FillType) Author: Jonathan_Payne (Xara Group Ltd) Created: 20/9/2000 Inputs: FillType - The type of fill required (see def. of FillTypeEnum) Returns: TRUE if things went OK, false otherwise Purpose: To import a fill into camelot, then apply it in the mannor selected SeeAlso: OnPageDrop ********************************************************************************************/ bool LibFillsSGallery::FillUsingFillGallerySelection(FillTypeEnum FillType) { PathName FileName; UINT32 TagObjectToFill = 0; // used for ApplyToObject and ApplyToObjectAsTransp // when downloading a fill if (GetSelectedItemCount() != 1 && FillType != AddToPage) { TRACEUSER( "Jonathan", _T("Fills: FillUsingGallerySelection failing due to multiple selection\n")); return false; } SGLibDisplayItem *FillItem = static_cast(DisplayTree->FindNextSelectedItem()); if (!FillItem->GetFileName(&FileName)) return false; if (!FileName.IsValid(FileName.GetPath())) { ERROR3("Filename is invalid"); return false; } bool NeedToDownload; if (_taccess(FileName.GetPath(), 0) == -1) NeedToDownload = true; else NeedToDownload = false; if (FillType == ApplyToObject || FillType == ApplyToObjectAsTransp) { SelRange* Sel = GetApplication()->FindSelection(); if (Sel==0) { ERROR3("Can't find SelRange!"); return false; } if (NeedToDownload) { Node *NodeToFill = Sel->FindFirst(); if (Sel->FindNext(NodeToFill) != 0) { // If mulitple objects are selected, saving the tag of just one object is not // going to do much good so for now we just give up in this case InformError(_R(IDE_SGLFILLS_NOMULTI_DL_FILL)); return false; } if (NodeToFill) TagObjectToFill = NodeToFill->GetTag(); else { // No node selected. This means the user has pressed fill from the gallery // with no selection, intending to set the default fill of the document. To // do this we set TagObjectToFill to zero which results in TagObjectValid not // being set. We do not have to use this logic in the case where the fill is // already downloaded as the ApplyFill(...) stuff just uses the current selection // (or the lack of current selection). TagObjectToFill = 0; } } } // Calculate where to put an imported object DocCoord DropPos; DocRect PageRect; Spread *s; if ((s = Document::GetSelectedSpread()) != 0) { if (s->GetPagesRect(&PageRect)) DropPos = PageRect.Centre(); else return false; } else return false; if (!NeedToDownload) // Don't need to download the fill { TRACEUSER( "Jonathan", _T("Fills: File in cache\n")); OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpBitmapImport)); if (pOpDesc != 0) { BitmapImportParam Param; Param.File = &FileName; Param.Result = TRUE; Param.pTargetDoc = Document::GetSelected(); Param.FillType = FillType; Param.pSpread = Document::GetSelectedSpread(); Param.DropPos = DropPos; Param.TagObjectValid = false; Param.pObjectValid = false; // Do it... pOpDesc->Invoke((OpParam *) &Param); if (!Param.Result) { ERROR3("Problem importing file from cache"); return false; } } } else // Need to download the fill { TRACEUSER( "Jonathan", _T("Fills: File not in cache : downloading\n")); OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpAsynchBitmapImport)); if (pOpDesc != 0) { AsynchBitmapImportParam* Param = new AsynchBitmapImportParam; if (!Param) return false; Library* pLibrary = FillItem->GetParentLibrary(); String_256 strFileURL = FileName.GetPath(); pLibrary->LocalPath2URL(&strFileURL); Param->file = FileName; Param->pTargetDoc = Document::GetSelected(); Param->strURL = strFileURL; String_256 strDescription; FillItem->GetNameText(&strDescription); Param->strDescription = _T("'"); Param->strDescription += strDescription; Param->strDescription += _T("'"); Param->type = TYPE_FILL; Param->FillType = FillType; Param->priority = AsynchDownload::PRIORITY_HIGH; Param->pSpread = Document::GetSelectedSpread(); Param->DropPos = DropPos; Param->TagObjectToFill = TagObjectToFill; Param->pObjectValid = false; // If TagObjectToFill == 0, don't set pObjectValid or TagObjectValid so // ApplyFill(...) just applies the fill to nothing (except if the user has // changed the selection during the download, in which case that object will // get filled - bit bad, but that is a very rare case). if (TagObjectToFill) Param->TagObjectValid = true; else Param->TagObjectValid = false; // Do it... pOpDesc->Invoke((OpParam *) Param); } } return true; } /******************************************************************************************** > virtual SGDisplayItem *LibFillsSGallery::AddLibraryItem(SGDisplayGroup *LibraryGroup, Library *ParentLib, LibraryIndex ItemIndex) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: LibraryGroup - The group to add the item into ParentLib - (For cross checking inputs) the library you allege the above group is for. ItemIndex - The Library generated index for this item Returns: NULL, or a pointer to the created item Purpose: Called by the Library class to create a display item for every item in a newly-scanned library file. It is essentially a callback to the gallery which requested that the library be scanned. Notes: This method MUST BE OVERRIDDEN by the derived gallery that opens the library, in order to create appropriate SGDisplayItem-derived nodes for the things in the library (e.g. a Fills library gallery will have to create items that display Fills thumbnails) SeeAlso: SuperGallery::AddLibraryGroup; SuperGallery::RemoveLibraryGroup ********************************************************************************************/ SGDisplayItem *LibFillsSGallery::AddLibraryItem(SGDisplayGroup *LibraryGroup, Library *ParentLib, LibraryIndex ItemIndex, BOOL bNew) { ERROR3IF(LibraryGroup == NULL || ParentLib == NULL, "LibFillsSGallery::AddLibraryItem - NULL params are illegal"); ERROR3IF(LibraryGroup->GetParentLibrary() != ParentLib, "LibFillsSGallery::AddLibraryitem - The DisplayGroup is not for the same library!"); // Create a Fills library item SGFillsItem *NewItem = new SGFillsItem(ItemIndex, bNew); // Alphabetic add... /* SGSortKey SortKeys[MaxSGSortKeys]; for (INT32 i = 0; i < MaxSGSortKeys; i++) { SortKeys[i].SortKey = 0; SortKeys[i].Reversed = FALSE; } SortKeys[0].SortKey = 1;*/ if (NewItem != NULL) LibraryGroup->AddItem(NewItem/*, (SGSortKey *)SortKeys*/); return(NewItem); } /******************************************************************************************** > virtual BOOL LibFillsSGallery::CanSearchKeywords(void) Author: Richard_Millican (Xara Group Ltd) Created: 30/3/95 Returns: TRUE Purpose: Used to determine if this type of gallery supports keyword searching. This one does ********************************************************************************************/ BOOL LibFillsSGallery::CanSearchKeywords(void) { return(TRUE); } /******************************************************************************************** > virtual void LibFillsSGallery::HandleDragStart(DragMessage *DragMsg) Author: Will_Cowling (Xara Group Ltd) Created: 25/3/95 Inputs: DragMsg - The DRAGSTARTED message that we've just recieved, indicating the type of drag being started Purpose: Checks a DragMessage to see if it is a colour drag. If it is, then it creates a drag target for this gallerys listbox. Notes: Overrides the default base-class action. Calls down to the base class if it is not a colour drag, so that dragging of gallery groups is allowed ********************************************************************************************/ void LibFillsSGallery::HandleDragStart(DragMessage *DragMsg) { // If it's a bitmap drag, add a target for our window. If not, let the base class // have a look at it (to see if it is a gallery item being dragged) if (DragMsg->pInfo->IsKindOf(CC_RUNTIME_CLASS(GalleryFillsDragInfo))) SGFillsDragTarget *NewTarget = new SGFillsDragTarget(this, GetListGadgetID()); else SuperGallery::HandleDragStart(DragMsg); } /******************************************************************************************** > virtual void LibFillsSGallery::WorkOutSectionName(String_256 *Section); Author: Richard_Millican (Xara Group Ltd) Created: 28/5/95 Outputs: Section - String used to return the section name Purpose: Returns the section name to use in the grm file ********************************************************************************************/ void LibFillsSGallery::WorkOutSectionName(String_256 *Section) { if(Section) *Section = _R(IDS_SGLFILLS_SECTION_NAME); // "FillsGallery"; } /******************************************************************************************** > virtual BOOL LibFillsSGallery::InitMenuCommands(void) Author: Jason_Williams (Xara Group Ltd) Created: 18/9/95 Returns: TRUE for success Purpose: Initialises any menu commands that this gallery needs. Notes: Will only create the menu commands once - further calls in the future will return TRUE immediately wihtout doing anything. ********************************************************************************************/ BOOL LibFillsSGallery::InitMenuCommands(void) { static BOOL MenusInitialised = FALSE; BOOL ok = TRUE; if (!MenusInitialised) { // Initialise menu command Ops // "Standard" entries for options menu ok = ok && InitMenuCommand((StringBase *) &SGCmd_Find, _R(IDS_SGMENU_FIND)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Sort, _R(IDS_SGMENU_SORT)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Properties, _R(IDS_SGMENU_PROPERTIES)); // "Special" entries for options menu ok = ok && InitMenuCommand((StringBase *) &SGCmd_Add, _R(IDS_SGMENU_ADDFILL)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_EmptyFillsCache, _R(IDS_SGMENU_EMPTYFILLCACHE)); // "Special" entries for over-list menu ok = ok && InitMenuCommand((StringBase *) &SGCmd_Import, _R(IDS_SGMENU_IMPORT)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Fill, _R(IDS_SGMENU_FILL)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Transp, _R(IDS_SGMENU_TRANSP)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_SetBackground, _R(IDS_SGMENU_SETBACKGROUND)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Download, _R(IDS_SGMENU_DOWNLOAD)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Remove, _R(IDS_SGMENU_REMOVE)); // "Standard" commands for over-list menu ok = ok && InitMenuCommand((StringBase *) &SGCmd_FoldGroup, _R(IDS_SGMENU_FOLD)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_UnfoldGroup, _R(IDS_SGMENU_UNFOLD)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_NextGroup, _R(IDS_SGMENU_NEXTGROUP)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_PrevGroup, _R(IDS_SGMENU_PREVGROUP)); MenusInitialised = TRUE; } return(ok); } /******************************************************************************************** > virtual BOOL LibFillsSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID) Author: Jason_Williams (Xara Group Ltd) Created: 15/9/95 Inputs: TheMenu - The menu to add commands to MenuID - The type of menu (over-list or from-options-button) to create Returns: TRUE if it succeeded Purpose: To build a menu of commands to be popped up over the gallery. Notes: Override this method to stop the default menus being built ********************************************************************************************/ BOOL LibFillsSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID) { BOOL ok = TRUE; if (MenuID == SGMENU_OPTIONS) { // Options menu ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Add); // With separator ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_EmptyFillsCache, TRUE); // With separator ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Find); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Sort); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Properties); } else { // Over-list menu ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Import); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Fill); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Transp,TRUE); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_Remove, TRUE); // With separator ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_SetBackground,TRUE); SGDisplayGroup *TheGroup = FindCommandGroup(); // Fold or unfold as appropriate if (TheGroup == NULL || !TheGroup->Flags.Folded) ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_FoldGroup); else ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_UnfoldGroup); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_PrevGroup); ok = ok && AddCommand(TheMenu, (StringBase *) &SGCmd_NextGroup); } return(ok); } /******************************************************************************************** > virtual OpState LibFillsSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason) Author: Jason_Williams (Xara Group Ltd) Created: 15/9/95 Inputs: CommandID - TheString ID of the command Outputs: ShadeReason - If you return (OpState.Greyed == TRUE) then this should be filled ion with the reason that the item is shaded/greyed. Returns: An OpState indicating the current menu item state. Purpose: To determine the state of a given menu item. This method is an exact parallel to an Op's GetState method (in fact, it is called by an Op's GetState) Notes: Override this method to provide state info for your special commands Call the base class for unknown commands to allow it to handle them for you The base class handles all of these (maybe more - see the base class help) Properties, Sort, Find; New, Edit, Delete, Redefine; NextGroup, PrevGroup, FoldGroup, UnfoldGroup; ********************************************************************************************/ OpState LibFillsSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason) { TRACEUSER( "Jonathan", _T("Fills::GetCommandState called for ")); TRACEUSER("Jonathan", *CommandID); TRACEUSER( "Jonathan", _T("\n")); OpState State; if (*CommandID == SGCmd_Add) // --- Add (always available) { return(State); } else if (*CommandID == SGCmd_EmptyFillsCache) { if (m_bDiscardWebFolders) State.Greyed = TRUE; return (State); } else if (*CommandID == SGCmd_Fill || *CommandID == SGCmd_Transp || // --- Fill/Transp/Set Background/Import *CommandID == SGCmd_SetBackground || *CommandID == SGCmd_Import) { if (GetSelectedItemCount() != 1) { State.Greyed = TRUE; ShadeReason->MakeMsg(_R(IDS_SGSHADE_SINGLE)); } } else if (*CommandID == SGCmd_Remove) // --- Remove { if (GetSelectedGroupCount() < 1) { State.Greyed = TRUE; ShadeReason->MakeMsg(_R(IDS_SGSHADE_NOSELGROUP)); } } else return(SuperGallery::GetCommandState(CommandID, ShadeReason)); // Unknown command- pass to baseclass return(State); } /******************************************************************************************** > virtual void LibFillsSGallery::DoCommand(StringBase *CommandID) Author: Jason_Williams (Xara Group Ltd) Created: 15/9/95 Inputs: CommandID - The String ID of the command Purpose: To apply a given command when it is chosen from the menu. Notes: Override this method to provide handling for your special commands. Call the base class if you don't recognise the command, so that it can handle standard commands. The base class handles all of these (maybe more - see the base class help) Properties, Sort, Find; New, Edit, Delete, Redefine; (it calls ApplyAction as appropriate) NextGroup, PrevGroup, FoldGroup, UnfoldGroup; ********************************************************************************************/ void LibFillsSGallery::DoCommand(StringBase *CommandID) { if (*CommandID == SGCmd_Import) // --- Import { if (Document::GetSelected() != NULL) FillUsingFillGallerySelection(AddToPage); } else if (*CommandID == SGCmd_Fill) // --- Fill { if (Document::GetSelected() != NULL) FillUsingFillGallerySelection(ApplyToObject); } else if (*CommandID == SGCmd_EmptyFillsCache) { RemoveWebFolders(SGLib_Fractal); } else if (*CommandID == SGCmd_Transp) // --- Transp { if (Document::GetSelected() != NULL) FillUsingFillGallerySelection(ApplyToObjectAsTransp); } else if (*CommandID == SGCmd_Add) // --- Add fills BrowseClicked(); else if (*CommandID == SGCmd_Remove) // --- Remove { RemoveSelectedLibraries(TRUE); UpdateGRMFile(); } else if (*CommandID == SGCmd_SetBackground) // --- Set background { if (Document::GetSelected() != NULL) FillUsingFillGallerySelection(SetBackground); } else SuperGallery::DoCommand(CommandID); // Unknown command- pass to the base class } /*********************************************************************************************** > virtual SGDisplayGroup *LibFillsSGallery::AddLibraryGroup(Library *LibraryToDisplay, INT32 NumItems) Author: Richard_Millican (Xara Group Ltd) Created: 20/4/95 Inputs: LibraryToDisplay - Pointer to the library associated with the group NumItems - Number of items in the group Returns: The newly created library group, or NULL if there were problems Purpose: Create a library group, as opposed to a display group Notes: ***********************************************************************************************/ SGDisplayGroup *LibFillsSGallery::AddLibraryGroup(Library *LibraryToDisplay, INT32 NumItems) { ERROR3IF(LibraryToDisplay == NULL, "LibFillsSGallery::AddLibraryGroup - NULL parameter is illegal"); if (DisplayTree == NULL) { ERROR3("LibFillsSGallery::AddLibraryGroup called before the DisplayTree was initialised!"); return(NULL); } SGLibGroup *TheGroup = (SGLibGroup *)DisplayTree->FindSubtree(this, NULL, LibraryToDisplay); if (TheGroup == NULL) { // No existing group for that library, so create a new one TheGroup = new SGLibGroup(this, NULL, LibraryToDisplay); if (TheGroup == NULL) // Failed! return(NULL); // And add it to our display tree DisplayTree->AddItem(TheGroup); } else TheGroup->DestroySubtree(FALSE); // Delete all items in the group return(TheGroup); } /******************************************************************************************** > virtual SGDisplayItem *LibFillsSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, SGDisplayGroup *DestGroup, SGDisplayItem *TargetPosition = NULL) Author: Richard_Millican (Xara Group Ltd) Created: 25/4/95 Inputs: SourceItem - The item to copy elsewhere in the tree (see below) DestGroup - The group into which the item should be inserted TargetPosition - NULL (to add the copied item to the end of the sibling list), or points to an item BEFORE which the copied item will be inserted. Returns: NULL (failed) or a pointer to the new (copied) display item Purpose: "Copies" the existing node in the tree in an appropriate fashion. This method is normally called when a gallery-organising drag completes, and it is discovered that the dragged item(s) have been dragged to a different display group. Notes: This method should be overridden by derived galleries to provide appropriate behaviour (some galleries (e.g colour) will copy the real-item that the given display-item references to the new group (document), while other galleries (layer) may just move the item after all). Note the handy InsertCopiedItem and MoveBefore/After methods which are available to take all of the hard work out of copying/moving items! See the body of this method in the source code for example pseudocode. For real code, see the Colour Gallery (sgcolour.cpp) SeeAlso: SuperGallery::InsertCopiedItem; SGDisplayItem::MoveBefore; SGDisplayItem::MoveAfter; ColourSGallery::CopyDisplayItem ********************************************************************************************/ SGDisplayItem *LibFillsSGallery::CopyDisplayItem(SGDisplayItem *SourceItem, SGDisplayGroup *DestGroup, SGDisplayItem *TargetPosition) { if(SourceItem == NULL || DestGroup == NULL) { ERROR3("LibFillsSGallery::CopyDisplayItem -> Illegal NULL param"); return NULL; } // Check if we've dragged from one group to another and warn if that's the case if(DestGroup->IsKindOf(CC_RUNTIME_CLASS(SGLibGroup))) { SGDisplayNode *SourceGroup = SourceItem->GetParent(); if((SGDisplayGroup *)SourceGroup != DestGroup) { // "Can't move library fills between groups." InformError(_R(IDS_FILLS_BETWEEN_GROUPS), _R(IDS_OK)); Error::ClearError(); } } return(NULL); } /******************************************************************************************** > BOOL OpDisplayLibFillsGallery::Init() Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: - Outputs: - Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: OpDisplayLibFillsGallery initialiser method Errors: ERROR will be called if there was insufficient memory to allocate the operation. SeeAlso: - ********************************************************************************************/ BOOL OpDisplayLibFillsGallery::Init() { // **** TO DO **** // Ensure the IDS_ OPTOKEN_ and IDBBL_ constants are available and correct // You should really also uppercase these constant names. return (RegisterOpDescriptor( 0, _R(IDS_DISPLAY_FILLS_GALLERY), CC_RUNTIME_CLASS(OpDisplayLibFillsGallery), OPTOKEN_DISPLAYFILLSGALLERY, OpDisplayLibFillsGallery::GetState, 0, /* help ID */ _R(IDBBL_DISPLAY_FILLS_GALLERY), 0 /* bitmap ID */)); } /******************************************************************************************** > OpState OpDisplayLibFillsGallery::GetState(String_256*, OpDescriptor*) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: - Outputs: - Returns: The state of the OpDisplayLibFillsGallery operation Purpose: For finding the OpDisplayLibFillsGallery's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpDisplayLibFillsGallery::GetState(String_256* UIDescription, OpDescriptor*) { OpState OpSt; // If the gallery is currenty open, then the menu item should be ticked DialogBarOp* pDialogBarOp = FindGallery(); if (pDialogBarOp != NULL) OpSt.Ticked = pDialogBarOp->IsVisible(); // OpSt.Greyed = (Document::GetSelected() == NULL); return(OpSt); } /******************************************************************************************** > void OpDisplayLibFillsGallery::Do(OpDescriptor*) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: - Outputs: - Returns: - Purpose: Displays the LibFillss gallery Updates the button state for this Op (the button sticks down while the gallery is open) Errors: - SeeAlso: - ********************************************************************************************/ void OpDisplayLibFillsGallery::Do(OpDescriptor*) { DialogBarOp *pDialogBarOp = FindGallery(); if (pDialogBarOp != NULL) { // Toggle the visible state of the gallery window pDialogBarOp->SetVisibility( !pDialogBarOp->IsVisible() ); // And update our button state SGInit::UpdateGalleryButton(OPTOKEN_DISPLAYFILLSGALLERY, pDialogBarOp->IsVisible()); // If we're closing the gallery, flush the thumbnail caches if(pDialogBarOp->IsVisible() == FALSE) { // Flush the thumbnail cache BROADCAST_TO_CLASS(ThumbMessage(ThumbMessage::ThumbState::KILLCACHE, SGLib_Texture), DialogOp); BROADCAST_TO_CLASS(ThumbMessage(ThumbMessage::ThumbState::KILLCACHE, SGLib_Fractal), DialogOp); // Ensure all open libraries are closed and memory reclaimed when the gallery closes if(LibFillsSGallery::ThisGallery != NULL) { // Free memory, etc... LibFillsSGallery::ThisGallery->GalleryAboutToClose(); } } } End(); } /******************************************************************************************** > static DialogBarOp *OpDisplayLibFillsGallery::FindGallery(void) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Returns: NULL or a pointer to the LibFills gallery instance Purpose: Finds the LibFills gallery class instance Notes: The bars system always keeps one LibFills gallery alive for us. If one is not found, this usually indicates that it can't be found in bars.ini: Check that the 'Name' string *exactly* matches the title string given in bars.ini. Also check that bars.ini indicates the bar is of the LibFillsSGallery class ********************************************************************************************/ DialogBarOp *OpDisplayLibFillsGallery::FindGallery(void) { String_32 Name = _R(IDS_SGLFILLS_GALLERY_NAME); // "Fill gallery" DialogBarOp* pDialogBarOp = DialogBarOp::FindDialogBarOp(Name); if (pDialogBarOp != NULL) { if (pDialogBarOp->GetRuntimeClass() == CC_RUNTIME_CLASS(LibFillsSGallery)) return(pDialogBarOp); ERROR3("Got the Fills gallery but it's not of the LibFillsSGallery class"); } else { ERROR3("Can't find the Fills gallery in bars.ini!\n"); } return(NULL); } /*********************************************************************************************** > virtual LibDisplayType SGFillsItem::GetDisplayType(SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: MiscInfo - Contains a few useful bits of info that may be needed for all event types. Outputs: Returns: The display mode type to use (position of text, and size of thumb) Purpose: Return the display type to use - Fills gallery override Notes: SeeAlso: ***********************************************************************************************/ LibDisplayType SGFillsItem::GetDisplayType(SGMiscInfo *MiscInfo) { switch(MiscInfo->DisplayMode) { case 2: return LibDisplay_SmallThumbText; break; case 1: return LibDisplay_FullInfo; break; case 0: default: return LibDisplay_LargeThumbTextUnder; break; } return LibDisplay_LargeThumbTextUnder; } /*********************************************************************************************** > SGFillsItem::SGFillsItem(LibraryIndex LibraryIndexToDisplay); Author: Richard_Millican (Xara Group Ltd) Created: 23/3/95 Inputs: LibraryIndex - Offset into index file which describes this item Outputs: Returns: Purpose: Creates and initialises a new item for the Fills gallery Notes: SeeAlso: ***********************************************************************************************/ SGFillsItem::SGFillsItem(LibraryIndex LibraryIndexToDisplay, BOOL bNew) : SGLibDisplayItem(LibraryIndexToDisplay, bNew) { } /* default constructor and destructor */ SGFillsItem::SGFillsItem() { } SGFillsItem::~SGFillsItem() { } /*********************************************************************************************** Drag stuff added by Will. ***********************************************************************************************/ /*********************************************************************************************** > virtual BOOL SGFillsItem::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) Author: Jason_Williams (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: EventType - An enumerated value describing what type of event is to be processed EventInfo - A structure describing the event (may be NULL). The exact thing pointed at by this pointer depends upon the event type: MonoOn Event Thing EventInfo points at SGEVENT_FORMAT (SGFormatInfo *) SGEVENT_REDRAW (SGRedrawInfo *) SGEVENT_MOUSECLICK (SGMouseInfo *) MonoOff Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this information - they provide useful error/type checking, and hide the cast MiscInfo - always provided. Contains a few useful bits of info that may be needed for all event types. Outputs: FormatInfo is updated as appropriate Returns: TRUE if the event was handled successfully FALSE if it was not Purpose: Handles a SuperGallery DisplayTree event Notes: This overrides the pure virtual SGDisplayNode::HandleEvent method A node need not handle a specific event - if it does not handle it, it should return FALSE. Redraw and Formatting handlers should never return TRUE, as this will prevent the event from continuing through the tree. Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order to pass the event dow the tree. THIS node is a leaf-node, so it doesn't. SeeAlso: SGDisplayNode::HandleEvent ***********************************************************************************************/ BOOL SGFillsItem::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) { switch (EventType) { case SGEVENT_MOUSECLICK: { SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo); if (Mouse != NULL && FormatRect.ContainsCoord(Mouse->Position)) { INT32 XSize=0, YSize=0; if(SGLibDisplayItem::StartDrag(EventType, EventInfo, MiscInfo, &XSize, &YSize)) { GalleryFillsDragInfo *DragFill; DragFill = new GalleryFillsDragInfo(this, Mouse, MiscInfo, Mouse->MenuClick, XSize, YSize); if (DragFill != NULL) DragManagerOp::StartDrag(DragFill, GetListWindow()); else if(LibraryGallery::TmpDraggingBitmap != NULL) { delete LibraryGallery::TmpDraggingBitmap; LibraryGallery::TmpDraggingBitmap = NULL; } } return TRUE; // Claim this event - nobody else can own this click } } } return(SGLibDisplayItem::HandleEvent(EventType, EventInfo, MiscInfo)); } /******************************************************************************************** > SGFillsDragTarget::SGFillsDragTarget(DialogOp *TheDialog, CGadgetID TheGadget = NULL) Author: Will_Cowling (Xara Group Ltd) Created: 25/3/95 Inputs: TheDialog - The kernel dialog in which the target exists TheGadget - The gadget within that dialogue which is the target Purpose: Constructor ********************************************************************************************/ SGFillsDragTarget::SGFillsDragTarget(DialogOp *TheDialog, CGadgetID TheGadget) : SGListDragTarget(TheDialog, TheGadget) { ERROR3IF(!TheDialog->IsKindOf(CC_RUNTIME_CLASS(LibFillsSGallery)), "You can only use SGFillsDragTargets with LibFillsSGallery dialogues!"); } /******************************************************************************************** BOOL SGFillsDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo, OilCoord *pMousePos, KeyPress* pKeyPress) Author: Will_Cowling (Xara Group Ltd) Created: 25/3/95 Inputs: Event - Indicates what has happened pDragInfo - points to drag information describing this drag. This should be a FillsDragInformation or derivation thereof pMousePos - points to information on the current mouse position, in OIL coords pKeyPress - NULL, or if for a keypress event, keypress information Returns: TRUE to claim the event, FALSE to let it through to other targets Purpose: Event Handler for SuperGallery listitem drag events. Overrides the base class handler to enable it to sort out the node being dragged for Fills drags. ********************************************************************************************/ BOOL SGFillsDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo, OilCoord *pMousePos, KeyPress* pKeyPress) { if (!pDragInfo->IsKindOf(CC_RUNTIME_CLASS(BitmapDragInformation))) return(FALSE); SGDisplayNode *DraggedNode = NULL; BOOL IsSimpleBitmapDrag = TRUE; // This target only knows about Fill gallery items. if (IS_A(pDragInfo, GalleryFillsDragInfo)) { DraggedNode = ((GalleryFillsDragInfo *)pDragInfo)->GetDraggedFill(); IsSimpleBitmapDrag = FALSE; } if (DraggedNode != NULL) { switch(Event) { case DRAGEVENT_COMPLETED: // If the DragInfo didn't know what to do, then call our baseclass HandleDragCompleted((SuperGallery *) TargetDialog, DraggedNode, pMousePos, IsSimpleBitmapDrag); return(TRUE); case DRAGEVENT_MOUSESTOPPED: case DRAGEVENT_MOUSEMOVED: case DRAGEVENT_MOUSEIDLE: { // Specialised cursor changing code - can't drag between groups... SuperGallery *ParentGallery = (SuperGallery *) TargetDialog; if (ParentGallery != NULL && pMousePos != NULL && DraggedNode != NULL) { // Convert the OilCoords into DocCoords DocCoord MousePos(pMousePos->x, pMousePos->y); SGDisplayNode *DestNode = ParentGallery->FindNodeUnderPointer(&MousePos); if(DestNode != NULL) { SGDisplayNode *DestGroup = DestNode->GetParent(); SGDisplayNode *SourceGroup = DraggedNode->GetParent(); if(DestGroup != NULL && SourceGroup != NULL) { // We're dragging within a group - that's ok if(SourceGroup == DestGroup) return(DetermineCursorShape(ParentGallery, DraggedNode, pMousePos)); } } } } // If we're trying to drag to unimplemented areas (between groups), set the no-can-do cursor CurrentCursorID = _R(IDC_DRAGGING_COLOUR); // No-can-drop cursor shape return TRUE; } } // Otherwise, we aren't interested in the event, so we don't claim it return(FALSE); } /******************************************************************************************** > void GalleryFillsDragInfo::GalleryFillsDragInfo() Author: Will_Cowling (Xara Group Ltd) Created: 19/3/95 Purpose: Default constructor - do not call this constructor ********************************************************************************************/ GalleryFillsDragInfo::GalleryFillsDragInfo() { ERROR3("Default GalleryFillsDragInfo constructor called"); } /******************************************************************************************** > void GalleryFillsDragInfo::~GalleryFillsDragInfo() Author: Richard_Millican (Xara Group Ltd) Created: 27/4/95 Purpose: Destructor - reclaim temporary bitmap memory ********************************************************************************************/ GalleryFillsDragInfo::~GalleryFillsDragInfo() { if(LibraryGallery::TmpDraggingBitmap != NULL) { delete LibraryGallery::TmpDraggingBitmap; LibraryGallery::TmpDraggingBitmap = NULL; } } /******************************************************************************************** > GalleryFillsDragInfo::GalleryFillsDragInfo(SGFillsItem *pSourceItem, SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo, BOOL IsAdjust = FALSE, INT32 XSize = 0, INT32 YSize = 0) Author: Will_Cowling (Xara Group Ltd) Created: 19/3/95 Inputs: pSourceItem - The gallery item from which the drag originated pMouseInfo - The mouse info which made the item start the drag pMiscInfo - The MiscInfo which accompanied the mouse event IsAdjust - TRUE if this is an adjust (line-Bitmap) drag XSize - Width in pixels of bmp to drag (0 for actual size of bmp) YSize - Height in pixels of bmp to drag (0 for actual size of bmp) Purpose: Constructor ********************************************************************************************/ GalleryFillsDragInfo::GalleryFillsDragInfo(SGFillsItem *pSourceItem, SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo, BOOL IsAdjust, INT32 XSize, INT32 YSize) : BitmapDragInformation(LibraryGallery::TmpDraggingBitmap, XSize, YSize, 0, 0, IsAdjust) { SourceItem = pSourceItem; // Copy the source item pointer MouseInfo = *pMouseInfo; // Duplicate the structures (they may cease to exist MiscInfo = *pMiscInfo; // soon after the drag is started) } /******************************************************************************************** > void GalleryFillsDragInfo::OnClick(INT32 Flags,POINT Point) Author: Will_Cowling (Xara Group Ltd) Created: 19/3/95 Inputs: - Outputs: - Returns: - Purpose: This is called if a drag was attempted but never started because it was a click all along. It calls back the SourceItem SGDisplayBitmap, to get it to handle the click. Errors: - SeeAlso: - ********************************************************************************************/ void GalleryFillsDragInfo::OnClick(INT32 Flags ,POINT Point) { if (SourceItem != NULL) SourceItem->DragWasReallyAClick(&MouseInfo, &MiscInfo); } /******************************************************************************************** > void GalleryFillsDragInfo::GetCursorID(DragTarget* pDragTarget) Author: Will_Cowling (Xara Group Ltd) Created: 25/3/95 Purpose: Set cursor over this target ********************************************************************************************/ UINT32 GalleryFillsDragInfo::GetCursorID(DragTarget* pDragTarget) { if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget)) { PageDropInfo PageDropInfo; ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo); // Find the object we are over (and which bit of it) NodeRenderableInk* pObjectHit = PageDropInfo.pObjectHit; ObjectDragTarget TargetHit = PageDropInfo.TargetHit; /* // Applying fills doesn't work asynchronously, so if we don't have the file we won't let the user drop it on objects PathName fillPath; SourceItem->GetFileName(&fillPath); if (pObjectHit && _taccess(fillPath.GetPath(), 0) == -1) return _R(IDC_CANTDROP); */ // We can't apply a fill to a NodeBitmap if (pObjectHit && pObjectHit->IS_KIND_OF(NodeBitmap)) TargetHit = NO_TARGET; // Ignore NodeBitmap objects ClickModifiers ClickMods = ClickModifiers::GetClickModifiers(); BOOL IsInside = ClickMods.Constrain; if (!IsInside && pObjectHit && pObjectHit->IsCompound()) { TargetHit = MANY_TARGET; } UINT32 CanFill = IsInside ? _R(IDC_DROPINSIDEONFILL) : _R(IDC_CANDROPONFILL); switch (TargetHit) { case FILL_TARGET: case LINE_TARGET: case STARTCOL_TARGET: case ENDCOL_TARGET: case ENDCOL2_TARGET: case ENDCOL3_TARGET: case MANY_TARGET: return CanFill; case NO_TARGET: // fill gallery - drop = page fill, CTRL + drop = add bitmap return IsInside ? _R(IDC_CANFILLPAGE) : _R(IDC_CANDROPONPAGE); //return _R(IDC_CANDROPONPAGE); }; return _R(IDC_CANDROPONPAGE); } return _R(IDC_CANTDROP); } /******************************************************************************************** > virtual BOOL GalleryFillsDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget) Author: Will_Cowling (Xara Group Ltd) Created: 25/3/95 Returns: Whether String is valid Purpose: provide status line text for this target ********************************************************************************************/ BOOL GalleryFillsDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget) { ERROR2IF(TheText==NULL,FALSE,"NULL string in GetStatusLineText()"); //if (TheBitmap == NULL || TheBitmap->ActualBitmap == NULL) // return FALSE; String_256 DragString; String_256 ItemName; SourceItem->GetNameText(&ItemName); PageDropInfo PageDropInfo; NodeRenderableInk* pObjectHit = NULL; ObjectDragTarget TargetHit; if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget)) { ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo); pObjectHit = PageDropInfo.pObjectHit; TargetHit = PageDropInfo.TargetHit; } PathName fillPath; SourceItem->GetFileName(&fillPath); // "Dragging fill '#1%s'" DragString.MakeMsg(_R(IDS_FILLS_DRAGGING), (TCHAR *)ItemName); if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget)) { DragString += String_8(_R(IDS_SGDFONTS_STAT_COLON_SEP)); //" : "; String_256 ObjectDesc = _R(IDS_SGLFILLS_THIS_OBJECT); // " this object"; if (pObjectHit) { ObjectDesc = pObjectHit->Describe(FALSE); } if (pObjectHit && pObjectHit->IS_KIND_OF(NodeBitmap)) TargetHit = NO_TARGET; // Ignore NodeBitmap objects ClickModifiers ClickMods = ClickModifiers::GetClickModifiers(); BOOL IsInside = ClickMods.Constrain; if (!IsInside && pObjectHit && pObjectHit->IsCompound()) { TargetHit = MANY_TARGET; } switch (TargetHit) { case FILL_TARGET: case LINE_TARGET: case STARTCOL_TARGET: case ENDCOL_TARGET: case ENDCOL2_TARGET: case ENDCOL3_TARGET: DragString += String_64(_R(IDS_SGLFILLS_DROP_TO_APPLY)); //"Drop to apply the fill to this "; DragString += ObjectDesc; if (IsInside) DragString += String_64(_R(IDS_SGLFILLS_ALONE)); // " alone"; break; case MANY_TARGET: DragString += String_64(_R(IDS_SGLFILLS_DROP_TO_APPLY)); //"Drop to apply the fill to this "; DragString += ObjectDesc; DragString += String_64(_R(IDS_SGLFILLS_DROP_INSIDE)); // "; Press 'Control' to drop 'Inside'"; break; case NO_TARGET: { if (IsInside) { DragString += String_256(_R(IDS_DRAGBMP_DROP_SETPAGEBACKGROUND)); // "Drop to set the Bitmap fill of the page background"; } else { // + "Drop to Insert a new Bitmap object on the Page" String_64 DropToThis(_R(IDS_FILLS_INSERT_BITMAP_TO_PAGE)); DragString += DropToThis; } break; } } *TheText = DragString; return TRUE; } *TheText = DragString; return TRUE; } /******************************************************************************************** > BOOL GalleryFillsDragInfo::OnPageDrop(ViewDragTarget* pDragTarget) Author: Will_Cowling (Xara Group Ltd) Created: 19/3/95 Inputs: pDragTarget, the ViewDragTarget that we were dropped onto. Returns: TRUE, if we handled the drop. Purpose: Called when a Fill is dropped onto the page. Use pDragTarget->GetDropInfo(), to details of the drop. SeeAlso: FillUsingFillGallerySelection ********************************************************************************************/ BOOL GalleryFillsDragInfo::OnPageDrop(ViewDragTarget* pDragTarget) { enum FillTypeEnum FillType; PageDropInfo ThePageDropInfo; ((ViewDragTarget*)pDragTarget)->GetDropInfo(&ThePageDropInfo); NodeRenderableInk* pObjectHit = ThePageDropInfo.pObjectHit; PathName FileName; SGLibDisplayItem *FillItem = SourceItem; if (!FillItem->GetFileName(&FileName)) return FALSE; if (!FileName.IsValid(FileName.GetPath())) { ERROR3("LibFillsSGallery::ImportFills - Filename is invalid"); return FALSE; } BOOL NeedToDownload; if (_taccess(FileName.GetPath(), 0) == -1) NeedToDownload = TRUE; else NeedToDownload = FALSE; BOOL Constrain = KeyPress::IsConstrainPressed(); if (Constrain && !pObjectHit) FillType = SetBackground; else if (pObjectHit && !pObjectHit->IS_KIND_OF(NodeBitmap)) FillType = ApplyToObject; else FillType = AddToPage; if (!NeedToDownload) // Don't need to download the fill { TRACEUSER( "Jonathan", _T("Fills: File in cache\n")); OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpBitmapImport)); if (pOpDesc != 0) { BitmapImportParam Param; Param.File = &FileName; Param.Result = TRUE; Param.pTargetDoc = Document::GetSelected(); Param.FillType = FillType; Param.pSpread = ThePageDropInfo.pSpread; Param.DropPos = ThePageDropInfo.DropPos; Param.TagObjectValid = false; Param.pObject = pObjectHit; Param.pObjectValid = true; // Do it... pOpDesc->Invoke((OpParam *) &Param); if (!Param.Result) { ERROR3("Problem importing file from cache"); return FALSE; } } } else // Need to download the fill { TRACEUSER( "Jonathan", _T("Fills: File not in cache : downloading\n")); OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpAsynchBitmapImport)); if (pOpDesc != 0) { AsynchBitmapImportParam* Param = new AsynchBitmapImportParam; if (!Param) return FALSE; Library* pLibrary = SourceItem->GetParentLibrary(); String_256 strFileURL = FileName.GetPath(); pLibrary->LocalPath2URL(&strFileURL); Param->file = FileName; Param->pTargetDoc = Document::GetSelected(); Param->strURL = strFileURL; String_256 strDescription; SourceItem->GetNameText(&strDescription); Param->strDescription = _T("'"); Param->strDescription += strDescription; Param->strDescription += _T("'"); Param->type = TYPE_FILL; Param->FillType = FillType; Param->priority = AsynchDownload::PRIORITY_HIGH; Param->pSpread = ThePageDropInfo.pSpread; Param->DropPos = ThePageDropInfo.DropPos; Param->pObjectValid = false; if (FillType == ApplyToObject || FillType == ApplyToObjectAsTransp) { Param->TagObjectToFill = pObjectHit->GetTag(); Param->TagObjectValid = true; } // Do it... pOpDesc->Invoke((OpParam *) Param); } } return TRUE; }