// $Id: sgname.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============================ */ // sgname.cpp - the NameGallery implementation. /* $Log: /Camelot/kernel/sgname.cpp $ * * 2 11/02/04 10:58a Alex * Support for HTML Help * * 2 16/07/99 18:06 Justinf * Now shows little circular blobs for adding sets to / subtracting sets * from the selection. * * 1 24/06/99 16:23 Justinf * Name Gallery */ #include "camtypes.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "ccdc.h" //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "grnddib.h" //#include "cxfrech.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "userattr.h" #include "tmpltatr.h" #include "grndbmp.h" //#include "wbitmap.h" #include "dragmgr.h" //#include "scrvw.h" //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "resource.h" //#include "galstr.h" //#include "galres.h" #include "sgmenu.h" //#include "barsdlgs.h" //#include "mario.h" //#include "justin3.h" //#include "richard2.h" //#include "xshelpid.h" #include "helpuser.h" #include "sginit.h" #include "sgname.h" DECLARE_SOURCE("$Revision: 1282 $"); // Implement the dynamic class bits... CC_IMPLEMENT_DYNCREATE(NameGallery, SuperGallery) CC_IMPLEMENT_DYNAMIC(SGNameItem, SGDisplayItem) CC_IMPLEMENT_DYNCREATE(OpDisplayNameGallery, Operation); CC_IMPLEMENT_DYNAMIC(GalleryNameDragInfo, BitmapDragInformation); CC_IMPLEMENT_DYNAMIC(SGNameDragTarget, SGListDragTarget); CC_IMPLEMENT_DYNCREATE(NameObjectsDlg, DialogOp) // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW /*********************************************************************************************** > SGNameItem::SGNameItem(const String_256& strName) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: NameItemToDisplay - The NameItem this item will display Purpose: SGNameItem constructor ***********************************************************************************************/ SGNameItem::SGNameItem(const String_256& strName) : m_strSetName(strName), m_eIntersect(AttributeSets::Intersect::NONE) { // TRACEUSER( "JustinF", _T("SGNameItem %s\n"), (LPCTSTR) m_strSetName); } /*********************************************************************************************** > virtual void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: FormatInfo - The formatting info from which to calculate my position/size MiscInfo - As usual, the useful misc info struct Outputs: member variable FormatRect - is returned filled in with the size/position of this NameItem item's display area. This is dependent upon the current display mode and format state. FormatInfo will be updated as a result of the formatting operation. Purpose: Shared code for NameItem items to calculate where they will appear in the grand scheme of things Notes: NameItems supply only one display mode ("full info") ***********************************************************************************************/ void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) { CalculateFormatRect(pFormatInfo, pMiscInfo, SG_InfiniteWidth, SG_DefaultSmallIcon); } /******************************************************************************************** > virtual void SGNameItem::GetNameText(String_256* pResult) Author: Justin_Flude (Xara Group Ltd) Created: 9/3/95 (base generated in sgbase.cpp) Outputs: On exit, the string pointed at by Result will contain either a blank string, or the name text associated with this item (if any) Purpose: To determine a name string for this node. Generally, this is used for a simple mechanism which searches for display items whose names match given search parameters in some way. It is also used in libraries to provide default redraw methods. Notes: **** TO DO **** Modify this method to return the correct text. You may also want to add an override for the GetFullInfoText() method if you can provide a full-info display mode. SeeAlso: SGDisplayNode::GetNameText ********************************************************************************************/ void SGNameItem::GetNameText(String_256* pResult) { ERROR3IF(pResult == 0, "SGNameItem::GetNameText: illegal null param"); *pResult = m_strSetName; } /******************************************************************************************** > virtual BOOL SGNameItem::GetBubbleHelp(DocCoord *pMousePos, String_256 *pResult) Author: Justin_Flude (Xara Group Ltd) Created: 16/4/95 Inputs: pMousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a bubble help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when bubble help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetStatusLineHelp ********************************************************************************************/ BOOL SGNameItem::GetBubbleHelp(DocCoord*, String_256* pResult) { ERROR3IF(pResult == 0, "SGNameItem::GetBubbleHelp: invalid null params"); // Work out the intersection with the user selection. AttributeSets::Intersect eState = GetDocument()->GetAttributeSets()->IntersectSelectedObj(m_strSetName); // Create the bubble help text. String_256 strName; GetNameText(&strName); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_ITEM), &String_32(_R(IDBBL_NAMEGAL_NONE) + INT32(eState)), &strName); } /******************************************************************************************** > virtual BOOL SGNameItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) Author: Justin_Flude (Xara Group Ltd) Created: 16/4/95 Inputs: pMousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a status line help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when status line help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetBubbleHelp ********************************************************************************************/ BOOL SGNameItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) { // Work out the intersection with the user selection. AttributeSets::Intersect eState = GetDocument()->GetAttributeSets()->IntersectSelectedObj(m_strSetName); // Create the bubble help text. String_256 strName; GetNameText(&strName); return pResult->MakeMsg(_R(IDS_NAMEGAL_ITEM_STATUS), &String_32(_R(IDBBL_NAMEGAL_NONE) + INT32(eState)), &strName); } /*********************************************************************************************** > virtual void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGFormatInfo* pFormatInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: RedrawInfo - The information on the kernel-rendered redraw area FormatInfo - The formatting information structure member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item Purpose: SGNameItem item redraw method - removed from the main HandleEvent method merely to make the code tidier. ***********************************************************************************************/ void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) { // Intersect the item's set with the user selection. String_256 strName; GetNameText(&strName); // Set the foreground and background colours according to whether this item is // gallery selected or not. RenderRegion* pRenderer = pRedrawInfo->Renderer; DocColour dcolForegnd, dcolBackgnd; if (Flags.Selected) { dcolForegnd = pRedrawInfo->SelForeground; dcolBackgnd = pRedrawInfo->SelBackground; } else { // Unselected items are in the 'selected' colour if the user selection includes // any of their members. dcolBackgnd = pRedrawInfo->Background; dcolForegnd = pRedrawInfo->Foreground; } // Work out the bounds of the bitmap and the label. DocRect drBmp(FormatRect), drTxt(FormatRect); drBmp.hi.x = drBmp.lo.x + SG_DefaultSmallIcon; drTxt.lo.x = drBmp.hi.x + SG_GapBeforeText; GridLockRect(pMiscInfo, &drBmp); GridLockRect(pMiscInfo, &drTxt); // Render the background. pRenderer->SetLineWidth(0); pRenderer->SetLineColour(pRedrawInfo->Transparent); pRenderer->SetFillColour(pRedrawInfo->Background); pRenderer->DrawRect(&drBmp); pRenderer->SetFillColour(dcolBackgnd); pRenderer->DrawRect(&drTxt); // Render the foreground. pRenderer->SetFixedSystemTextColours(&dcolForegnd, &dcolBackgnd); pRenderer->DrawFixedSystemText(&strName, drTxt); // Work out which bitmap to render beside it. UINT32 idBmp; m_eIntersect = GetDocument()->GetAttributeSets()->IntersectSelectedObj(strName); switch (m_eIntersect) { case AttributeSets::Intersect::NONE: idBmp = _R(IDB_NAMEGAL_NONESEL); break; case AttributeSets::Intersect::SOME: idBmp = _R(IDB_NAMEGAL_SOMESEL); break; case AttributeSets::Intersect::ALL: idBmp = _R(IDB_NAMEGAL_ALLSEL); break; } // Render the bitmap. DrawBitmap(pRenderer, &drBmp, idBmp); } /*********************************************************************************************** > virtual BOOL SGNameItem::HandleEvent(SGEventType nEventType, void* pEventInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: nEventType - An enumerated value describing what type of event is to be processed pEventInfo - A structure describing the event (may be 0). The exact thing pointed at by this pointer depends upon the event type: SGEVENT_FORMAT 0 SGEVENT_REDRAW (SGRedrawInfo*) SGEVENT_BGREDRAW 0 SGEVENT_BGFLUSH 0 - May have 0 MiscInfo SGEVENT_MOUSECLICK (SGMouseInfo*) SGEVENT_DRAGSTARTED (DragMessage*) SGEVENT_CLAIMPOINT (SGMouseInfo*) SGEVENT_THUMBMSG (ThumbMessage*) - May have 0 MiscInfo Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this information - they provide useful error/type checking, and hide the cast pMiscInfo - almost always provided. Contains a few useful bits of info that may be needed for all event types. This may be 0 for special event types (see sgtree.h for the enum and information on which ones may pass 0 MiscInfo - currently this is _THUMBMSG and _BGFLUSH, neither of which should concern you - so as long as you only reference MiscInfo once you know the event type, you will be safe) 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: VERY IMPORTANT: The rendering must be enclosed by calls to StartRendering and StopRendering, to ensure that rendering works properly (in the future we may change the redraw system to use a GRenderRegion for each individual item, rather than one global one for the window, for which these calls will be essential) SeeAlso: SGDisplayNode::HandleEvent; SGDisplayItem::HandleEvent ***********************************************************************************************/ BOOL SGNameItem::HandleEvent(SGEventType nEventType, void* pEventInfo, SGMiscInfo* pMiscInfo) { switch (nEventType) { case SGEVENT_FORMAT: { SGFormatInfo* pFormatInfo = GetFormatInfo(nEventType, pEventInfo); CalculateMyRect(pFormatInfo, pMiscInfo); break; } case SGEVENT_REDRAW: { DocRect MyRect(FormatRect); // Rely on FormatRect being cached from above SGRedrawInfo* pRedrawInfo = GetRedrawInfo(nEventType, pEventInfo); if (IMustRedraw(pRedrawInfo)) { StartRendering(pRedrawInfo, pMiscInfo); HandleRedraw(pRedrawInfo, pMiscInfo); StopRendering(pRedrawInfo, pMiscInfo); } break; } case SGEVENT_MOUSECLICK: { // Work out the bounds of the bitmap and the label. DocRect drBmp(FormatRect), drTxt(FormatRect); drBmp.hi.x = drBmp.lo.x + SG_DefaultSmallIcon; drTxt.lo.x = drBmp.hi.x + SG_GapBeforeText; GridLockRect(pMiscInfo, &drBmp); GridLockRect(pMiscInfo, &drTxt); // Check if the click is on the text label or the bitmap button beside it. SGMouseInfo* pMouse = GetMouseInfo(nEventType, pEventInfo); if (drTxt.ContainsCoord(pMouse->Position)) { // It's a click on the text label. Work out what to do. // No drag, so move on to selection click handling. Note that // Adjust-Double-Click does _not_ close the Name gallery. if (pMouse->DoubleClick) DefaultClickHandler(pMouse, pMiscInfo, FALSE, FALSE); else { // See if the base class can handle the mouse event. DefaultPreDragHandler(pMouse, pMiscInfo); // Make an appropriate attribute and try to start a drag. String_256 strName; GetNameText(&strName); TemplateAttribute* pAttrib = new TemplateAttribute(String_256(TEXT("ObjectName")), NullString, strName); if (pAttrib != 0) { GalleryNameDragInfo* pInfo = new GalleryNameDragInfo(this, pMouse, pMiscInfo, pAttrib, pMouse->MenuClick); if (pInfo != 0) DragManagerOp::StartDrag(pInfo, GetListWindow()); } } // Claim this event - nobody else can own this click. return TRUE; } else if (drBmp.ContainsCoord(pMouse->Position)) { // It's a click on the selection bitmap button. String_256 strName; GetNameText(&strName); INT32 nChanged = 0; switch (m_eIntersect) { case AttributeSets::Intersect::NONE: case AttributeSets::Intersect::SOME: nChanged = GetDocument()->GetAttributeSets()->ChangeObjSelect(strName, TRUE); break; case AttributeSets::Intersect::ALL: nChanged = GetDocument()->GetAttributeSets()->ChangeObjSelect(strName, FALSE); break; } // Make sure the selection is updated if something happened. if (nChanged != 0) GetApplication()->FindSelection()->Update(TRUE); // Claim the event. return TRUE; } break; } default: // Let the base class handle any events we don't know about. // This includes things like hit testing (CLAIMPOINT) etc return SGDisplayItem::HandleEvent(nEventType, pEventInfo, pMiscInfo); } // Default return value: we do not claim this event, so it will be passed on to others. return FALSE; } /******************************************************************************************** > NameGallery::NameGallery() Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Purpose: Initialises a NameGallery object, registering an idle processor for it. ********************************************************************************************/ NameGallery::NameGallery() : m_fMenusCreated(FALSE), m_fIdleProc(FALSE) { // Empty. } /******************************************************************************************** > NameGallery::~NameGallery() Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Purpose: Destroys a NameGallery object, deregistering its idle processor. ********************************************************************************************/ NameGallery::~NameGallery() { // Stop sending idle events if we are still claiming them. if (m_fIdleProc) GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_HIGH, this); } /******************************************************************************************** > BOOL NameGallery::PreCreate() Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Returns: TRUE if the Gallery initialised successfully FALSE if it should not be opened due to a failure to initialise Purpose: The NameGallery 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 NameGallery::PreCreate() { // If there isn't already one, create a DisplayTree. if (GetDisplayTree() == 0) { DisplayTree = new SGDisplayRootScroll(this); ERRORIF(DisplayTree == 0, _R(IDE_NOMORE_MEMORY), FALSE); } // For each document already present, create a display subtree (possibly replacing // a previous displaytree for it if we had one earlier) Document* pDoc = (Document*) GetApplication()->Documents.GetTail(); while (pDoc != 0) { // Find the existing subtree, if any, and create the items for it. SGNameGroup* pGroup = (SGNameGroup*) GetDisplayTree()->FindSubtree(this, pDoc, 0); if (!CreateItems(pDoc, pGroup)) return FALSE; pDoc = (Document*) GetApplication()->Documents.GetPrev(pDoc); } // Success. return TRUE; } /******************************************************************************************** > virtual SGNameGroup* NameGallery::CreateItems(Document* pParentDoc, SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: pParentDoc - The document to create a display subtree for pGroup - NULL (creates a new group for this document), or a pointer to the existing group-node for this document (in which case it clears all displayitems from the group and rebuilds it in place - this stops the display group moving around the tree at random!) Returns: Pointer to the group the items were created in, or null if it fails. Purpose: Internal call. This takes the NameItem list of the given document and creates a DisplayTree subtree from it. This subtree is then added to the DisplayTree. Note that this does not force a redraw of the list - after making this call, you should also call ForceRedrawOfList Notes: Passing in a NULL parent document pointer results in an ERROR3 - the function returns without doing anything in retail builds SeeAlso: SuperGallery::ForceRedrawOfList ********************************************************************************************/ SGNameGroup* NameGallery::CreateItems(Document* pParentDoc, SGNameGroup* pGroup) { ERROR3IF(pParentDoc == 0, "NameSGallery::CreateNewSubtree: no document"); // If there isn't already one, create a DisplayTree. if (GetDisplayTree() == 0) { DisplayTree = new SGDisplayRootScroll(this); ERRORIF(DisplayTree == 0, _R(IDE_NOMORE_MEMORY), 0); } // Set up a sort key ("by name") for both items and groups. SGSortKey sk[2] = { { SGSORTKEY_BYNAME, FALSE }, { SGSORTKEY_NONE, FALSE } }; // Use either the provided group or create a new one. if (pGroup != 0) { ERROR3IF(pGroup->GetParentDocument() != pParentDoc, "NameGallery::CreateItems: Group/Document mismatch"); pGroup->DestroySubtree(FALSE); } else { pGroup = new SGNameGroup(this, pParentDoc); ERRORIF(pGroup == 0, _R(IDE_NOMORE_MEMORY), 0); GetDisplayTree()->AddItem(pGroup, sk); } // Iterate over all the name in the set, creating a DisplayItem for // each one and inserting it in the DisplayGroup. String_256 strName; AttributeSets* pSets = pParentDoc->GetAttributeSets(); BOOL fOK = pSets->GetFirstSet(&strName); while (fOK) { SGNameItem* pNewItem = new SGNameItem(strName); ERRORIF(pNewItem == 0, _R(IDE_NOMORE_MEMORY), 0); pGroup->AddItem(pNewItem, sk); fOK = pSets->GetNextSet(&strName); } // Success. return pGroup; } /******************************************************************************************** > virtual MsgResult NameGallery::Message(Msg* pMessage) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: pMessage - 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; NameGallery::UpdateList ********************************************************************************************/ MsgResult NameGallery::Message(Msg* pMessage) { // User interface? if (IS_OUR_DIALOG_MSG(pMessage)) { DialogMsg* pMsg = (DialogMsg*) pMessage; switch (pMsg->DlgMsg) { case DIM_CREATE: SGInit::UpdateGalleryButton(OPTOKEN_DISPLAY_NAME_GALLERY, TRUE); break; case DIM_CANCEL: SGInit::UpdateGalleryButton(OPTOKEN_DISPLAY_NAME_GALLERY, FALSE); break; // Handle custom buttons. case DIM_LFT_BN_CLICKED: switch(pMsg->GadgetID) { case _R(IDC_NAMEGAL_RENAME): ApplyAction(SGACTION_EDIT); break; case _R(IDC_NAMEGAL_UNNAME): ApplyAction((SGActionType) SGACTION_UNNAME); break; case _R(IDC_GALLERY_HELP): HelpUserTopic(_R(IDS_HELPPATH_Gallery_Name)); break; } break; } } // A new document or a change in focus? else if (MESSAGE_IS_A(pMessage, DocChangingMsg)) { DocChangingMsg* pMsg = (DocChangingMsg*) pMessage; switch (pMsg->State) { case DocChangingMsg::DocState::BORNANDSTABLE: { // A new document has been opened, create a new group and items for it. MILLIPOINT nExtent = GetDisplayExtent(); if (!CreateItems(pMsg->pChangingDoc, 0)) return FAIL; ShadeGallery(FALSE); InvalidateCachedFormat(); RedrawEverythingBelow(-nExtent); } break; case DocChangingMsg::DocState::SELCHANGED: // Unhighlight all the items in the old document's group. if (pMsg->pOldDoc != 0) SelectItems(FALSE, FALSE, pMsg->pOldDoc); break; } // Make sure the button states are updated. SelectionHasChanged(); } // New intersection to show? else if (MESSAGE_IS_A(pMessage, SelChangingMsg)) { SelChangingMsg* pMsg = (SelChangingMsg*) pMessage; if (pMsg->State == SelChangingMsg::SelectionState::SELECTIONCHANGED) RefreshDocument(Document::GetCurrent()); } // An message that a Document's AttributeSets has changed? else if (MESSAGE_IS_A(pMessage, AttrSetChangeMsg)) { AttrSetChangeMsg* pMsg = (AttrSetChangeMsg*) pMessage; RefreshDocument(pMsg->GetDocument()); } // Always pass messages on for base class handling. return SuperGallery::Message(pMessage); } /******************************************************************************************** > virtual void NameGallery::RefreshDocument(Document* pDoc) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: pDoc --- the Document whose gallery items should be refreshed on the next idle event. Purpose: Marks a gallery as needing to be refreshed/redrawn on the next idle event sent to the NameGallery. SeeAlso: NameGallery::Message; NameGallery::OnIdleEvent; SGNameGroup::SetRefresh ********************************************************************************************/ void NameGallery::RefreshDocument(Document* pDoc) { // Ignore messages sent before there's a DisplayTree, or for Documents which don't // have an associated group. if (GetDisplayTree() == 0) return; SGNameGroup* pGroup = (SGNameGroup*) GetDisplayTree()->FindSubtree(this, pDoc, 0); if (pGroup != 0) { // Mark the group as needing to be refreshed and if there isn't one already, // register an idle event handler for this gallery. pGroup->SetRefresh(); if (!m_fIdleProc) { // Set at high priority so the gallery UI is quick. The proc will be // deregistered after one event so it won't hog the idle time. GetApplication()->RegisterIdleProcessor(IDLEPRIORITY_HIGH, this); m_fIdleProc = TRUE; } } } /******************************************************************************************** > virtual BOOL NameGallery::OnIdleEvent() Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Purpose: Called on idle events. Updates the selection if it's been changed, and recreates and redraws SGNameGroups if the named objects in their associated Documents have been changed. Notes: We bypass the standard SuperGallery OnIdleEvent background redraw code as we may have to destroy SGNameItems during the refresh operation, which cannot be done during the HandleEvent processing. SeeAlso: NameGallery::Message; NameGallery::OnIdleEvent; SGNameGroup::SetRefresh; Application::RegisterIdleProcessor ********************************************************************************************/ BOOL NameGallery::OnIdleEvent() { // If there's no display tree or we're shaded or closed then there's nothing // more to do. BOOL fChanged = FALSE; if (GetDisplayTree() != 0 && !AmShaded && IsVisible()) { // Iterate over all the groups, recreating and redrawing each that is marked // for refresh. SGNameGroup* pGroup = (SGNameGroup*) GetDisplayTree()->GetChild(); while (pGroup != 0) { if (pGroup->NeedsRefresh()) { // Recreate the items in this group and redraw everything. CreateItems(pGroup->GetParentDocument(), pGroup); fChanged = TRUE; } pGroup = (SGNameGroup*) pGroup->GetNext(); } } // If we changed something then update the buttons and the display. if (fChanged) { SelectionHasChanged(); ForceRedrawOfList(); } // Kill the idle event now the update has been done. ERROR3IF(!m_fIdleProc, "NameGallery::OnIdleEvent: lost track of idle event proc"); GetApplication()->RemoveIdleProcessor(IDLEPRIORITY_HIGH, this); m_fIdleProc = FALSE; // Don't call the SuperGallery handler as this gallery doesn't use the // background redraw facility and works on a lower priority level. return TRUE; } /******************************************************************************************** > virtual void NameGallery::SelectionHasChanged() Author: Justin_Flude (Xara Group Ltd) Created: 7/4/95 Purpose: Called by the base-class SuperGallery whenever the user clicks on an item. This version overrides the default bahaviour so that selecting more than one item does NOT grey the "Apply" button. ********************************************************************************************/ void NameGallery::SelectionHasChanged() { // Nothing to do if we are unavailable. if (AmShaded || !IsVisible()) return; // Work out if the user has selected any objects in the selected Document. BOOL fSelectionExists = Document::GetSelected() != 0 && !GetApplication()->FindSelection()->IsEmpty(); // Work out how items are highlighted in the gallery. INT32 n = GetSelectedItemCount(); // New button available when there is something selected in the Document. EnableGadget(_R(IDC_GALLERY_NEW), fSelectionExists); // Apply and Delete buttons available when at least one item is highlighted. EnableGadget(_R(IDC_GALLERY_APPLY), n >= 1); EnableGadget(_R(IDC_GALLERY_DELETE), n >= 1); // Rename button available when only one item is highlighted. EnableGadget(_R(IDC_NAMEGAL_RENAME), n == 1); // Redefine button available when at least one item is highlighted and something // is selected in the Document. EnableGadget(_R(IDC_GALLERY_REDEFINE), n >= 1 && fSelectionExists); // Unname button available when at least one item is highlighted and something // is selected in the Document. EnableGadget(_R(IDC_NAMEGAL_UNNAME), n >= 1 && fSelectionExists); } /******************************************************************************************** > virtual BOOL NameGallery::ApplyAction(SGActionType nAction) Author: Justin_Flude (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: nAction - 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 NameGallery::ApplyAction(SGActionType nAction) { // No display tree? Better forget about it then! if (GetDisplayTree() == 0) return FALSE; // Determine useful info - this is usually needed for most actions, so always get it Document* pDoc = Document::GetSelected(); ERROR3IF(pDoc == 0, "NameGallery::ApplyAction: no selected Document"); SGNameGroup* pGroup = (SGNameGroup*) GetDisplayTree()->FindSubtree(this, pDoc, 0); ERROR3IF(pGroup == 0, "NameGallery::ApplyAction: no Group for selected Document"); // Call the appropriate handler. switch (nAction) { case SGACTION_APPLY: return OnApply(pGroup, FALSE); case SGACTION_APPLYADJUST: return OnApply(pGroup, TRUE); case SGACTION_CREATE: return OnCreate(pGroup); case SGACTION_EDIT: return OnRename(pGroup); case SGACTION_DELETE: return OnDelete(pGroup); case SGACTION_REDEFINE: return OnRedefine(pGroup); case SGACTION_UNNAME: return OnUnname(pGroup); default: TRACEUSER( "JustinF", _T("NameGallery::ApplyAction: unimplemented action\n")); break; } // Successful processing. return TRUE; } /*********************************************************************************************** > virtual BOOL NameGallery::OnApply(SGNameGroup* pGroup, BOOL fIsAdjust) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group whose items are being applied fIsAdjust --- if TRUE then this is an "adjust" action, eg. the user ran the action with the Control button as a click modifier. Returns: TRUE if successful. Purpose: Selects (not "adjust") or toggles ("adjust") the selection status of all the objects in the associated attribute set of each highlighted SGNameItem. Notes: The Application's SelRange object is updated _after_ the SuperGallery event has been processed, as calling SelRange::Update during an SG event may destroy the SGNameItems which are processing it. SeeAlso: NameGallery::ApplyAction; AttributeSets::ChangeObjSelect ***********************************************************************************************/ BOOL NameGallery::OnApply(SGNameGroup* pGroup, BOOL fIsAdjust) { // If not Adjust then deselect all other objects first. If Adjust then _don't_ change // the selection of other objects. Don't broadcast a SelChangingMsg or the items will // be deleted before the iteration. if (!fIsAdjust) NodeRenderableInk::DeselectAll(TRUE, FALSE); // Work out what the new selection status of the objects will be. If Adjust then // toggle the selection states, otherwise set the selection states. BOOL fState = (fIsAdjust) ? -1 : TRUE; // Iterate over all the SGNameItems in pGroup which are selected. INT32 nChanged = 0; SGNameItem* pItem = (SGNameItem*) pGroup->FindNextSelectedItem(0); while (pItem != 0) { SGNameItem* pNextItem = (SGNameItem*) pGroup->FindNextSelectedItem(pItem); // Change the selection status of every object in the sets. Afterwards // NameGallery::Message will update the app's object selection. String_256 strName; pItem->GetNameText(&strName); nChanged += pItem->GetDocument()->GetAttributeSets()->ChangeObjSelect(strName, fState); pItem = pNextItem; } // Inform the application that the selection has changed if any objects were affected. if (nChanged != 0) GetApplication()->FindSelection()->Update(TRUE); return TRUE; } /*********************************************************************************************** > virtual BOOL NameGallery::GetNewName(SGNameGroup* pGroup, UINT32 nDialogTemplateID, String_256* pstrName) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group that a new name is being prompted for nDialogTemplateID --- the template ID to use, ie. _R(IDD_NAMEOBJ_NAMEDLG) or _R(IDD_NAMEOBJ_RENAMEDLG) Outputs: Returns: TRUE if successful and *pstrName is valid, FALSE if the user cancelled the dialog or something else went wrong. Purpose: Runs either the "Name selected objects" or "Rename objects" dialogs, returning a new, unique name chosen by the user. SeeAlso: NameGallery::OnCreate; NameGallery::OnRename; class NameObjectsDlg ***********************************************************************************************/ BOOL NameGallery::GetNewName(SGNameGroup* pGroup, UINT32 nDialogTemplateID, String_256* pstrName) { // Nightmarish pointer gubbins. ERROR3IF(pstrName == 0, "NameGallery::GetNewName: no output parameter"); ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::GetNewName: no Group or Document"); AttributeSets* pSets = pGroup->GetParentDocument()->GetAttributeSets(); OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NAME_OBJECTS_DLG); ERROR3IF(pDesc == 0, "NameGallery::OnCreate: can't find OPTOKEN_NAME_OBJECTS_DLG"); // Prompt the user until successfully ok-ed or cancelled. for (;;) { // Run the given dialog and get its result. BOOL fOk; pDesc->Invoke(&OpParam((INT32) pstrName, (INT32) nDialogTemplateID, &fOk)); // Did the user cancel the dialog or OK it with a valid entry? if (!fOk) return FALSE; if (!pSets->IsSet(*pstrName)) break; // Explain to the user that new names must be different and prompt again. InformError(_R(IDE_NAMEOBJ_NAME_EXISTS)); } // Success. return TRUE; } /*********************************************************************************************** > virtual BOOL NameGallery::OnCreate(SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group in which a new name is to be created Purpose: Prompts the user for a new name for the selected objects in the group's associated document and creates a new attribute set with that name. Returns: TRUE if successful. SeeAlso: NameGallery::ApplyAction; NameGallery::GetNewName; AttributeSets::CreateSetOfSelectedObj ***********************************************************************************************/ BOOL NameGallery::OnCreate(SGNameGroup* pGroup) { ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::OnCreate: no Group or Document"); // Run the "Name selected objects" dialog and get its result back. If the user // cancels the dialog we've nothing more to do. String_256 strName = GetApplication()->FindSelection()->Describe(STATUS_BAR); if (!GetNewName(pGroup, _R(IDD_NAMEOBJ_NAMEDLG), &strName)) return TRUE; // Ask the Document's AttributeSets object to make a set of the given name of all // the selected objects. ERROR3IF(pGroup->GetParentDocument() != Document::GetSelected(), "NameGallery::OnCreate: can't CreateSetOfSelectedObj as Document not selected"); return pGroup->GetParentDocument()->GetAttributeSets()->CreateSetOfSelectedObj(strName); } /*********************************************************************************************** > virtual BOOL NameGallery::OnRename(SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group containing the item to be renamed Returns: TRUE if successful. Purpose: Changes the existing name of objects. SeeAlso: NameGallery::ApplyAction; NameGallery::GetNewName; AttributeSets::RenameSet ***********************************************************************************************/ BOOL NameGallery::OnRename(SGNameGroup* pGroup) { ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::OnRename: no Group or Document"); // Extract the old name from the item. String_256 strName; SGNameItem* pItem = (SGNameItem*) pGroup->FindNextSelectedItem(0); pItem->GetNameText(&strName); // Run the "Name selected objects" dialog and get its result back. If the user // cancels the dialog we've nothing more to do. String_256 strNewName = strName; if (!GetNewName(pGroup, _R(IDD_NAMEOBJ_RENAMEDLG), &strNewName)) return TRUE; // Ask the Document's AttributeSets object to make a set of the given name of all // the selected objects. return pGroup->GetParentDocument()->GetAttributeSets()->RenameSet(strName, strNewName); } /*********************************************************************************************** > virtual BOOL NameGallery::OnDelete(SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group containing the items to be deleted Returns: TRUE if successful. Purpose: Deletes the given set from the group's document's AttributeSets. SeeAlso: NameGallery::ApplyAction ***********************************************************************************************/ BOOL NameGallery::OnDelete(SGNameGroup* pGroup) { ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::OnDelete: no Group or Document"); // Allocate an array of name parameters at least as big as all the number of // selected items. Set the last entry to null. INT32 nEntries = GetSelectedItemCount(); typedef const StringBase* PSTRBASE; PSTRBASE* pstrNames = new PSTRBASE[nEntries + 1]; ERRORIF(pstrNames == 0, _R(IDE_NOMORE_MEMORY), FALSE); pstrNames[nEntries] = 0; // Iterate over all the SGNameItems in pGroup which are selected, extracting their // names and allocating a copy for them. PSTRBASE* pstrIter = pstrNames; SGNameItem* pItem = (SGNameItem*) pGroup->FindNextSelectedItem(0); while (pItem != 0) { SGNameItem* pNextItem = (SGNameItem*) pGroup->FindNextSelectedItem(pItem); String_256 strName; pItem->GetNameText(&strName); *pstrIter = new String_256(strName); if (*pstrIter++ == 0) { delete[] pstrNames; Error::SetError(_R(IDE_NOMORE_MEMORY), 0); return FALSE; } pItem = pNextItem; } // Destroy the attribute sets. BOOL fResult = pGroup->GetParentDocument()->GetAttributeSets()->DestroySets(pstrNames); // Deallocate the parameter array and return the result. pstrIter = pstrNames; while (*pstrIter != 0) delete *pstrIter++; delete[] pstrNames; return fResult; } /*********************************************************************************************** > virtual BOOL NameGallery::OnRedefine(SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group containing the items to be redefined Returns: TRUE if successful. SeeAlso: NameGallery::ApplyAction ***********************************************************************************************/ BOOL NameGallery::OnRedefine(SGNameGroup* pGroup) { ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::OnRedefine: no Group or Document"); // Allocate an array of name parameters at least as big as all the number of // selected items. Set the last entry to null. INT32 nEntries = GetSelectedItemCount(); typedef const StringBase* PSTRBASE; PSTRBASE* pstrNames = new PSTRBASE[nEntries + 1]; ERRORIF(pstrNames == 0, _R(IDE_NOMORE_MEMORY), FALSE); pstrNames[nEntries] = 0; // Iterate over all the SGNameItems in pGroup which are selected, extracting their // names and allocating a copy for them. PSTRBASE* pstrIter = pstrNames; SGNameItem* pItem = (SGNameItem*) pGroup->FindNextSelectedItem(0); while (pItem != 0) { SGNameItem* pNextItem = (SGNameItem*) pGroup->FindNextSelectedItem(pItem); String_256 strName; pItem->GetNameText(&strName); *pstrIter = new String_256(strName); if (*pstrIter++ == 0) { delete[] pstrNames; Error::SetError(_R(IDE_NOMORE_MEMORY), 0); return FALSE; } pItem = pNextItem; } // Destroy the attribute sets. BOOL fResult = pGroup->GetParentDocument()->GetAttributeSets()->RedefineSetsAsSelectedObj(pstrNames); // Deallocate the parameter array and return the result. pstrIter = pstrNames; while (*pstrIter != 0) delete *pstrIter++; delete[] pstrNames; return fResult; } /*********************************************************************************************** > virtual BOOL NameGallery::OnUnname(SGNameGroup* pGroup) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/99 Inputs: pGroup --- the group containing the items to be removed from the selected objects Returns: TRUE if successful. Purpose: Removes the given sets from Document's currently selected objects. SeeAlso: NameGallery::ApplyAction ***********************************************************************************************/ BOOL NameGallery::OnUnname(SGNameGroup* pGroup) { ERROR3IF(pGroup == 0 || pGroup->GetParentDocument() == 0, "NameGallery::OnUnname: no Group or Document"); // Allocate an array of name parameters at least as big as all the number of // selected items. Set the last entry to null. INT32 nEntries = GetSelectedItemCount(); typedef const StringBase* PSTRBASE; PSTRBASE* pstrNames = new PSTRBASE[nEntries + 1]; ERRORIF(pstrNames == 0, _R(IDE_NOMORE_MEMORY), FALSE); pstrNames[nEntries] = 0; // Iterate over all the SGNameItems in pGroup which are selected, extracting their // names and allocating a copy for them. PSTRBASE* pstrIter = pstrNames; SGNameItem* pItem = (SGNameItem*) pGroup->FindNextSelectedItem(0); while (pItem != 0) { SGNameItem* pNextItem = (SGNameItem*) pGroup->FindNextSelectedItem(pItem); String_256 strName; pItem->GetNameText(&strName); *pstrIter = new String_256(strName); if (*pstrIter++ == 0) { delete[] pstrNames; Error::SetError(_R(IDE_NOMORE_MEMORY), 0); return FALSE; } pItem = pNextItem; } // Destroy the attribute sets. BOOL fResult = pGroup->GetParentDocument()->GetAttributeSets()->RemoveSelectedObjFromSets(pstrNames); // Deallocate the parameter array and return the result. pstrIter = pstrNames; while (*pstrIter != 0) delete *pstrIter++; delete[] pstrNames; return fResult; } /******************************************************************************************** > virtual BOOL NameGallery::InitMenuCommands() Author: Justin_Flude (Xara Group Ltd) Created: 18/9/95 Returns: TRUE if successful. Purpose: Initialises any menu commands that the Name gallery needs. ********************************************************************************************/ BOOL NameGallery::InitMenuCommands() { // Menus are only initialised once. return (m_fMenusCreated) ? TRUE : m_fMenusCreated = InitMenuCommand((StringBase*) &SGCmd_Find, _R(IDS_SGMENU_FIND)) && InitMenuCommand((StringBase*) &SGCmd_Apply, _R(IDS_SGMENU_APPLY)) && InitMenuCommand((StringBase*) &SGCmd_New, _R(IDS_SGMENU_NEW)) && InitMenuCommand((StringBase*) &SGCmd_Unname, _R(IDS_SGMENU_UNNAME)) && InitMenuCommand((StringBase*) &SGCmd_Delete, _R(IDS_SGMENU_DELETE)) && InitMenuCommand((StringBase*) &SGCmd_Rename, _R(IDS_SGMENU_RENAME)) && InitMenuCommand((StringBase*) &SGCmd_Redefine, _R(IDS_SGMENU_REDEFINE)) && InitMenuCommand((StringBase*) &SGCmd_FoldGroup, _R(IDS_SGMENU_FOLD)) && InitMenuCommand((StringBase*) &SGCmd_UnfoldGroup, _R(IDS_SGMENU_UNFOLD)) && InitMenuCommand((StringBase*) &SGCmd_PrevGroup, _R(IDS_SGMENU_PREVGROUP)) && InitMenuCommand((StringBase*) &SGCmd_NextGroup, _R(IDS_SGMENU_NEXTGROUP)); } /******************************************************************************************** > virtual BOOL NameGallery::BuildCommandMenu(GalleryContextMenu* pMenu, SGMenuID id) Author: Justin_Flude (Xara Group Ltd) Created: 15/9/95 Inputs: pMenu --- the menu to add commands to id --- the menu type (over-list or options-button) to create Returns: TRUE if successful. Purpose: To build a menu of commands to be popped up over the gallery. Notes: The Name gallery provides only a simple pop-up menu for items. ********************************************************************************************/ BOOL NameGallery::BuildCommandMenu(GalleryContextMenu* pMenu, SGMenuID id) { // Only handle pop-ups over display items. if (id != SGMENU_OVERITEM) return TRUE; SGNameGroup* pGroup = (SGNameGroup*) FindCommandGroup(); return AddCommand(pMenu, (StringBase*) &SGCmd_Find, TRUE) && AddCommand(pMenu, (StringBase*) &SGCmd_Apply) && AddCommand(pMenu, (StringBase*) &SGCmd_New) && AddCommand(pMenu, (StringBase*) &SGCmd_Unname) && AddCommand(pMenu, (StringBase*) &SGCmd_Delete) && AddCommand(pMenu, (StringBase*) &SGCmd_Rename) && AddCommand(pMenu, (StringBase*) &SGCmd_Redefine, TRUE) && ((pGroup == 0 || !pGroup->Flags.Folded) ? AddCommand(pMenu, (StringBase*) &SGCmd_FoldGroup) : AddCommand(pMenu, (StringBase*) &SGCmd_UnfoldGroup)) && AddCommand(pMenu, (StringBase*) &SGCmd_PrevGroup) && AddCommand(pMenu, (StringBase*) &SGCmd_NextGroup); } /******************************************************************************************** > virtual OpState NameGallery::OpState GetCommandState(StringBase* pstrCommandID, String_256* pstrShadeReason) Author: Justin_Flude (Xara Group Ltd) Created: 15/9/95 Inputs: pstrCommandID --- the ID of the command Outputs: pstrShadeReason --- if returning (OpState.Greyed == TRUE) then this is set to 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 NameGallery::GetCommandState(StringBase* pstrCommandID, String_256* pstrShadeReason) { // If the gallery is closed then return "greyed". OpState st(FALSE, TRUE); if (AmShaded) return st; // Work out if the user has selected any objects in the selected Document. BOOL fSelectionExists = Document::GetSelected() != 0 && !GetApplication()->FindSelection()->IsEmpty(); // Work out how items are highlighted in the gallery. INT32 n = GetSelectedItemCount(); // Work out the state for each command. if (*pstrCommandID == SGCmd_New) // 'New' is greyed if there's no selected document or no objects are selected. st.Greyed = !fSelectionExists; else if (*pstrCommandID == SGCmd_Apply || *pstrCommandID == SGCmd_Delete) // 'Apply/Delete' are greyed when no items are highlighted in the gallery. st.Greyed = (n == 0); else if (*pstrCommandID == SGCmd_Rename) // 'Rename' is enabled when only one item is highlighted. st.Greyed = (n != 1); else if (*pstrCommandID == SGCmd_Redefine || *pstrCommandID == SGCmd_Unname) // 'Redefine' and 'Unname' are greyed when no items are highlighted or there are // no selected objects in the Document. st.Greyed = (n == 0) || !fSelectionExists; else // Call the base class for default handling of the other commands. st = SuperGallery::GetCommandState(pstrCommandID, pstrShadeReason); return st; } /******************************************************************************************** > virtual void NameGallery::DoCommand(StringBase* pstrCommandID) Author: Justin_Flude (Xara Group Ltd) Created: 15/9/95 Inputs: pstrCommandID --- the ID of the command Purpose: Overrides the default virtual function in the SuperGallery base class so as to handle the custom SGACTION_UNNAME command. ********************************************************************************************/ void NameGallery::DoCommand(StringBase* pstrCommandID) { if (*pstrCommandID == SGCmd_Unname) ApplyAction((SGActionType) SGACTION_UNNAME); else SuperGallery::DoCommand(pstrCommandID); } /******************************************************************************************** > SGNameDragTarget::SGNameDragTarget() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Purpose: Default constructor, required for dynamic creation. ********************************************************************************************/ SGNameDragTarget::SGNameDragTarget() : SGListDragTarget(0, 0) { // Empty. } /******************************************************************************************** > SGNameDragTarget::SGNameDragTarget(NameGallery* pGallery, CGadgetID idGadget = 0); Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: pGallery --- the instance of the Name gallery idGadget --- the gadget within that dialogue which is the target Purpose: Initialises a drag target for an item from the Name gallery. ********************************************************************************************/ SGNameDragTarget::SGNameDragTarget(NameGallery* pGallery, CGadgetID idGadget) : SGListDragTarget(pGallery, idGadget) { // Empty. } /******************************************************************************************** BOOL SGNameDragTarget::ProcessEvent(DragEventType nEvent, DragInformation* pDragInfo, OilCoord* pMousePos, KeyPress* pKeyPress) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: nEvent --- indicates what has happened pDragInfo --- points to drag information describing this drag. This should be a BitmapDragInformation 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 SGNameItem gallery drag events. Overrides the base class handler to enable it to sort out the node being dragged for Name drags. ********************************************************************************************/ BOOL SGNameDragTarget::ProcessEvent(DragEventType nEvent, DragInformation* pDragInfo, OilCoord* pMousePos, KeyPress* pKeyPress) { ERROR3IF(!pDragInfo->IS_KIND_OF(GalleryNameDragInfo), "SGNameDragTarget::ProcessEvent: wrong kind of DragInfo"); SGDisplayNode* pDraggedNode = ((GalleryNameDragInfo*) pDragInfo)->GetDraggedNameAttr(); if (pDraggedNode == 0) return FALSE; switch (nEvent) { case DRAGEVENT_COMPLETED: // Drag just one item. HandleDragCompleted((NameGallery*) TargetDialog, pDraggedNode, pMousePos, TRUE); return TRUE; case DRAGEVENT_MOUSEMOVED: case DRAGEVENT_MOUSESTOPPED: case DRAGEVENT_MOUSEIDLE: return DetermineCursorShape((NameGallery*) TargetDialog, pDraggedNode, pMousePos); } // Not interested in any other event so don't claim it. return FALSE; } /******************************************************************************************** > GalleryNameDragInfo::GalleryNameDragInfo() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Purpose: Default constructor, required for dynamic creation. ********************************************************************************************/ GalleryNameDragInfo::GalleryNameDragInfo() : m_pSourceItem(0), m_pAttrib(0) { // Empty. } /******************************************************************************************** > GalleryNameDragInfo::GalleryNameDragInfo(SGNameItem* pSourceItem, SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo, TemplateAttribute* pAttrib, BOOL fIsAdjust = FALSE) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/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 pAttrib --- the attribute associated with the SGNameItem fIsAdjust --- TRUE if this is an "adjust" (Ctrl) drag ********************************************************************************************/ GalleryNameDragInfo::GalleryNameDragInfo(SGNameItem* pSourceItem, SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo, TemplateAttribute* pAttrib, BOOL fIsAdjust) : BitmapDragInformation(0, 100, 50, 0, 0, fIsAdjust), m_pSourceItem(pSourceItem), m_MouseInfo(*pMouseInfo), m_MiscInfo(*pMiscInfo), m_pAttrib(pAttrib) { // Empty. } /******************************************************************************************** > virtual GalleryNameDragInfo::~GalleryNameDragInfo() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Purpose: Destructor. Deletes the attribute associated with this object. ********************************************************************************************/ GalleryNameDragInfo::~GalleryNameDragInfo() { if (m_pAttrib != 0) { delete m_pAttrib; m_pAttrib = 0; } } /******************************************************************************************** > virtual void GalleryNameDragInfo::OnClick(INT32 nFlags, POINT ptClick) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: nFlags --- which keys are depressed during the drag ptClick --- the position of the mosue click Purpose: This is called if a drag was attempted but never started because it was a click all along. It calls back the SourceItem SGDisplayLine, to get it to handle the click. ********************************************************************************************/ void GalleryNameDragInfo::OnClick(INT32 nFlags, POINT ptClick) { if (m_pSourceItem != 0) m_pSourceItem->DefaultClickHandler(&m_MouseInfo, &m_MiscInfo); } /******************************************************************************************** > void GalleryNameDragInfo::GetCursorID(DragTarget* pDragTarget) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: pDragTarget --- the drag target to set the cursor for Purpose: Set cursor over this target. ********************************************************************************************/ UINT32 GalleryNameDragInfo::GetCursorID(DragTarget* pDragTarget) { // Only allow drops on the document view. if (pDragTarget == 0 || !pDragTarget->IS_KIND_OF(ViewDragTarget)) return _R(IDC_CANTDROP); // Get information about what's below the cursor. PageDropInfo pdInfo; ((ViewDragTarget*) pDragTarget)->GetDropInfo(&pdInfo); NodeRenderableInk* pObjectHit = pdInfo.pObjectHit; // ClickModifiers cmMods = ClickModifiers::GetClickModifiers(); // If there's an object below the cursor then show the "can drop" cursor, otherwise // show the "can't drop" cursor. return (pObjectHit != 0) ? _R(IDC_CANDROPONPAGE) : _R(IDC_CANTDROP); } /******************************************************************************************** > virtual BOOL GalleryNameDragInfo::GetStatusLineText(String_256* pText, DragTarget* pDragTarget) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: pText --- where to output the status line text pDragTarget --- the target of the drag (ie. the document view) Returns: TRUE if the output string is valid. Purpose: Works out status line text for this target of a Name gallery item drag. ********************************************************************************************/ BOOL GalleryNameDragInfo::GetStatusLineText(String_256* pText, DragTarget* pDragTarget) { // Validate outputs and object state. ERROR3IF(pText == 0, "GalleryNameDragInfo::GetStatusLineText: no output parameter"); if (TheBitmap == 0 || TheBitmap->ActualBitmap == 0) return FALSE; // Only provide status-line help for drops on the document view. if (pDragTarget == 0 || !pDragTarget->IS_KIND_OF(ViewDragTarget)) return FALSE; // Get information about what the mouse is over in the document view. PageDropInfo pdInfo; ((ViewDragTarget*) pDragTarget)->GetDropInfo(&pdInfo); NodeRenderableInk* pObjectHit = pdInfo.pObjectHit; // Build up the status-line help text. *pText = _R(IDST_NAMEGAL_DRAG); // "Dragging name" *pText += String_8(_R(IDS_SGDFONTS_STAT_COLON_SEP)); // " : " // Try to work out the specific description of the object the mouse is over. String_256 strObjectDesc = _R(IDS_SGLDRAG_THIS_OBJECT); // " this object"; if (pObjectHit != 0) strObjectDesc = pObjectHit->Describe(FALSE); *pText += String_256(_R(IDST_NAMEGAL_DROP_TO_APPLY)); // "Drop to apply this name to this "; *pText += strObjectDesc; return TRUE; } /******************************************************************************************** > virtual BOOL GalleryNameDragInfo::CanDropOnPage() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Returns: TRUE if the a name item can be dropped on a page (ie. a document view). Purpose: Called by the kernel dragging code to test whether a dragged name item can be dropped on a view onto a document. ********************************************************************************************/ BOOL GalleryNameDragInfo::CanDropOnPage() { return TRUE; } /******************************************************************************************** > virtual BOOL GalleryNameDragInfo::OnPageDrop(ViewDragTarget* pDragTarget) Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Inputs: pDragTarget --- the drag target representing the view onto a document (the "page"). Returns: TRUE if successful. Purpose: Called when a Name gallery item is dropped onto the page. ********************************************************************************************/ BOOL GalleryNameDragInfo::OnPageDrop(ViewDragTarget* pDragTarget) { // Extract the address of the object dropped on and apply the dragged name // attribute to it. PageDropInfo pdInfo; pDragTarget->GetDropInfo(&pdInfo); NodeRenderableInk* pObjectHit = pdInfo.pObjectHit; if (pObjectHit != 0) { // This call always deletes the passed attribute, so make sure we don't as well. AttributeManager::ApplyAttribToNode(pObjectHit, m_pAttrib); m_pAttrib = 0; } return TRUE; } /******************************************************************************************** > virtual INT32 GalleryNameDragInfo::GetDragTransparency() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Returns: A transparency value, in this case, 50% Purpose: Specifies how transparent a drag should be. ********************************************************************************************/ INT32 GalleryNameDragInfo::GetDragTransparency() { return 50; } /******************************************************************************************** > virtual KernelBitmap* GalleryNameDragInfo::GetSolidDragMask() Author: Justin_Flude (Xara Group Ltd) Created: 10/4/95 Returns: A pointer to a KernelBitmap to use as a 1bpp mask for the dragged item, or 0 for failure. Purpose: Renders an image of the dragged item into monochrome bitmap to use as an XOR mask for rendering the dragged Name gallery item. ********************************************************************************************/ KernelBitmap* GalleryNameDragInfo::GetSolidDragMask() { // If there's no current View, or no Spread, then fail. DocView* pView = DocView::GetCurrent(); if (pView == 0) return 0; Spread* pSpread = pView->FindEnclosingSpread(OilCoord(0, 0)); if (pSpread == 0) return 0; // Create a device context for the display. CDC cdcDisplay; cdcDisplay.CreateDC("DISPLAY", 0, 0, 0); // Calculate the size of the rendering and set up the rendering matrix etc. Matrix matConvert; FIXED16 fxScale = 1; DocRect drClip(0, 0, SG_DefaultNameText, SG_DefaultSmallIcon); // Create a render region with the given properties of the display etc. double dpi = (double) GetDeviceCaps(cdcDisplay.m_hDC, LOGPIXELSX); GRenderBitmap* pMaskRegion = new GRenderBitmap(drClip, matConvert, fxScale, 1, dpi); pMaskRegion->AttachDevice(pView, &cdcDisplay, pSpread); // Get the name of the item. String_256 strName; m_pSourceItem->GetNameText(&strName); // Render the blank background. pMaskRegion->StartRender(); pMaskRegion->SetLineWidth(0); pMaskRegion->SetLineColour(COLOUR_BLACK); pMaskRegion->SetFillColour(COLOUR_BLACK); pMaskRegion->DrawRect(&drClip); // Render the text. DocColour dcText(COLOUR_WHITE), dcBack(COLOUR_BLACK); pMaskRegion->SetFixedSystemTextColours(&dcText, &dcBack); pMaskRegion->DrawFixedSystemText(&strName, drClip); pMaskRegion->StopRender(); // Create a kernel bitmap from the OIL bitmap and return it. OILBitmap* pOilMaskBmp = pMaskRegion->ExtractBitmap(); delete pMaskRegion; return new KernelBitmap(pOilMaskBmp, TRUE); } /******************************************************************************************** > NameObjectsDlg::NameObjectsDlg() Author: Justin_Flude (Xara Group Ltd) Created: 9/8/94 Purpose: Create a NameObjectsDlg which is a modal DialogOp of template _R(IDD_NAMEOBJ_NAMEDLG) or _R(IDD_NAMEOBJ_RENAMEDLG). ********************************************************************************************/ NameObjectsDlg::NameObjectsDlg() : DialogOp(0, MODAL), // template ID is passed via OpParam to DoWithParam() m_pstrOutputName(0), m_pfOkCancel(0) { // Empty. } /******************************************************************************************** > virtual void NameObjectsDlg::DoWithParam(OpDescriptor*, OpParam* pOpParam) Author: Justin_Flude (Xara Group Ltd) Created: 9/8/94 Inputs: pOpParam --- pOpParam->Param1 is a pointer to the String_256 to set the committed value of the dialog to. pOpParam->Param2 is the dialog template to use ie. _R(IDD_NAMEOBJ_NAMEDLG) or _R(IDD_NAMEOBJ_RENAMEDLG). pOpParam->Output is a pointer to the BOOL to set to TRUE if the dialog is OK's, FALSE if it's cancelled. Purpose: Creates then opens the dialog ********************************************************************************************/ void NameObjectsDlg::DoWithParam(OpDescriptor*, OpParam* pOpParam) { // Remember the output parameters. ERROR3IF(pOpParam == 0, "NameObjectsDlg::DoWithParam: no OpParam"); ERROR3IF(pOpParam->Param1 == 0 || pOpParam->Output == 0, "NameObjectsDlg::DoWithParam: no output parameters"); // Extract the input and output parameters. m_pstrOutputName = (String_256*) (pOpParam->Param1); DlgResID = (CDlgResID) pOpParam->Param2; m_pfOkCancel = (BOOL*) (pOpParam->Output); // Try to run the operation. *m_pfOkCancel = FALSE; if (!Create()) { InformError(0, _R(IDS_OK)); End(); } } /******************************************************************************************** > MsgResult NameObjectsDlg::Message(Msg* pMessage) Author: Justin_Flude (Xara Group Ltd) Created: 9/8/94 Purpose: Handles kernel messages for the NameObjectsDlg dialog operation. ********************************************************************************************/ MsgResult NameObjectsDlg::Message(Msg* pMessage) { // A message from the dialog or its gadgets? if (IS_OUR_DIALOG_MSG(pMessage)) { DialogMsg* pMsg = (DialogMsg*) pMessage; switch (pMsg->DlgMsg) { case DIM_CREATE: SetStringGadgetValue(_R(IDC_NAMEOBJ_NAME), m_pstrOutputName); SetKeyboardFocus(_R(IDC_NAMEOBJ_NAME)); HighlightText(_R(IDC_NAMEOBJ_NAME)); break; case DIM_COMMIT: *m_pstrOutputName = GetStringGadgetValue(_R(IDC_NAMEOBJ_NAME), m_pfOkCancel); // nobreak; case DIM_CANCEL: Close(); End(); break; } } // Pass everything on to the base class . . . return DialogOp::Message(pMessage); } /******************************************************************************************** > static OpState NameObjectsDlg::GetState(String_256*, OpDescriptor*) Author: Justin_Flude (Xara Group Ltd) Created: 9/8/94 Purpose: The usual default GetState function for the NameObjectsDlg dialog operation. ********************************************************************************************/ OpState NameObjectsDlg::GetState(String_256*, OpDescriptor*) { OpState OpSt; return OpSt; } /******************************************************************************************** > static BOOL NameObjectsDlg::Init() Author: Justin_Flude (Xara Group Ltd) Created: 9/8/94 Purpose: Register operation. SeeAlso: SGInit::Init ********************************************************************************************/ BOOL NameObjectsDlg::Init() { return RegisterOpDescriptor(0, _R(IDS_NAMEOBJ_NAMEDLG), CC_RUNTIME_CLASS(NameObjectsDlg), OPTOKEN_NAME_OBJECTS_DLG, NameObjectsDlg::GetState, 0, // help ID 0); // bubble ID } /******************************************************************************************** > BOOL OpDisplayNameGallery::Init() Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: OpDisplayNameGallery initialiser method. Regsiters Operations. ********************************************************************************************/ BOOL OpDisplayNameGallery::Init() { return RegisterOpDescriptor(0, _R(IDS_DISPLAY_NAME_GALLERY), CC_RUNTIME_CLASS(OpDisplayNameGallery), OPTOKEN_DISPLAY_NAME_GALLERY, OpDisplayNameGallery::GetState, 0, // help id _R(IDBBL_DISPLAY_NAME_GALLERY), // bubble help id 0); // bitmap id } /******************************************************************************************** > OpState OpDisplayNameGallery::GetState(String_256*, OpDescriptor*) Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Returns: The state of the OpDisplayNameGallery operation Purpose: For finding the OpDisplayNameGallery's state. ********************************************************************************************/ OpState OpDisplayNameGallery::GetState(String_256* UIDescription, OpDescriptor*) { // If the gallery is currently open, then the menu item should be ticked OpState OpSt; DialogBarOp* pDialogBarOp = FindGallery(); if (pDialogBarOp != 0) OpSt.Ticked = pDialogBarOp->IsVisible(); // If there are no open documents, you can't toggle the gallery OpSt.Greyed = (Document::GetSelected() == 0); return OpSt; } /******************************************************************************************** > void OpDisplayNameGallery::Do(OpDescriptor*) Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Purpose: Displays the Names gallery Updates the button state for this Op (the button sticks down while the gallery is open) ********************************************************************************************/ void OpDisplayNameGallery::Do(OpDescriptor*) { DialogBarOp *pOp = FindGallery(); if (pOp != 0) { // Toggle the visible state of the gallery window pOp->SetVisibility(!pOp->IsVisible()); SGInit::UpdateGalleryButton(OPTOKEN_DISPLAY_NAME_GALLERY, pOp->IsVisible()); } End(); } /******************************************************************************************** > static DialogBarOp* OpDisplayNameGallery::FindGallery() Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Returns: 0 or a pointer to the Name gallery instance Purpose: Finds the Name gallery class instance Notes: The bars system always keeps one Name 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 NameGallery class ********************************************************************************************/ DialogBarOp* OpDisplayNameGallery::FindGallery() { String_32 id(_R(IDS_SGNAME_GALLERY_NAME)); // "Name gallery"; DialogBarOp* pOp = DialogBarOp::FindDialogBarOp(id); ERROR3IF(pOp == 0 || pOp->GetRuntimeClass() != CC_RUNTIME_CLASS(NameGallery), "OpDisplayNameGallery::FindGallery: Can't find the gallery in bars.ini!\n"); return pOp; }