// $Id: ngitem.cpp 1488 2006-07-20 15:31:34Z phil $ /* @@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============================ */ /* $Header: /Camelot/kernel/ngitem.cpp 17 22/11/04 18:55 Phil $ Attribute gallery display items */ #include "camtypes.h" #include "ngcore.h" #include "ngdrag.h" #include "ngitem.h" #include "ngprop.h" #include "ngscan.h" #include "ngsentry.h" #include "ngsetop.h" //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "dragmgr.h" #include "keypress.h" //#include "bitmap.h" // bitmaps - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodebmp.h" //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "cxfrech.h" // names - in camtypes.h [AUTOMATICALLY REMOVED] //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "userattr.h" #include "tmpltatr.h" #include "fontman.h" // fonts //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "nodetext.h" //#include "doccolor.h" // colours - in camtypes.h [AUTOMATICALLY REMOVED] #include "colourix.h" //#include "galres.h" //#include "mario.h" //#include "justin3.h" #include "slicehelper.h" #include "fillattr2.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif DECLARE_SOURCE("$Revision: 1488 $"); // Implement the dynamic class bits... CC_IMPLEMENT_DYNAMIC(SGNameItem, SGDisplayItem); CC_IMPLEMENT_DYNAMIC(SGNameGroup, SGDisplayGroup); // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW /*********************************************************************************************** > SGNameItem::SGNameItem(const StringBase& strName) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: strName - the name ('attribute value') of this set item. Purpose: Construct an SGNameItem. ***********************************************************************************************/ SGNameItem::SGNameItem(const StringBase& strName) : m_strName(strName), m_pCachedPropertyNode(0), m_nNodes(0), m_nObjects(0), m_nSelected(0) { // TRACEUSER( "JustinF", _T("SGNameItem::SGNameItem(%s)\n"), (LPCTSTR) m_strName); } /*********************************************************************************************** > virtual void SGNameItem::GetNameText(String_256* pResult) Author: Justin_Flude (Xara Group Ltd) Created: 9/3/99 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_strName; } /*********************************************************************************************** > SGNameProp* SGNameItem::GetProperty(INT32 nIndex = -1) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: nIndex --- the index of the property to retrieve (default is the current property) Returns: The property associated with this item of the given type (index). NB. the item remains responsible for deallocation of the property. SeeAlso: SGNameProp; NodeSetProperty; NodeSetSentinel ***********************************************************************************************/ SGNameProp* SGNameItem::GetProperty(INT32 nIndex) const { // No document means no properties. Document* pDoc = Document::GetSelected(); if (pDoc == 0) return 0; // Only 'Used Names' have properties (for now). if (GetParent() != NameGallery::Instance()->GetUsedNames()) return 0; // Fetch the current property? if (nIndex == -1) nIndex = NameGallery::Instance()->GetPropertyIndex(); ERROR3IF(nIndex < 0 || nIndex >= SGNameProp::nPropertyCount, "SGNameItem::GetProperty: index out of range"); // Retrieve the SGNameProp* from the associated NodeSetProperty. NodeSetProperty* pSetProp = pDoc->GetSetSentinel()->FindPropertyNode(m_strName); if (pSetProp == 0) return 0; SGNameProp* pProp = pSetProp->GetProperty(nIndex); ERROR3IF(pProp == 0, "SGNameItem::GetProperty: no property"); return pProp; } /*********************************************************************************************** > void SGNameItem::Reset(BOOL fPropagateChanges) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: fPropagateChanges --- TRUE if all bounds records should be sync'ed (?) Purpose: Resets the state of the object in preparation for a refresh ***********************************************************************************************/ void SGNameItem::Reset(BOOL fPropagateChanges) { // Remember the old bounds of the set and reset all running totals. if (fPropagateChanges) m_rOldSetBounds = m_rSetBounds; m_rSetBounds.MakeEmpty(); m_rSelectBounds.MakeEmpty(); m_nNodes = m_nObjects = m_nSelected = 0; m_pCachedPropertyNode = 0; } /*********************************************************************************************** > NodeSetProperty* SGNameItem::GetPropertyNode() Author: Simon_Knight (Xara Group Ltd) Created: 17/3/00 Purpose: returns a cached ptr to this sets property node. This is NULLed in Reset() and filled with a search on demand ***********************************************************************************************/ NodeSetProperty* SGNameItem::GetPropertyNode() { // scan for the property node and cache this ptr return (m_pCachedPropertyNode != 0) ? m_pCachedPropertyNode : m_pCachedPropertyNode = Document::GetCurrent()->GetSetSentinel()->FindPropertyNode(m_strName); } /*********************************************************************************************** > void SGNameItem::Include(Node* pNode) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to "register" Purpose: Called by the CreateScan::Do when a node is discovered that is a member of this set item. Updates the running totals of member objects and selected member objects. ***********************************************************************************************/ void SGNameItem::Include(Node* pNode) { // Count nodes, including the sentinel. ++m_nNodes; if (pNode->IsNodeRenderableClass()) { // Count selectable (renderable) nodes. ++m_nObjects; BOOL fSelect = (pNode->IsSelected() || pNode->IsChildOfSelected()) || (pNode->IsCompound() && pNode->IsParentOfSelected()); if (fSelect) ++m_nSelected; // Accumulate bounds of objects, and just those selected. if (pNode->IsBounded()) { DocRect rBounds = SliceHelper::BoundingNodeSize(pNode); m_rSetBounds = m_rSetBounds.Union(rBounds); if (fSelect) m_rSelectBounds = m_rSelectBounds.Union(rBounds); } } } /*********************************************************************************************** > virtual INT32 SGNameItem::CompareTo(SGDisplayNode* pOther, INT32 nKey) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: (see SGDisplayNode::CompareTo) Returns: -1 if comparison is < 0 if = +1 if > Purpose: Overrides the default comparator so that it takes into accounted appended numbers. ***********************************************************************************************/ INT32 SGNameItem::CompareTo(SGDisplayNode* pItem, INT32 nKey) { ERROR3IF(pItem == 0, "SGNameItem::CompareTo: null input"); ERROR3IF(!pItem->IS_KIND_OF(SGNameItem), "SGNameItem::CompareTo: not an SGNameItem"); switch (nKey) { case SGSORTKEY_BYNAME: { // Compare the strings character by character until we can determine their // lexical order. If the characters to be compared are numeric, then parse // and compare them as ordinals. LPCTSTR pchThis = m_strName, pchOther = ((SGNameItem*) pItem)->m_strName; for (;;) { // Eat up any whitespace. while (StringBase::IsSpace(*pchThis)) pchThis = camStrinc(pchThis); while (StringBase::IsSpace(*pchOther)) pchOther = camStrinc(pchOther); // Check if we've reached the end of the strings. If we have reached // the end of both, they are equal. Otherwise the one that is shortest // is 'lower'. if (*pchThis == TEXT('\0')) return (*pchOther == TEXT('\0')) ? 0 : -1; else if (*pchOther == TEXT('\0')) return 1; // Are the next two characters to be compared numeric? if (StringBase::IsNumeric(*pchThis) && StringBase::IsNumeric(*pchOther)) { // Span and copy the integers embedded in each string. String_256 strThisNum, strOtherNum; LPTSTR pchThisNum = strThisNum, pchOtherNum = strOtherNum; do { *pchThisNum = *pchThis; pchThisNum = camStrinc(pchThisNum); pchThis = camStrinc(pchThis); } while (StringBase::IsNumeric(*pchThis)); do { *pchOtherNum = *pchOther; pchOtherNum = camStrinc(pchOtherNum); pchOther = camStrinc(pchOther); } while (StringBase::IsNumeric(*pchOther)); *pchThisNum = *pchOtherNum = TEXT('\0'); // Convert and compare the numbers. INT32 nThis, nOther; Convert::StringToLong( strThisNum, &nThis ); Convert::StringToLong( strOtherNum, &nOther ); if (nThis < nOther) return -1; else if (nThis > nOther) return 1; // Restart all tests as we may now be pointing at a null or a space. continue; } // The characters are not both numeric, so perform a normal comparison. INT32 nTest = *pchOther - *pchThis; PORTNOTE("other", "Removed CompareString, rwplace with simple subtraction" ) #if !defined(EXCLUDE_FROM_XARALX) ::CompareString(LOCALE_USER_DEFAULT, NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH | NORM_IGNORECASE, pchThis, 1, pchOther, 1) - 2; #endif if (nTest != 0) return nTest; // The strings are still equal so compare the next characters. pchThis = camStrinc(pchThis); pchOther = camStrinc(pchOther); } } break; default: // Let the base class handle all other types of comparison. return SGDisplayItem::CompareTo(pItem, nKey); } return 0; } /*********************************************************************************************** > virtual void SGNameItem::DragWasReallyAClick(SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: (see SGDisplayNode::DragWasReallyACick) Purpose: Called by the dragging code when a drag turns out to be a mundane single click. ***********************************************************************************************/ void SGNameItem::DragWasReallyAClick(SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo) { // NB. called post-drag. DefaultClickHandler(pMouseInfo, pMiscInfo, TRUE); } /******************************************************************************************** > virtual BOOL SGNameItem::GetBubbleHelp(DocCoord *pMousePos, String_256 *pResult) Author: Justin_Flude (Xara Group Ltd) Created: 16/4/99 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* pMousePos, String_256* pResult) { ERROR3IF(pResult == 0, "SGNameItem::GetBubbleHelp: invalid null params"); // Matt - 16/09/2000 - Added for tooltip help over properties // Work out which UI item is hovered over, if any... if (m_nObjects > 0 && m_rProp.ContainsCoord(*pMousePos)) { //Then we're hovering over the properties section... SGNameProp* pProp = GetProperty(); if (pProp->GetIndex() == 0) { //Then it's an EXPORT property TRACEUSER( "matt", _T("...EXPORTY...\n")); } else if (pProp->GetIndex() == 1) { //Then it's a SLICE tickbox TRACEUSER( "matt", _T("SLICEY...\n")); } else if (pProp->GetIndex() == 2) { //Then it's a STRETCH tickbox TRACEUSER( "matt", _T("...STRETCHY...\n")); } String strNameGal( _R(IDBBL_NAMEGAL_NONE) ); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_ITEM), &strNameGal, &m_strName); } else { // Work out the intersection with the user selection. UINT32 id; if (IsNoneSelected()) id = _R(IDBBL_NAMEGAL_NONE); else if (IsAllSelected()) id = _R(IDBBL_NAMEGAL_ALL); else id = _R(IDBBL_NAMEGAL_SOME); // Create the bubble help text. String strNameGal( id ); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_ITEM), &strNameGal, &m_strName); } } /********************************************************************************************** > virtual BOOL SGNameItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) Author: Justin_Flude (Xara Group Ltd) Created: 16/4/99 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) { // Matt - 16/09/2000 - Added for statusbar help over properties // Work out which UI item is hovered over, if any... if (m_nObjects > 0 && m_rProp.ContainsCoord(*pMousePos)) { //Then we're hovering over the properties section... SGNameProp* pProp = GetProperty(); if (pProp->GetIndex() == 0) { //Then it's an EXPORT property TRACEUSER( "matt", _T("...EXPORTY...\n")); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPEXPORTOPT)); } else if (pProp->GetIndex() == 1) { //Then it's a SLICE tickbox TRACEUSER( "matt", _T("SLICEY...\n")); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPSLICE)); } else if (pProp->GetIndex() == 2) { //Then it's a STRETCH tickbox TRACEUSER( "matt", _T("...STRETCHY...\n")); return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPSTRETCH)); } } else { String strSel; // Intersect this item's set with the selected objects. if (IsNoneSelected()) strSel = _R(IDBBL_NAMEGAL_NONE); else if (IsAllSelected()) strSel = _R(IDBBL_NAMEGAL_ALL); else strSel = _R(IDBBL_NAMEGAL_SOME); strSel.toLower(); // What is the mouse pointing at? UINT32 idMask; SGNameGroup* pGroup = (SGNameGroup*) GetParent(); if (m_rToggle.ContainsCoord(*pMousePos)) // Over the selection toggle gadget. idMask = _R(IDST_NAMEGAL_ITEM_SEL_GADGET); else if (pGroup == NameGallery::Instance()->GetUsedNames()) // Over a 'Used Name' idMask = _R(IDST_NAMEGAL_NAME_ITEM); else // Over 'Used' something else. idMask = _R(IDST_NAMEGAL_OTHER_ITEM); // Build up a specific message. String strType(pGroup->GetTypeID()); return pResult->MakeMsg(idMask, &strSel, &m_strName, &strType, &strType); } // It failed, so return FALSE. return FALSE; } /*********************************************************************************************** > virtual void SGNameItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pFormatInfo --- formatting info from which to calculate my position/size pMiscInfo --- the window dimensions, pixel size etc Purpose: Calculates the bounds of the distinct UI items that make up a line in the Attribute gallery. Notes: Member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item. SeeAlso: SGNameItem::HandleRedraw; SGNameItem::HandleEvent ***********************************************************************************************/ void SGNameItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) { // pMiscInfo can't be null (pFormatInfo can be as it's not very useful). ERROR3IF(pMiscInfo == 0, "SGNameItem::CalcUiBounds: null input/output argument"); // Work out the maximum bounds of the toggle gadget, label and property. m_rText = FormatRect; m_rText.hi.x -= SG_GapBeforeText / 2; m_rToggle = m_rText; m_rToggle.hi.x = m_rToggle.lo.x + SG_DefaultSmallIcon; m_rText.lo.x = m_rToggle.hi.x + SG_GapBeforeText; // Split the label bounds with the property. SGNameProp* pProp = GetProperty(); if (pProp == 0) m_rProp.MakeEmpty(); else { m_rProp = m_rText; PORTNOTE("other", "Removed SuperGallery related stuff" ) #if !defined(EXCLUDE_FROM_XARALX) pProp->CalcUiBounds(this, pFormatInfo, pMiscInfo, &m_rProp); #endif m_rText.hi.x = m_rProp.lo.x - SG_GapBeforeText; } // Pixel-align. GridLockRect(pMiscInfo, &m_rToggle); GridLockRect(pMiscInfo, &m_rText); GridLockRect(pMiscInfo, &m_rProp); } /*********************************************************************************************** > virtual void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pFormatInfo - The formatting info from which to calculate my position/size Outputs: pMiscInfo - As usual, the useful misc info struct 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 ***********************************************************************************************/ void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) { CalculateFormatRect(pFormatInfo, pMiscInfo, SG_InfiniteWidth, SG_DefaultSmallIcon); CalcUiBounds(pFormatInfo, pMiscInfo); } /*********************************************************************************************** > virtual void SGNameItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pRedrawInfo --- the information on the kernel-rendered redraw area pMiscInfo --- the drawing context information structure Purpose: Default implementation for drawing the label of an item, the renderer has already been set up with default attributes. Notes: Member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item. SeeAlso: SGNameItem::CalcUiBounds ***********************************************************************************************/ void SGNameItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) { pRedrawInfo->Renderer->DrawFixedSystemText(&m_strName, m_rText); } /*********************************************************************************************** > virtual void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGFormatInfo* pFormatInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pRedrawInfo --- the information on the kernel-rendered redraw area pFormatInfo --- the formatting information structure Purpose: SGNameItem item redraw method - removed from the main HandleEvent method merely to make the code tidier. Notes: Member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item. SeeAlso: SGNameItem::CalcUiBounds ***********************************************************************************************/ void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) { // Set the foreground and background colours according to whether this item is // gallery selected or not. 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; } // Render the unhighlighted background. pRedrawInfo->Renderer->SetFillColour(pRedrawInfo->Background); pRedrawInfo->Renderer->SetLineColour(pRedrawInfo->Transparent); pRedrawInfo->Renderer->SetLineWidth(0); pRedrawInfo->Renderer->DrawRect(&m_rToggle); pRedrawInfo->Renderer->DrawRect(&m_rProp); // Render highlighted background. pRedrawInfo->Renderer->SetFillColour(dcolBackgnd); pRedrawInfo->Renderer->DrawRect(&m_rText); // Render the selection toggle gadget, on the left, if the set isn't empty. if (!IsEmpty()) { UINT32 idBmp; if (IsNoneSelected()) idBmp = _R(IDB_NAMEGAL_NONESEL); else if (IsAllSelected()) idBmp = _R(IDB_NAMEGAL_ALLSEL); else idBmp = _R(IDB_NAMEGAL_SOMESEL); pRedrawInfo->Renderer->DrawBitmap(m_rToggle.lo, idBmp); } // Render the label of the item, in the middle. pRedrawInfo->Renderer->SetFixedSystemTextColours(&dcolForegnd, &dcolBackgnd); DrawLabel(pRedrawInfo, pMiscInfo); // Render the property, on the right. if (m_nObjects > 0) { PORTNOTE("other", "Removed SuperGallery related stuff" ) #if !defined(EXCLUDE_FROM_XARALX) SGNameProp* pProp = GetProperty(); if (pProp != 0) pProp->HandleRedraw(this, pRedrawInfo, pMiscInfo, m_rProp); #endif } } /*********************************************************************************************** > 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: *pFormatInfo is updated as appropriate Returns: TRUE if the event was handled successfully, FALSE if it was not. Purpose: Handles a SuperGallery display 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: SGDisplayItem::HandleEvent; SGNameItem::CalcUiBounds ***********************************************************************************************/ BOOL SGNameItem::HandleEvent(SGEventType nEventType, void* pEventInfo, SGMiscInfo* pMiscInfo) { switch (nEventType) { case SGEVENT_FORMAT: { SGFormatInfo* pFormatInfo = GetFormatInfo(nEventType, pEventInfo); CalculateMyRect(pFormatInfo, pMiscInfo); CalcUiBounds(0, 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); pRedrawInfo->Renderer->SaveContext(); HandleRedraw(pRedrawInfo, pMiscInfo); pRedrawInfo->Renderer->RestoreContext(); StopRendering(pRedrawInfo, pMiscInfo); } break; } case SGEVENT_MOUSECLICK: { // Work out which UI item has been clicked on, if any. SGMouseInfo* pMouseInfo = GetMouseInfo(nEventType, pEventInfo); if (m_rToggle.ContainsCoord(pMouseInfo->Position)) { TRACEUSER( "matt", _T("m_rToggle Contains the Mouse Coords\n")); if (m_nObjects > 0) { TRACEUSER( "matt", _T("Num Objects > 0\n")); // It's a click on the selection toggle gadget for some objects. SelectScan::Change eChange; if (KeyPress::IsGalleryCtrlPressed()) eChange = SelectScan::TOGGLE; else if (IsAllSelected()) eChange = SelectScan::DESELECT; else eChange = SelectScan::SELECT; // Change the selection state of the objects within this set item and // claim the event. OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_SELECT_SET); ERROR3IF(pDesc == 0, "SGNameItem::HandleEvent: no descriptor"); OpParam param( this, INT32(eChange) ); pDesc->Invoke( ¶m ); return TRUE; } } else if (m_nObjects > 0 && m_rProp.ContainsCoord(pMouseInfo->Position)) { TRACEUSER( "matt", _T("m_rToggle DOES NOT contain MouseCoords, m_rProp DOES\n")); PORTNOTE("other", "Removed SuperGallery related stuff" ) #if !defined(EXCLUDE_FROM_XARALX) // It's a click on the property UI. Pass it on and claim it. SGNameProp* pProp = GetProperty(); if (pProp != 0 && !pProp->HandleMouse(this, pMouseInfo, pMiscInfo)) { InformError(); return FALSE; } #endif return TRUE; } else if (m_rText.ContainsCoord(pMouseInfo->Position) || (m_nObjects == 0 && m_rProp.ContainsCoord(pMouseInfo->Position))) { TRACEUSER( "matt", _T("m_rText contains MouseCoords OR m_rProp DOES\n")); // It's a click on the text label. If a name is clicked then (always) // start dragging it. If the click isn't really a drag then // DragWasReallyAClick will be called when the drag is cancelled. DefaultPreDragHandler(pMouseInfo, pMiscInfo); PORTNOTE("other", "Removed bitmap drag handling BitmapDragInformation"); #ifndef EXCLUDE_FROM_XARALX if (GetParent() == NameGallery::Instance()->GetUsedNames()) { // It's a name (ie. a child of the 'Used Names' group), so create and run // a drag operation. SGNameDrag* pDragInfo = new SGNameDrag(this, pMouseInfo, pMiscInfo); ERRORIF(pDragInfo == 0, _R(IDE_NOMORE_MEMORY), FALSE); DragManagerOp::StartDrag(pDragInfo, GetListWindow()); } else #endif // Not a name so just do the default, but don't close on // adjust-double-click. DefaultClickHandler(pMouseInfo, pMiscInfo, FALSE); TRACEUSER("JustinF", _T("%s \"%s\" at 0x%p --- %d nodes, %d objects, %d selected\n"), (LPCTSTR) String(((SGNameGroup*) GetParent())->GetTypeID()), (LPCTSTR) m_strName, (LPVOID) this, m_nNodes, m_nObjects, m_nSelected); // Claim this click. return TRUE; } TRACEUSER( "matt", _T("Click outside bounds of item's UI\n")); // The click was outside the bounds of the item's UI gadgets. break; } /* // Matt - 15/09/2000 - Added for tooltip help over properties case SGEVENT_CLAIMPOINT: { // Work out which UI item is hovered over, if any... SGClaimPointInfo *pMouseInfo = GetClaimPointInfo(nEventType, pEventInfo); if (!m_rToggle.ContainsCoord(pMouseInfo->Position) && m_nObjects > 0 && m_rProp.ContainsCoord(pMouseInfo->Position)) { //Then we're hovering over the properties section... SGNameProp* pProp = GetProperty(); if (pProp->GetIndex() == 0) { //Then it's an EXPORT property TRACEUSER( "matt", _T("...EXPORTY...\n")); } else if (pProp->GetIndex() == 1) { //Then it's a SLICE tickbox TRACEUSER( "matt", _T("SLICEY...\n")); } else if (pProp->GetIndex() == 2) { //Then it's a STRETCH tickbox TRACEUSER( "matt", _T("...STRETCHY...\n")); } // if (pProp != 0 && !pProp->HandleMouse(this, pMouseInfo, pMiscInfo)) // { // InformError(); // return FALSE; // } 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; } // is this name group item a backbar? BOOL SGNameItem::IsABackBar() { String_256 SubName = m_strName; *(((TCHAR *)SubName) + 7) = 0; return ( SubName == _T("BackBar") ); } //////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// /******************************************************************************************** > SGNameGroup::SGNameGroup(UINT32 idType, Document* pDoc = 0) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pDoc --- the document associated with this group (by default, always whatever is the currently 'selected' document) Purpose: Creates an abstract Name Gallery group. Notes: Uses the lowest bit of SGDisplayFlags.Reserved to track whether a group has been automatically folded because it has no items (and hence should automatically unfold if it later has new items to show). ********************************************************************************************/ SGNameGroup::SGNameGroup(UINT32 idType, UINT32 idTitle, Document* pDoc) : SGDisplayGroup(NameGallery::Instance(), pDoc), m_idType(idType), m_idTitle(idTitle) { Flags.CanSelect = TRUE; Flags.Reserved &= ~1; } /******************************************************************************************** > virtual UINT32 SGNameGroup::GetTypeID() const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Returns: The ID of a string that describes the type of items in this group. ********************************************************************************************/ UINT32 SGNameGroup::GetTypeID() const { return m_idType; } /******************************************************************************************** > SGNameItem* SGNameGroup::FindItem(const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Returns: The ID of a string that describes the type of items in this group. ********************************************************************************************/ SGNameItem* SGNameGroup::FindItem(const StringBase& strName) const { // Iterate over all the items looking a matching name. for (SGNameItem* pItem = (SGNameItem*) GetChild(); pItem != 0; pItem = (SGNameItem*) pItem->GetNext()) { if (pItem->GetNameTextPtr()->CompareTo(strName) == 0) return pItem; } // Can't find an item with that name. return 0; } /******************************************************************************************** > SGNameItem* SGNameGroup::RegisterMember(Node* pNode, const StringBase& strName) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to register as a member strName --- the name of the new item to make if one doesn't exist already Purpose: Creates and inserts a SGNameItem with the given name if one doesn't exist already. Includes the given node in the set's bounds etc. Errors: Out of memory. ********************************************************************************************/ SGNameItem* SGNameGroup::RegisterMember(Node* pNode, const StringBase& strName) { // Only make a new item if there isn't one already. SGNameItem* pItem; for ( pItem = (SGNameItem*) GetChild(); pItem != 0 && !pItem->IsEqual(strName); pItem = (SGNameItem*) pItem->GetNext()) /* empty */ ; if (pItem == 0) { // If we previously had no children and folded because of that then // automatically unfold. if (GetChild() == 0 && (Flags.Reserved & 1)) { Flags.Reserved &= ~1; Flags.Folded = FALSE; } // We must create a new set item for this 'attribute value'. pItem = MakeItem(strName); ERRORIF(pItem == 0, _R(IDE_NOMORE_MEMORY), 0); // Insert in alphabetical order. SGSortKey sk[2] = { { SGSORTKEY_BYNAME } }; AddItem(pItem, sk); } /* TRACEUSER( "JustinF", _T("Registering %s at 0x%p as a member of %s\n"), (LPCTSTR) pNode->GetRuntimeClass()->m_lpszClassName, (LPVOID) pNode, (LPCTSTR) strName); */ // 'Register' the node with the set item which will note its selection // status, bounds etc. pItem->Include(pNode); return pItem; } /******************************************************************************************** > virtual SGNameItem* SGNameGroup::MakeItem(const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Purpose: Seize control of the group's title from the base class. ********************************************************************************************/ SGNameItem* SGNameGroup::MakeItem(const StringBase& strName) const { return new SGNameItem(strName); } /******************************************************************************************** > virtual void SGNameGroup::ReadGroupTitle() Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Purpose: Seize control of the group's title from the base class. ********************************************************************************************/ void SGNameGroup::ReadGroupTitle() { TitleText.Load(m_idTitle); } /******************************************************************************************** > virtual BOOL SGUsedNames::IsMember(Node* pNode, const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test for membership strName --- the set value (name) to test for equality Returns: TRUE if the given node is a member of a set within this group. SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedNames::IsMember(Node* pNode, const StringBase& strName) const { TemplateAttribute* pAttr; for (pAttr = (TemplateAttribute*) pNode->FindFirstAttr( &Node::IsAnObjectName ); pAttr != 0; pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ) ) if (strName == pAttr->GetParam()) return TRUE; return FALSE; } /******************************************************************************************** > virtual BOOL SGUsedNames::CreateItems(Node* pNode) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test/register for membership Purpose: Create 'Used Names' set items for the node, as appropriate. Returns: FALSE for an error, eg. out of memory. SeeAlso: SGNameGroup::RegisterMember; SGUsedNames::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedNames::CreateItems(Node* pNode) { TemplateAttribute* pAttr; for (pAttr = (TemplateAttribute*) pNode->FindFirstAttr( &Node::IsAnObjectName ); pAttr != 0; pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ) ) if (RegisterMember(pNode, pAttr->GetParam()) == 0) return FALSE; return TRUE; } /******************************************************************************************** > virtual BOOL SGUsedBitmaps::IsMember(Node* pNode, const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test for membership strName --- the set value (name) to test for equality Returns: TRUE if the given node is a member of the given set within this group. SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; CreateDisplayScan::CreateItems::Do NB. the value returned as pBmp can sometimes be set to 1 rather than NULL. so for the meantime test for this too ********************************************************************************************/ BOOL SGUsedBitmaps::IsMember(Node* pNode, const StringBase& strName) const { // Is it a bitmap with that value? KernelBitmap* pBmp; String_256 str; if (pNode->IsABitmap()) { pBmp = ((NodeBitmap*) pNode)->BitmapRef.GetBitmap(); if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; } // Test against bitmap transparency fills. NodeAttribute* pAttr = pNode->FindFirstAttr( &Node::IsABitmapTranspFill ); if (pAttr != 0) { pBmp = ((BitmapTranspFillAttribute*) pAttr->GetAttributeValue()) ->BitmapRef.GetBitmap(); if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; } // Test against bitmap colour fills. pAttr = pNode->FindFirstAttr( &Node::IsABitmapColourFill ); if (pAttr != 0) { pBmp = ((BitmapFillAttribute*) pAttr->GetAttributeValue()) ->BitmapRef.GetBitmap(); if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; } return FALSE; } /******************************************************************************************** > virtual BOOL SGUsedBitmaps::CreateItems(Node* pNode) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test/register for membership Purpose: Create 'Used Bitmaps' set items for the node, as appropriate. Returns: FALSE for an error, eg. out of memory. SeeAlso: SGNameGroup::RegisterMember; SGUsedBitmaps::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedBitmaps::CreateItems(Node* pNode) { // Is the object itself a kind of bitmap? KernelBitmap* pBmp; if (pNode->IsABitmap()) { pBmp = ((NodeBitmap*) pNode)->BitmapRef.GetBitmap(); if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) return FALSE; else if (pBmp != 0) return (TRUE); } // Does it have a bitmap transparency fill attribute? NodeAttribute* pAttr = pNode->FindFirstAttr( &Node::IsABitmapTranspFill ); if (pAttr != 0) { pBmp = ((BitmapTranspFillAttribute*) pAttr->GetAttributeValue()) ->BitmapRef.GetBitmap(); if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) return FALSE; else if (pBmp != 0) return (TRUE); } // Does a bitmap colour or transparency fill attribute apply to it? pAttr = pNode->FindFirstAttr( &Node::IsABitmapFill ); if (pAttr != 0 && !pAttr->IsAFractalFill()) // fractals and plasmas don't have a bitmap!!! sjk { pBmp = ((BitmapFillAttribute*) pAttr->GetAttributeValue()) ->BitmapRef.GetBitmap(); if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) return FALSE; else if (pBmp != 0) return (TRUE); } return TRUE; } /******************************************************************************************** > virtual BOOL SGUsedFonts::IsMember(Node* pNode, const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test for membership strName --- the set value (name) to test for equality Returns: TRUE if the given node is a member of the given set within this group. SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedFonts::IsMember(Node* pNode, const StringBase& strName) const { // Only consider genuine text objects. if (!pNode->IsATextChar()) return FALSE; // if (!pNode->IsABaseTextClass()) return FALSE; // Does a typeface attribute apply? AttrTxtFontTypeface* pAttr = (AttrTxtFontTypeface*) pNode->FindFirstAttr( &Node::IsATypeface ); if (pAttr == 0) return FALSE; // The same value? String_64 strFont; FONTMANAGER->GetFontName(pAttr->Value.HTypeface, strFont); return strFont == strName; } /******************************************************************************************** > virtual BOOL SGUsedFonts::CreateItems(Node* pNode) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test/register for membership Purpose: Create 'Used Fonts' set items for the node, as appropriate. Returns: FALSE for an error, eg. out of memory. SeeAlso: SGNameGroup::RegisterMember; SGUsedFonts::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedFonts::CreateItems(Node* pNode) { // Only consider genuine text objects. if (!pNode->IsATextChar()) return TRUE; // if (!pNode->IsABaseTextClass()) return TRUE; // Does a typeface attribute apply? AttrTxtFontTypeface* pAttr = (AttrTxtFontTypeface*) pNode->FindFirstAttr( &Node::IsATypeface ); if (pAttr == 0) return TRUE; // Yes, make an item for it. String_64 strFont; FONTMANAGER->GetFontName(pAttr->Value.HTypeface, strFont); return RegisterMember(pNode, strFont) != 0; } /******************************************************************************************** > virtual void SGUsedColourItem::CalcUiBounds(SGFormatInfo*, SGMiscInfo*) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: (see SGNameGroup::CalcUiBounds) Returns: The width of a colour icon plus a little gap. SeeAlso: SGNameGroup::RegisterMember; SGUsedColours::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ void SGUsedColourItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) { SGNameItem::CalcUiBounds(pFormatInfo, pMiscInfo); // Work out the new maximum bounds of the patch and the text. m_rPatch = m_rText; MILLIPOINT w = m_rPatch.Width(), h = m_rPatch.Height(); m_rPatch.hi.x = m_rPatch.lo.x + (h <= w ? h : w); m_rText.lo.x = m_rPatch.hi.x + SG_GapBeforeText / 2; // Deflate the patch a little and pixel-align. m_rPatch.Inflate(4 * -pMiscInfo->PixelSize, 4 * -pMiscInfo->PixelSize); m_rPatch.Translate(-4, 0); GridLockRect(pMiscInfo, &m_rPatch); GridLockRect(pMiscInfo, &m_rText); } /******************************************************************************************** > void SGUsedColourItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: (see SGNameItem::HandleRedraw) Purpose: Renders the colour icon for this display item. SeeAlso: SGNameItem::DrawLabel ********************************************************************************************/ void SGUsedColourItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) { SGNameItem::DrawLabel(pRedrawInfo, pMiscInfo); // Save the context, or we disturb the colour system. Set the outline. pRedrawInfo->Renderer->SaveContext(); pRedrawInfo->Renderer->SetLineWidth(0); pRedrawInfo->Renderer->SetLineColour(COLOUR_BLACK); // Make a short-lived reference to the indexed colour. DocColour dcFill; ERROR3IF(m_picSample == 0, "SGUsedColourItem::DrawLabel: no indexed colour"); dcFill.MakeRefToIndexedColour(m_picSample); pRedrawInfo->Renderer->SetFillColour(dcFill); // Render a circle for a spot colour, rectangle for others. extern void DrawCircle(RenderRegion*, DocRect&); if (m_picSample->IsSpotOrTintOfSpot()) DrawCircle(pRedrawInfo->Renderer, m_rPatch); else pRedrawInfo->Renderer->DrawRect(&m_rPatch); // Restore context as per SGDisplayColour::HandleRedraw. pRedrawInfo->Renderer->RestoreContext(); } /******************************************************************************************** > SGUsedColourItem* SGUsedColours::RegisterMember(Node* pNode, const StringBase& strName, DocColour* pCol) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Purpose: Register a 'Used Colours' set item for the node. Returns: 0 for out of memory, pointer to the SGUsedColourItem if successful. SeeAlso: SGNameGroup::RegisterMember ********************************************************************************************/ SGUsedColourItem* SGUsedColours::RegisterMember(Node* pNode, const StringBase& strName, DocColour* pCol) { SGUsedColourItem* pItem = (SGUsedColourItem*) SGNameGroup::RegisterMember(pNode, strName); ERROR3IF(pCol == 0, "SGUsedColours::RegisterMember: null input"); if (pItem != 0) pItem->SetPatchColour(pCol->FindParentIndexedColour()); return pItem; } /******************************************************************************************** > static const StringBase* SGUsedColours::IsNamedColour(DocColour* pCol) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pCol --- the colour to test for nomination Outputs: strName --- name of the colour, if any Purpose: Helper to the SGUsedColours display group. Returns: Null if the colour isn't named, the address of its name if it is. SeeAlso: DocColour::FindParentIndexedColour; IndexedColour::GetName SGUsedColours::IsMember; SGUsedColours::CreateItems ********************************************************************************************/ const StringBase* SGUsedColours::IsNamedColour(DocColour* pCol) { ERROR3IF(pCol == 0, "SGUsedColours::IsNamedColour: null input"); IndexedColour* pIndex = pCol->FindParentIndexedColour(); return pIndex != 0 && pIndex->IsNamed() ? pIndex->GetName() : 0; } /******************************************************************************************** > virtual BOOL SGUsedColours::IsMember(Node* pNode, const StringBase& strName) const Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test for membership strName --- the set value (name) to test for equality Returns: TRUE if the given node is a member of the given set within this group. SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedColours::IsMember(Node* pNode, const StringBase& strName) const { const StringBase* pstrCol; DocColour* pCol; AttrFillGeometry* pAttr; for (pAttr = (AttrFillGeometry*) pNode->FindFirstAttr( &Node::IsAFillAttr ); pAttr != 0; pAttr = (AttrFillGeometry*) pAttr->FindNextAttr( &Node::IsAFillAttr ) ) { pCol = pAttr->GetStartColour(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && *pstrCol == strName) return TRUE; } pCol = pAttr->GetEndColour(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && *pstrCol == strName) return TRUE; } pCol = pAttr->GetEndColour2(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && *pstrCol == strName) return TRUE; } pCol = pAttr->GetEndColour3(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && *pstrCol == strName) return TRUE; } } return FALSE; } /******************************************************************************************** > virtual BOOL SGUsedColours::CreateItems(Node* pNode) Author: Justin_Flude (Xara Group Ltd) Created: 27/6/99 Inputs: pNode --- the node to test/register for membership Purpose: Create 'Used Names' set items for the node, as appropriate. Returns: FALSE for an error, eg. out of memory. SeeAlso: SGNameGroup::RegisterMember; SGUsedColours::IsMember; CreateDisplayScan::CreateItems::Do ********************************************************************************************/ BOOL SGUsedColours::CreateItems(Node* pNode) { const StringBase* pstrCol; DocColour* pCol; AttrFillGeometry* pAttr; for (pAttr = (AttrFillGeometry*) pNode->FindFirstAttr( &Node::IsAFillAttr ); pAttr != 0; pAttr = (AttrFillGeometry*) pAttr->FindNextAttr( &Node::IsAFillAttr )) { pCol = pAttr->GetStartColour(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) return FALSE; } pCol = pAttr->GetEndColour(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) return FALSE; } pCol = pAttr->GetEndColour2(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) return FALSE; } pCol = pAttr->GetEndColour3(); if (pCol != 0) { pstrCol = IsNamedColour(pCol); if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) return FALSE; } } return TRUE; }