00001 // $Id: ngitem.cpp 1488 2006-07-20 15:31:34Z phil $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 /* 00099 $Header: /Camelot/kernel/ngitem.cpp 17 22/11/04 18:55 Phil $ 00100 Attribute gallery display items 00101 */ 00102 00103 #include "camtypes.h" 00104 00105 #include "ngcore.h" 00106 #include "ngdrag.h" 00107 #include "ngitem.h" 00108 #include "ngprop.h" 00109 #include "ngscan.h" 00110 #include "ngsentry.h" 00111 #include "ngsetop.h" 00112 00113 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "docrect.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00116 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 #include "dragmgr.h" 00118 #include "keypress.h" 00119 00120 //#include "bitmap.h" // bitmaps - in camtypes.h [AUTOMATICALLY REMOVED] 00121 #include "nodebmp.h" 00122 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00123 00124 //#include "cxfrech.h" // names - in camtypes.h [AUTOMATICALLY REMOVED] 00125 //#include "attrval.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00126 #include "userattr.h" 00127 #include "tmpltatr.h" 00128 00129 #include "fontman.h" // fonts 00130 //#include "txtattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00131 #include "nodetext.h" 00132 00133 //#include "doccolor.h" // colours - in camtypes.h [AUTOMATICALLY REMOVED] 00134 #include "colourix.h" 00135 00136 //#include "galres.h" 00137 //#include "mario.h" 00138 //#include "justin3.h" 00139 #include "slicehelper.h" 00140 #include "fillattr2.h" 00141 00142 #ifdef _DEBUG 00143 #undef THIS_FILE 00144 static char BASED_CODE THIS_FILE[] = __FILE__; 00145 #endif 00146 00147 DECLARE_SOURCE("$Revision: 1488 $"); 00148 00149 // Implement the dynamic class bits... 00150 CC_IMPLEMENT_DYNAMIC(SGNameItem, SGDisplayItem); 00151 CC_IMPLEMENT_DYNAMIC(SGNameGroup, SGDisplayGroup); 00152 00153 // This line mustn't go before any CC_IMPLEMENT_... macros 00154 #define new CAM_DEBUG_NEW 00155 00156 00157 /*********************************************************************************************** 00158 > SGNameItem::SGNameItem(const StringBase& strName) 00159 00160 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00161 Created: 27/6/99 00162 Inputs: strName - the name ('attribute value') of this set item. 00163 Purpose: Construct an SGNameItem. 00164 ***********************************************************************************************/ 00165 00166 SGNameItem::SGNameItem(const StringBase& strName) 00167 : m_strName(strName), 00168 m_pCachedPropertyNode(0), 00169 m_nNodes(0), 00170 m_nObjects(0), 00171 m_nSelected(0) 00172 { 00173 // TRACEUSER( "JustinF", _T("SGNameItem::SGNameItem(%s)\n"), (LPCTSTR) m_strName); 00174 } 00175 00176 00177 00178 /*********************************************************************************************** 00179 > virtual void SGNameItem::GetNameText(String_256* pResult) 00180 00181 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00182 Created: 9/3/99 00183 Outputs: On exit, the string pointed at by Result will contain either a blank 00184 string, or the name text associated with this item (if any) 00185 Purpose: To determine a name string for this node. Generally, this is used for 00186 a simple mechanism which searches for display items whose names match 00187 given search parameters in some way. It is also used in libraries to 00188 provide default redraw methods. 00189 Notes: **** TO DO **** 00190 Modify this method to return the correct text. You may also want to 00191 add an override for the GetFullInfoText() method if you can provide 00192 a full-info display mode. 00193 SeeAlso: SGDisplayNode::GetNameText 00194 ***********************************************************************************************/ 00195 00196 void SGNameItem::GetNameText(String_256* pResult) 00197 { 00198 ERROR3IF(pResult == 0, "SGNameItem::GetNameText: illegal null param"); 00199 *pResult = m_strName; 00200 } 00201 00202 00203 00204 /*********************************************************************************************** 00205 > SGNameProp* SGNameItem::GetProperty(INT32 nIndex = -1) const 00206 00207 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00208 Created: 27/6/99 00209 Inputs: nIndex --- the index of the property to retrieve (default is the 00210 current property) 00211 Returns: The property associated with this item of the given type (index). NB. the 00212 item remains responsible for deallocation of the property. 00213 SeeAlso: SGNameProp; NodeSetProperty; NodeSetSentinel 00214 ***********************************************************************************************/ 00215 00216 SGNameProp* SGNameItem::GetProperty(INT32 nIndex) const 00217 { 00218 // No document means no properties. 00219 Document* pDoc = Document::GetSelected(); 00220 if (pDoc == 0) return 0; 00221 00222 // Only 'Used Names' have properties (for now). 00223 if (GetParent() != NameGallery::Instance()->GetUsedNames()) 00224 return 0; 00225 00226 // Fetch the current property? 00227 if (nIndex == -1) nIndex = NameGallery::Instance()->GetPropertyIndex(); 00228 ERROR3IF(nIndex < 0 || nIndex >= SGNameProp::nPropertyCount, 00229 "SGNameItem::GetProperty: index out of range"); 00230 00231 // Retrieve the SGNameProp* from the associated NodeSetProperty. 00232 NodeSetProperty* pSetProp = pDoc->GetSetSentinel()->FindPropertyNode(m_strName); 00233 if (pSetProp == 0) return 0; 00234 SGNameProp* pProp = pSetProp->GetProperty(nIndex); 00235 ERROR3IF(pProp == 0, "SGNameItem::GetProperty: no property"); 00236 return pProp; 00237 } 00238 00239 00240 00241 /*********************************************************************************************** 00242 > void SGNameItem::Reset(BOOL fPropagateChanges) 00243 00244 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00245 Created: 27/6/99 00246 Inputs: fPropagateChanges --- TRUE if all bounds records should be sync'ed (?) 00247 Purpose: Resets the state of the object in preparation for a refresh 00248 ***********************************************************************************************/ 00249 00250 void SGNameItem::Reset(BOOL fPropagateChanges) 00251 { 00252 // Remember the old bounds of the set and reset all running totals. 00253 if (fPropagateChanges) m_rOldSetBounds = m_rSetBounds; 00254 m_rSetBounds.MakeEmpty(); 00255 m_rSelectBounds.MakeEmpty(); 00256 m_nNodes = m_nObjects = m_nSelected = 0; 00257 m_pCachedPropertyNode = 0; 00258 } 00259 00260 00261 /*********************************************************************************************** 00262 > NodeSetProperty* SGNameItem::GetPropertyNode() 00263 00264 Author: Simon_Knight (Xara Group Ltd) <camelotdev@xara.com> 00265 Created: 17/3/00 00266 Purpose: returns a cached ptr to this sets property node. 00267 This is NULLed in Reset() and filled with a search on demand 00268 ***********************************************************************************************/ 00269 NodeSetProperty* SGNameItem::GetPropertyNode() 00270 { 00271 // scan for the property node and cache this ptr 00272 return (m_pCachedPropertyNode != 0) 00273 ? m_pCachedPropertyNode 00274 : m_pCachedPropertyNode = 00275 Document::GetCurrent()->GetSetSentinel()->FindPropertyNode(m_strName); 00276 } 00277 00278 00279 00280 /*********************************************************************************************** 00281 > void SGNameItem::Include(Node* pNode) 00282 00283 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00284 Created: 27/6/99 00285 Inputs: pNode --- the node to "register" 00286 Purpose: Called by the CreateScan::Do when a node is discovered that is a member 00287 of this set item. Updates the running totals of member objects and 00288 selected member objects. 00289 ***********************************************************************************************/ 00290 00291 void SGNameItem::Include(Node* pNode) 00292 { 00293 // Count nodes, including the sentinel. 00294 ++m_nNodes; 00295 if (pNode->IsNodeRenderableClass()) 00296 { 00297 // Count selectable (renderable) nodes. 00298 ++m_nObjects; 00299 BOOL fSelect = (pNode->IsSelected() || pNode->IsChildOfSelected()) || (pNode->IsCompound() && pNode->IsParentOfSelected()); 00300 if (fSelect) ++m_nSelected; 00301 00302 // Accumulate bounds of objects, and just those selected. 00303 if (pNode->IsBounded()) 00304 { 00305 DocRect rBounds = SliceHelper::BoundingNodeSize(pNode); 00306 m_rSetBounds = m_rSetBounds.Union(rBounds); 00307 if (fSelect) m_rSelectBounds = m_rSelectBounds.Union(rBounds); 00308 } 00309 } 00310 } 00311 00312 00313 00314 /*********************************************************************************************** 00315 > virtual INT32 SGNameItem::CompareTo(SGDisplayNode* pOther, INT32 nKey) 00316 00317 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00318 Created: 27/6/99 00319 Inputs: (see SGDisplayNode::CompareTo) 00320 Returns: -1 if comparison is < 00321 0 if = 00322 +1 if > 00323 Purpose: Overrides the default comparator so that it takes into accounted 00324 appended numbers. 00325 ***********************************************************************************************/ 00326 00327 INT32 SGNameItem::CompareTo(SGDisplayNode* pItem, INT32 nKey) 00328 { 00329 ERROR3IF(pItem == 0, "SGNameItem::CompareTo: null input"); 00330 ERROR3IF(!pItem->IS_KIND_OF(SGNameItem), "SGNameItem::CompareTo: not an SGNameItem"); 00331 00332 switch (nKey) 00333 { 00334 case SGSORTKEY_BYNAME: 00335 { 00336 // Compare the strings character by character until we can determine their 00337 // lexical order. If the characters to be compared are numeric, then parse 00338 // and compare them as ordinals. 00339 LPCTSTR pchThis = m_strName, pchOther = ((SGNameItem*) pItem)->m_strName; 00340 for (;;) 00341 { 00342 // Eat up any whitespace. 00343 while (StringBase::IsSpace(*pchThis)) pchThis = camStrinc(pchThis); 00344 while (StringBase::IsSpace(*pchOther)) pchOther = camStrinc(pchOther); 00345 00346 // Check if we've reached the end of the strings. If we have reached 00347 // the end of both, they are equal. Otherwise the one that is shortest 00348 // is 'lower'. 00349 if (*pchThis == TEXT('\0')) 00350 return (*pchOther == TEXT('\0')) ? 0 : -1; 00351 else if (*pchOther == TEXT('\0')) 00352 return 1; 00353 00354 // Are the next two characters to be compared numeric? 00355 if (StringBase::IsNumeric(*pchThis) && StringBase::IsNumeric(*pchOther)) 00356 { 00357 // Span and copy the integers embedded in each string. 00358 String_256 strThisNum, strOtherNum; 00359 LPTSTR pchThisNum = strThisNum, pchOtherNum = strOtherNum; 00360 00361 do { 00362 *pchThisNum = *pchThis; 00363 pchThisNum = camStrinc(pchThisNum); 00364 pchThis = camStrinc(pchThis); 00365 } while (StringBase::IsNumeric(*pchThis)); 00366 00367 do { 00368 *pchOtherNum = *pchOther; 00369 pchOtherNum = camStrinc(pchOtherNum); 00370 pchOther = camStrinc(pchOther); 00371 } while (StringBase::IsNumeric(*pchOther)); 00372 00373 *pchThisNum = *pchOtherNum = TEXT('\0'); 00374 00375 // Convert and compare the numbers. 00376 INT32 nThis, nOther; 00377 Convert::StringToLong( strThisNum, &nThis ); 00378 Convert::StringToLong( strOtherNum, &nOther ); 00379 if (nThis < nOther) 00380 return -1; 00381 else if (nThis > nOther) 00382 return 1; 00383 00384 // Restart all tests as we may now be pointing at a null or a space. 00385 continue; 00386 } 00387 00388 // The characters are not both numeric, so perform a normal comparison. 00389 INT32 nTest = *pchOther - *pchThis; 00390 PORTNOTE("other", "Removed CompareString, rwplace with simple subtraction" ) 00391 #if !defined(EXCLUDE_FROM_XARALX) 00392 ::CompareString(LOCALE_USER_DEFAULT, 00393 NORM_IGNOREKANATYPE | 00394 NORM_IGNOREWIDTH | 00395 NORM_IGNORECASE, 00396 pchThis, 1, pchOther, 1) - 2; 00397 #endif 00398 00399 if (nTest != 0) return nTest; 00400 00401 // The strings are still equal so compare the next characters. 00402 pchThis = camStrinc(pchThis); 00403 pchOther = camStrinc(pchOther); 00404 } 00405 } 00406 break; 00407 00408 default: 00409 // Let the base class handle all other types of comparison. 00410 return SGDisplayItem::CompareTo(pItem, nKey); 00411 } 00412 00413 return 0; 00414 } 00415 00416 00417 00418 /*********************************************************************************************** 00419 > virtual void SGNameItem::DragWasReallyAClick(SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo) 00420 00421 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00422 Created: 27/6/99 00423 Inputs: (see SGDisplayNode::DragWasReallyACick) 00424 Purpose: Called by the dragging code when a drag turns out to be a 00425 mundane single click. 00426 ***********************************************************************************************/ 00427 00428 void SGNameItem::DragWasReallyAClick(SGMouseInfo* pMouseInfo, SGMiscInfo* pMiscInfo) 00429 { 00430 // NB. called post-drag. 00431 DefaultClickHandler(pMouseInfo, pMiscInfo, TRUE); 00432 } 00433 00434 00435 00436 /******************************************************************************************** 00437 > virtual BOOL SGNameItem::GetBubbleHelp(DocCoord *pMousePos, String_256 *pResult) 00438 00439 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00440 Created: 16/4/99 00441 Inputs: pMousePos - The current mouse position. This will generally be expected 00442 to lie inside this item's FormatRect. With it, this item can provide 00443 help on specific areas of an item. 00444 Outputs: On exit, if the return value is TRUE, the string pointed at by Result 00445 will contain a bubble help string for this item 00446 Returns: TRUE if it filled in the string, FALSE if it did not 00447 Purpose: Called by the parent gallery when bubble help is needed. The parent 00448 gallery will do a hit test to determine which node contains the pointer, 00449 and will then ask that node to supply bubble/status-line help. 00450 Notes: The base class returns FALSE (i.e. provides no help) 00451 If you can provide help, then override the base class method to do so. 00452 SeeAlso: SGDisplayNode::GetStatusLineHelp 00453 ********************************************************************************************/ 00454 00455 BOOL SGNameItem::GetBubbleHelp(DocCoord* pMousePos, String_256* pResult) 00456 { 00457 ERROR3IF(pResult == 0, "SGNameItem::GetBubbleHelp: invalid null params"); 00458 00459 // Matt - 16/09/2000 - Added for tooltip help over properties 00460 // Work out which UI item is hovered over, if any... 00461 if (m_nObjects > 0 && m_rProp.ContainsCoord(*pMousePos)) 00462 { 00463 //Then we're hovering over the properties section... 00464 SGNameProp* pProp = GetProperty(); 00465 if (pProp->GetIndex() == 0) 00466 { 00467 //Then it's an EXPORT property 00468 TRACEUSER( "matt", _T("...EXPORTY...\n")); 00469 } 00470 else if (pProp->GetIndex() == 1) 00471 { 00472 //Then it's a SLICE tickbox 00473 TRACEUSER( "matt", _T("SLICEY...\n")); 00474 } 00475 else if (pProp->GetIndex() == 2) 00476 { 00477 //Then it's a STRETCH tickbox 00478 TRACEUSER( "matt", _T("...STRETCHY...\n")); 00479 } 00480 00481 String strNameGal( _R(IDBBL_NAMEGAL_NONE) ); 00482 return pResult->MakeMsg(_R(IDBBL_NAMEGAL_ITEM), &strNameGal, &m_strName); 00483 } 00484 else 00485 { 00486 // Work out the intersection with the user selection. 00487 UINT32 id; 00488 if (IsNoneSelected()) 00489 id = _R(IDBBL_NAMEGAL_NONE); 00490 else if (IsAllSelected()) 00491 id = _R(IDBBL_NAMEGAL_ALL); 00492 else 00493 id = _R(IDBBL_NAMEGAL_SOME); 00494 00495 // Create the bubble help text. 00496 String strNameGal( id ); 00497 return pResult->MakeMsg(_R(IDBBL_NAMEGAL_ITEM), &strNameGal, &m_strName); 00498 } 00499 } 00500 00501 00502 00503 /********************************************************************************************** 00504 > virtual BOOL SGNameItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) 00505 00506 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00507 Created: 16/4/99 00508 Inputs: pMousePos - The current mouse position. This will generally be expected 00509 to lie inside this item's FormatRect. With it, this item can provide 00510 help on specific areas of an item. 00511 Outputs: On exit, if the return value is TRUE, the string pointed at by Result 00512 will contain a status line help string for this item 00513 Returns: TRUE if it filled in the string, FALSE if it did not 00514 Purpose: Called by the parent gallery when status line help is needed. The parent 00515 gallery will do a hit test to determine which node contains the pointer, 00516 and will then ask that node to supply bubble/status-line help. 00517 Notes: The base class returns FALSE (i.e. provides no help) 00518 If you can provide help, then override the base class method to do so. 00519 SeeAlso: SGDisplayNode::GetBubbleHelp 00520 **********************************************************************************************/ 00521 00522 BOOL SGNameItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) 00523 { 00524 // Matt - 16/09/2000 - Added for statusbar help over properties 00525 // Work out which UI item is hovered over, if any... 00526 if (m_nObjects > 0 && m_rProp.ContainsCoord(*pMousePos)) 00527 { 00528 //Then we're hovering over the properties section... 00529 SGNameProp* pProp = GetProperty(); 00530 if (pProp->GetIndex() == 0) 00531 { 00532 //Then it's an EXPORT property 00533 TRACEUSER( "matt", _T("...EXPORTY...\n")); 00534 return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPEXPORTOPT)); 00535 } 00536 else if (pProp->GetIndex() == 1) 00537 { 00538 //Then it's a SLICE tickbox 00539 TRACEUSER( "matt", _T("SLICEY...\n")); 00540 return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPSLICE)); 00541 } 00542 else if (pProp->GetIndex() == 2) 00543 { 00544 //Then it's a STRETCH tickbox 00545 TRACEUSER( "matt", _T("...STRETCHY...\n")); 00546 return pResult->MakeMsg(_R(IDBBL_NAMEGAL_PROPSTRETCH)); 00547 } 00548 } 00549 else 00550 { 00551 String strSel; 00552 00553 // Intersect this item's set with the selected objects. 00554 if (IsNoneSelected()) 00555 strSel = _R(IDBBL_NAMEGAL_NONE); 00556 else if (IsAllSelected()) 00557 strSel = _R(IDBBL_NAMEGAL_ALL); 00558 else 00559 strSel = _R(IDBBL_NAMEGAL_SOME); 00560 00561 strSel.toLower(); 00562 00563 // What is the mouse pointing at? 00564 UINT32 idMask; 00565 SGNameGroup* pGroup = (SGNameGroup*) GetParent(); 00566 if (m_rToggle.ContainsCoord(*pMousePos)) 00567 // Over the selection toggle gadget. 00568 idMask = _R(IDST_NAMEGAL_ITEM_SEL_GADGET); 00569 else if (pGroup == NameGallery::Instance()->GetUsedNames()) 00570 // Over a 'Used Name' 00571 idMask = _R(IDST_NAMEGAL_NAME_ITEM); 00572 else 00573 // Over 'Used' something else. 00574 idMask = _R(IDST_NAMEGAL_OTHER_ITEM); 00575 00576 // Build up a specific message. 00577 String strType(pGroup->GetTypeID()); 00578 return pResult->MakeMsg(idMask, &strSel, &m_strName, &strType, &strType); 00579 } 00580 00581 // It failed, so return FALSE. 00582 return FALSE; 00583 } 00584 00585 00586 00587 /*********************************************************************************************** 00588 > virtual void SGNameItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) 00589 00590 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00591 Created: 27/6/99 00592 Inputs: pFormatInfo --- formatting info from which to calculate my position/size 00593 pMiscInfo --- the window dimensions, pixel size etc 00594 Purpose: Calculates the bounds of the distinct UI items that make up a line in 00595 the Attribute gallery. 00596 Notes: Member variable FormatRect should be set up (before calling this method) 00597 to be the rectangle in which to draw this item. 00598 SeeAlso: SGNameItem::HandleRedraw; SGNameItem::HandleEvent 00599 ***********************************************************************************************/ 00600 00601 void SGNameItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) 00602 { 00603 // pMiscInfo can't be null (pFormatInfo can be as it's not very useful). 00604 ERROR3IF(pMiscInfo == 0, "SGNameItem::CalcUiBounds: null input/output argument"); 00605 00606 // Work out the maximum bounds of the toggle gadget, label and property. 00607 m_rText = FormatRect; 00608 m_rText.hi.x -= SG_GapBeforeText / 2; 00609 m_rToggle = m_rText; 00610 m_rToggle.hi.x = m_rToggle.lo.x + SG_DefaultSmallIcon; 00611 m_rText.lo.x = m_rToggle.hi.x + SG_GapBeforeText; 00612 00613 // Split the label bounds with the property. 00614 SGNameProp* pProp = GetProperty(); 00615 if (pProp == 0) 00616 m_rProp.MakeEmpty(); 00617 else 00618 { 00619 m_rProp = m_rText; 00620 PORTNOTE("other", "Removed SuperGallery related stuff" ) 00621 #if !defined(EXCLUDE_FROM_XARALX) 00622 pProp->CalcUiBounds(this, pFormatInfo, pMiscInfo, &m_rProp); 00623 #endif 00624 m_rText.hi.x = m_rProp.lo.x - SG_GapBeforeText; 00625 } 00626 00627 // Pixel-align. 00628 GridLockRect(pMiscInfo, &m_rToggle); 00629 GridLockRect(pMiscInfo, &m_rText); 00630 GridLockRect(pMiscInfo, &m_rProp); 00631 } 00632 00633 00634 00635 /*********************************************************************************************** 00636 > virtual void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) 00637 00638 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00639 Created: 27/6/99 00640 Inputs: pFormatInfo - The formatting info from which to calculate my position/size 00641 Outputs: pMiscInfo - As usual, the useful misc info struct 00642 member variable FormatRect - is returned filled in with the size/position of 00643 this NameItem item's display area. This is dependent upon the current display 00644 mode and format state. FormatInfo will be updated as a result of the formatting 00645 operation. 00646 Purpose: Shared code for NameItem items to calculate where they will appear in the 00647 grand scheme of things 00648 ***********************************************************************************************/ 00649 00650 void SGNameItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) 00651 { 00652 CalculateFormatRect(pFormatInfo, pMiscInfo, SG_InfiniteWidth, SG_DefaultSmallIcon); 00653 CalcUiBounds(pFormatInfo, pMiscInfo); 00654 } 00655 00656 00657 00658 /*********************************************************************************************** 00659 > virtual void SGNameItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) 00660 00661 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00662 Created: 27/6/99 00663 Inputs: pRedrawInfo --- the information on the kernel-rendered redraw area 00664 pMiscInfo --- the drawing context information structure 00665 Purpose: Default implementation for drawing the label of an item, the renderer 00666 has already been set up with default attributes. 00667 Notes: Member variable FormatRect should be set up (before calling this method) 00668 to be the rectangle in which to draw this item. 00669 SeeAlso: SGNameItem::CalcUiBounds 00670 ***********************************************************************************************/ 00671 00672 void SGNameItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) 00673 { 00674 pRedrawInfo->Renderer->DrawFixedSystemText(&m_strName, m_rText); 00675 } 00676 00677 00678 00679 /*********************************************************************************************** 00680 > virtual void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, 00681 SGFormatInfo* pFormatInfo) 00682 00683 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00684 Created: 27/6/99 00685 Inputs: pRedrawInfo --- the information on the kernel-rendered redraw area 00686 pFormatInfo --- the formatting information structure 00687 Purpose: SGNameItem item redraw method - removed from the main HandleEvent 00688 method merely to make the code tidier. 00689 Notes: Member variable FormatRect should be set up (before calling this method) 00690 to be the rectangle in which to draw this item. 00691 SeeAlso: SGNameItem::CalcUiBounds 00692 ***********************************************************************************************/ 00693 00694 void SGNameItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) 00695 { 00696 // Set the foreground and background colours according to whether this item is 00697 // gallery selected or not. 00698 DocColour dcolForegnd, dcolBackgnd; 00699 if (Flags.Selected) 00700 { 00701 dcolForegnd = pRedrawInfo->SelForeground; 00702 dcolBackgnd = pRedrawInfo->SelBackground; 00703 } 00704 else 00705 { 00706 // Unselected items are in the 'selected' colour if the user selection includes 00707 // any of their members. 00708 dcolBackgnd = pRedrawInfo->Background; 00709 dcolForegnd = pRedrawInfo->Foreground; 00710 } 00711 00712 // Render the unhighlighted background. 00713 pRedrawInfo->Renderer->SetFillColour(pRedrawInfo->Background); 00714 pRedrawInfo->Renderer->SetLineColour(pRedrawInfo->Transparent); 00715 pRedrawInfo->Renderer->SetLineWidth(0); 00716 pRedrawInfo->Renderer->DrawRect(&m_rToggle); 00717 pRedrawInfo->Renderer->DrawRect(&m_rProp); 00718 00719 // Render highlighted background. 00720 pRedrawInfo->Renderer->SetFillColour(dcolBackgnd); 00721 pRedrawInfo->Renderer->DrawRect(&m_rText); 00722 00723 // Render the selection toggle gadget, on the left, if the set isn't empty. 00724 if (!IsEmpty()) 00725 { 00726 UINT32 idBmp; 00727 if (IsNoneSelected()) 00728 idBmp = _R(IDB_NAMEGAL_NONESEL); 00729 else if (IsAllSelected()) 00730 idBmp = _R(IDB_NAMEGAL_ALLSEL); 00731 else 00732 idBmp = _R(IDB_NAMEGAL_SOMESEL); 00733 00734 pRedrawInfo->Renderer->DrawBitmap(m_rToggle.lo, idBmp); 00735 } 00736 00737 // Render the label of the item, in the middle. 00738 pRedrawInfo->Renderer->SetFixedSystemTextColours(&dcolForegnd, &dcolBackgnd); 00739 DrawLabel(pRedrawInfo, pMiscInfo); 00740 00741 // Render the property, on the right. 00742 if (m_nObjects > 0) 00743 { 00744 PORTNOTE("other", "Removed SuperGallery related stuff" ) 00745 #if !defined(EXCLUDE_FROM_XARALX) 00746 SGNameProp* pProp = GetProperty(); 00747 if (pProp != 0) pProp->HandleRedraw(this, pRedrawInfo, pMiscInfo, m_rProp); 00748 #endif 00749 } 00750 } 00751 00752 00753 00754 /*********************************************************************************************** 00755 > virtual BOOL SGNameItem::HandleEvent(SGEventType nEventType, void* pEventInfo, 00756 SGMiscInfo* pMiscInfo) 00757 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00758 Created: 17/4/99 00759 Inputs: nEventType - an enumerated value describing what type of event is to be processed 00760 pEventInfo - a structure describing the event (may be 0). The exact thing 00761 pointed at by this pointer depends upon the event type: 00762 00763 SGEVENT_FORMAT 0 00764 SGEVENT_REDRAW (SGRedrawInfo*) 00765 SGEVENT_BGREDRAW 0 00766 SGEVENT_BGFLUSH 0 - May have 0 MiscInfo 00767 SGEVENT_MOUSECLICK (SGMouseInfo*) 00768 SGEVENT_DRAGSTARTED (DragMessage*) 00769 SGEVENT_CLAIMPOINT (SGMouseInfo*) 00770 SGEVENT_THUMBMSG (ThumbMessage*) - May have 0 MiscInfo 00771 00772 Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this 00773 information - they provide useful error/type checking, and hide the cast 00774 00775 pMiscInfo - almost always provided. Contains a few useful bits of info that 00776 may be needed for all event types. This may be 0 for special event types 00777 (see sgtree.h for the enum and information on which ones may pass 0 MiscInfo 00778 - currently this is _THUMBMSG and _BGFLUSH, neither of which should concern 00779 you - so as long as you only reference MiscInfo once you know the event type, 00780 you will be safe) 00781 00782 Outputs: *pFormatInfo is updated as appropriate 00783 Returns: TRUE if the event was handled successfully, FALSE if it was not. 00784 Purpose: Handles a SuperGallery display event. 00785 Notes: VERY IMPORTANT: The rendering must be enclosed by calls to StartRendering 00786 and StopRendering, to ensure that rendering works properly (in the future 00787 we may change the redraw system to use a GRenderRegion for each individual 00788 item, rather than one global one for the window, for which these calls will 00789 be essential) 00790 SeeAlso: SGDisplayItem::HandleEvent; SGNameItem::CalcUiBounds 00791 ***********************************************************************************************/ 00792 00793 BOOL SGNameItem::HandleEvent(SGEventType nEventType, void* pEventInfo, SGMiscInfo* pMiscInfo) 00794 { 00795 switch (nEventType) 00796 { 00797 case SGEVENT_FORMAT: 00798 { 00799 SGFormatInfo* pFormatInfo = GetFormatInfo(nEventType, pEventInfo); 00800 CalculateMyRect(pFormatInfo, pMiscInfo); 00801 CalcUiBounds(0, pMiscInfo); 00802 break; 00803 } 00804 00805 case SGEVENT_REDRAW: 00806 { 00807 DocRect MyRect(FormatRect); // Rely on FormatRect being cached from above 00808 SGRedrawInfo* pRedrawInfo = GetRedrawInfo(nEventType, pEventInfo); 00809 if (IMustRedraw(pRedrawInfo)) 00810 { 00811 StartRendering(pRedrawInfo, pMiscInfo); 00812 pRedrawInfo->Renderer->SaveContext(); 00813 HandleRedraw(pRedrawInfo, pMiscInfo); 00814 pRedrawInfo->Renderer->RestoreContext(); 00815 StopRendering(pRedrawInfo, pMiscInfo); 00816 } 00817 break; 00818 } 00819 00820 case SGEVENT_MOUSECLICK: 00821 { 00822 // Work out which UI item has been clicked on, if any. 00823 SGMouseInfo* pMouseInfo = GetMouseInfo(nEventType, pEventInfo); 00824 if (m_rToggle.ContainsCoord(pMouseInfo->Position)) 00825 { 00826 TRACEUSER( "matt", _T("m_rToggle Contains the Mouse Coords\n")); 00827 if (m_nObjects > 0) 00828 { 00829 TRACEUSER( "matt", _T("Num Objects > 0\n")); 00830 // It's a click on the selection toggle gadget for some objects. 00831 SelectScan::Change eChange; 00832 if (KeyPress::IsGalleryCtrlPressed()) 00833 eChange = SelectScan::TOGGLE; 00834 else if (IsAllSelected()) 00835 eChange = SelectScan::DESELECT; 00836 else 00837 eChange = SelectScan::SELECT; 00838 00839 // Change the selection state of the objects within this set item and 00840 // claim the event. 00841 OpDescriptor* pDesc = 00842 OpDescriptor::FindOpDescriptor(OPTOKEN_SELECT_SET); 00843 ERROR3IF(pDesc == 0, "SGNameItem::HandleEvent: no descriptor"); 00844 00845 OpParam param( this, INT32(eChange) ); 00846 pDesc->Invoke( ¶m ); 00847 return TRUE; 00848 } 00849 } 00850 00851 else if (m_nObjects > 0 && m_rProp.ContainsCoord(pMouseInfo->Position)) 00852 { 00853 TRACEUSER( "matt", _T("m_rToggle DOES NOT contain MouseCoords, m_rProp DOES\n")); 00854 00855 PORTNOTE("other", "Removed SuperGallery related stuff" ) 00856 #if !defined(EXCLUDE_FROM_XARALX) 00857 // It's a click on the property UI. Pass it on and claim it. 00858 SGNameProp* pProp = GetProperty(); 00859 if (pProp != 0 && !pProp->HandleMouse(this, pMouseInfo, pMiscInfo)) 00860 { 00861 InformError(); 00862 return FALSE; 00863 } 00864 #endif 00865 return TRUE; 00866 } 00867 00868 else if (m_rText.ContainsCoord(pMouseInfo->Position) || 00869 (m_nObjects == 0 && m_rProp.ContainsCoord(pMouseInfo->Position))) 00870 { 00871 TRACEUSER( "matt", _T("m_rText contains MouseCoords OR m_rProp DOES\n")); 00872 00873 // It's a click on the text label. If a name is clicked then (always) 00874 // start dragging it. If the click isn't really a drag then 00875 // DragWasReallyAClick will be called when the drag is cancelled. 00876 DefaultPreDragHandler(pMouseInfo, pMiscInfo); 00877 PORTNOTE("other", "Removed bitmap drag handling BitmapDragInformation"); 00878 #ifndef EXCLUDE_FROM_XARALX 00879 if (GetParent() == NameGallery::Instance()->GetUsedNames()) 00880 { 00881 // It's a name (ie. a child of the 'Used Names' group), so create and run 00882 // a drag operation. 00883 SGNameDrag* pDragInfo = new SGNameDrag(this, pMouseInfo, pMiscInfo); 00884 ERRORIF(pDragInfo == 0, _R(IDE_NOMORE_MEMORY), FALSE); 00885 DragManagerOp::StartDrag(pDragInfo, GetListWindow()); 00886 } 00887 else 00888 #endif 00889 // Not a name so just do the default, but don't close on 00890 // adjust-double-click. 00891 DefaultClickHandler(pMouseInfo, pMiscInfo, FALSE); 00892 00893 TRACEUSER("JustinF", 00894 _T("%s \"%s\" at 0x%p --- %d nodes, %d objects, %d selected\n"), 00895 (LPCTSTR) String(((SGNameGroup*) GetParent())->GetTypeID()), 00896 (LPCTSTR) m_strName, (LPVOID) this, 00897 m_nNodes, m_nObjects, m_nSelected); 00898 00899 // Claim this click. 00900 return TRUE; 00901 } 00902 00903 TRACEUSER( "matt", _T("Click outside bounds of item's UI\n")); 00904 // The click was outside the bounds of the item's UI gadgets. 00905 break; 00906 } 00907 /* 00908 // Matt - 15/09/2000 - Added for tooltip help over properties 00909 case SGEVENT_CLAIMPOINT: 00910 { 00911 // Work out which UI item is hovered over, if any... 00912 SGClaimPointInfo *pMouseInfo = GetClaimPointInfo(nEventType, pEventInfo); 00913 if (!m_rToggle.ContainsCoord(pMouseInfo->Position) && m_nObjects > 0 && m_rProp.ContainsCoord(pMouseInfo->Position)) 00914 { 00915 //Then we're hovering over the properties section... 00916 SGNameProp* pProp = GetProperty(); 00917 00918 if (pProp->GetIndex() == 0) 00919 { 00920 //Then it's an EXPORT property 00921 TRACEUSER( "matt", _T("...EXPORTY...\n")); 00922 } 00923 else if (pProp->GetIndex() == 1) 00924 { 00925 //Then it's a SLICE tickbox 00926 TRACEUSER( "matt", _T("SLICEY...\n")); 00927 } 00928 else if (pProp->GetIndex() == 2) 00929 { 00930 //Then it's a STRETCH tickbox 00931 TRACEUSER( "matt", _T("...STRETCHY...\n")); 00932 } 00933 00934 // if (pProp != 0 && !pProp->HandleMouse(this, pMouseInfo, pMiscInfo)) 00935 // { 00936 // InformError(); 00937 // return FALSE; 00938 // } 00939 return true; 00940 } 00941 break; 00942 } 00943 */ 00944 default: 00945 // Let the base class handle any events we don't know about. 00946 // This includes things like hit testing (CLAIMPOINT) etc 00947 return SGDisplayItem::HandleEvent(nEventType, pEventInfo, pMiscInfo); 00948 } 00949 00950 // Default return value: we do not claim this event, so it will be passed on to others. 00951 return FALSE; 00952 } 00953 00954 // is this name group item a backbar? 00955 BOOL SGNameItem::IsABackBar() 00956 { 00957 String_256 SubName = m_strName; 00958 *(((TCHAR *)SubName) + 7) = 0; 00959 return ( SubName == _T("BackBar") ); 00960 } 00961 00962 00963 00964 00969 00970 00971 00972 00973 /******************************************************************************************** 00974 > SGNameGroup::SGNameGroup(UINT32 idType, Document* pDoc = 0) 00975 00976 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 00977 Created: 27/6/99 00978 Inputs: pDoc --- the document associated with this group (by default, 00979 always whatever is the currently 'selected' document) 00980 Purpose: Creates an abstract Name Gallery group. 00981 Notes: Uses the lowest bit of SGDisplayFlags.Reserved to track whether a group 00982 has been automatically folded because it has no items (and hence should 00983 automatically unfold if it later has new items to show). 00984 ********************************************************************************************/ 00985 00986 SGNameGroup::SGNameGroup(UINT32 idType, UINT32 idTitle, Document* pDoc) 00987 : SGDisplayGroup(NameGallery::Instance(), pDoc), 00988 m_idType(idType), 00989 m_idTitle(idTitle) 00990 { 00991 Flags.CanSelect = TRUE; 00992 Flags.Reserved &= ~1; 00993 } 00994 00995 00996 00997 /******************************************************************************************** 00998 > virtual UINT32 SGNameGroup::GetTypeID() const 00999 01000 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01001 Created: 27/6/99 01002 Returns: The ID of a string that describes the type of items in this group. 01003 ********************************************************************************************/ 01004 01005 UINT32 SGNameGroup::GetTypeID() const 01006 { 01007 return m_idType; 01008 } 01009 01010 01011 01012 /******************************************************************************************** 01013 > SGNameItem* SGNameGroup::FindItem(const StringBase& strName) const 01014 01015 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01016 Created: 27/6/99 01017 Returns: The ID of a string that describes the type of items in this group. 01018 ********************************************************************************************/ 01019 01020 SGNameItem* SGNameGroup::FindItem(const StringBase& strName) const 01021 { 01022 // Iterate over all the items looking a matching name. 01023 for (SGNameItem* pItem = (SGNameItem*) GetChild(); 01024 pItem != 0; 01025 pItem = (SGNameItem*) pItem->GetNext()) 01026 { 01027 if (pItem->GetNameTextPtr()->CompareTo(strName) == 0) 01028 return pItem; 01029 } 01030 01031 // Can't find an item with that name. 01032 return 0; 01033 } 01034 01035 01036 01037 /******************************************************************************************** 01038 > SGNameItem* SGNameGroup::RegisterMember(Node* pNode, const StringBase& strName) 01039 01040 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01041 Created: 27/6/99 01042 Inputs: pNode --- the node to register as a member 01043 strName --- the name of the new item to make if one doesn't 01044 exist already 01045 Purpose: Creates and inserts a SGNameItem with the given name if one doesn't 01046 exist already. Includes the given node in the set's bounds etc. 01047 Errors: Out of memory. 01048 ********************************************************************************************/ 01049 01050 SGNameItem* SGNameGroup::RegisterMember(Node* pNode, const StringBase& strName) 01051 { 01052 // Only make a new item if there isn't one already. 01053 SGNameItem* pItem; 01054 for ( pItem = (SGNameItem*) GetChild(); 01055 pItem != 0 && !pItem->IsEqual(strName); 01056 pItem = (SGNameItem*) pItem->GetNext()) 01057 /* empty */ ; 01058 01059 if (pItem == 0) 01060 { 01061 // If we previously had no children and folded because of that then 01062 // automatically unfold. 01063 if (GetChild() == 0 && (Flags.Reserved & 1)) 01064 { 01065 Flags.Reserved &= ~1; 01066 Flags.Folded = FALSE; 01067 } 01068 01069 // We must create a new set item for this 'attribute value'. 01070 pItem = MakeItem(strName); 01071 ERRORIF(pItem == 0, _R(IDE_NOMORE_MEMORY), 0); 01072 01073 // Insert in alphabetical order. 01074 SGSortKey sk[2] = { { SGSORTKEY_BYNAME } }; 01075 AddItem(pItem, sk); 01076 } 01077 /* 01078 TRACEUSER( "JustinF", _T("Registering %s at 0x%p as a member of %s\n"), 01079 (LPCTSTR) pNode->GetRuntimeClass()->m_lpszClassName, 01080 (LPVOID) pNode, (LPCTSTR) strName); 01081 */ 01082 // 'Register' the node with the set item which will note its selection 01083 // status, bounds etc. 01084 pItem->Include(pNode); 01085 return pItem; 01086 } 01087 01088 01089 01090 /******************************************************************************************** 01091 > virtual SGNameItem* SGNameGroup::MakeItem(const StringBase& strName) const 01092 01093 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01094 Created: 27/6/99 01095 Purpose: Seize control of the group's title from the base class. 01096 ********************************************************************************************/ 01097 01098 SGNameItem* SGNameGroup::MakeItem(const StringBase& strName) const 01099 { 01100 return new SGNameItem(strName); 01101 } 01102 01103 01104 01105 /******************************************************************************************** 01106 > virtual void SGNameGroup::ReadGroupTitle() 01107 01108 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01109 Created: 27/6/99 01110 Purpose: Seize control of the group's title from the base class. 01111 ********************************************************************************************/ 01112 01113 void SGNameGroup::ReadGroupTitle() 01114 { 01115 TitleText.Load(m_idTitle); 01116 } 01117 01118 01119 01120 /******************************************************************************************** 01121 > virtual BOOL SGUsedNames::IsMember(Node* pNode, const StringBase& strName) const 01122 01123 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01124 Created: 27/6/99 01125 Inputs: pNode --- the node to test for membership 01126 strName --- the set value (name) to test for equality 01127 Returns: TRUE if the given node is a member of a set within this group. 01128 SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; 01129 CreateDisplayScan::CreateItems::Do 01130 ********************************************************************************************/ 01131 01132 BOOL SGUsedNames::IsMember(Node* pNode, const StringBase& strName) const 01133 { 01134 TemplateAttribute* pAttr; 01135 for (pAttr = (TemplateAttribute*) pNode->FindFirstAttr( &Node::IsAnObjectName ); 01136 pAttr != 0; 01137 pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ) ) 01138 if (strName == pAttr->GetParam()) 01139 return TRUE; 01140 01141 return FALSE; 01142 } 01143 01144 01145 01146 /******************************************************************************************** 01147 > virtual BOOL SGUsedNames::CreateItems(Node* pNode) 01148 01149 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01150 Created: 27/6/99 01151 Inputs: pNode --- the node to test/register for membership 01152 Purpose: Create 'Used Names' set items for the node, as appropriate. 01153 Returns: FALSE for an error, eg. out of memory. 01154 SeeAlso: SGNameGroup::RegisterMember; SGUsedNames::IsMember; 01155 CreateDisplayScan::CreateItems::Do 01156 ********************************************************************************************/ 01157 01158 BOOL SGUsedNames::CreateItems(Node* pNode) 01159 { 01160 TemplateAttribute* pAttr; 01161 for (pAttr = (TemplateAttribute*) pNode->FindFirstAttr( &Node::IsAnObjectName ); 01162 pAttr != 0; 01163 pAttr = (TemplateAttribute*) pAttr->FindNextAttr( &Node::IsAnObjectName ) ) 01164 if (RegisterMember(pNode, pAttr->GetParam()) == 0) 01165 return FALSE; 01166 01167 return TRUE; 01168 } 01169 01170 01171 01172 /******************************************************************************************** 01173 > virtual BOOL SGUsedBitmaps::IsMember(Node* pNode, const StringBase& strName) const 01174 01175 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01176 Created: 27/6/99 01177 Inputs: pNode --- the node to test for membership 01178 strName --- the set value (name) to test for equality 01179 Returns: TRUE if the given node is a member of the given set within this group. 01180 SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; 01181 CreateDisplayScan::CreateItems::Do 01182 01183 NB. the value returned as pBmp can sometimes be set to 1 rather than NULL. 01184 so for the meantime test for this too 01185 ********************************************************************************************/ 01186 BOOL SGUsedBitmaps::IsMember(Node* pNode, const StringBase& strName) const 01187 { 01188 // Is it a bitmap with that value? 01189 KernelBitmap* pBmp; 01190 String_256 str; 01191 if (pNode->IsABitmap()) 01192 { 01193 pBmp = ((NodeBitmap*) pNode)->BitmapRef.GetBitmap(); 01194 if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; 01195 } 01196 01197 // Test against bitmap transparency fills. 01198 NodeAttribute* pAttr = pNode->FindFirstAttr( &Node::IsABitmapTranspFill ); 01199 if (pAttr != 0) 01200 { 01201 pBmp = ((BitmapTranspFillAttribute*) pAttr->GetAttributeValue()) 01202 ->BitmapRef.GetBitmap(); 01203 if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; 01204 } 01205 01206 // Test against bitmap colour fills. 01207 pAttr = pNode->FindFirstAttr( &Node::IsABitmapColourFill ); 01208 if (pAttr != 0) 01209 { 01210 pBmp = ((BitmapFillAttribute*) pAttr->GetAttributeValue()) 01211 ->BitmapRef.GetBitmap(); 01212 if (pBmp != 0 && pBmp != (class KernelBitmap *)1 && pBmp->GetName() == strName) return TRUE; 01213 } 01214 01215 return FALSE; 01216 } 01217 01218 01219 01220 /******************************************************************************************** 01221 > virtual BOOL SGUsedBitmaps::CreateItems(Node* pNode) 01222 01223 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01224 Created: 27/6/99 01225 Inputs: pNode --- the node to test/register for membership 01226 Purpose: Create 'Used Bitmaps' set items for the node, as appropriate. 01227 Returns: FALSE for an error, eg. out of memory. 01228 SeeAlso: SGNameGroup::RegisterMember; SGUsedBitmaps::IsMember; 01229 CreateDisplayScan::CreateItems::Do 01230 ********************************************************************************************/ 01231 01232 BOOL SGUsedBitmaps::CreateItems(Node* pNode) 01233 { 01234 // Is the object itself a kind of bitmap? 01235 KernelBitmap* pBmp; 01236 if (pNode->IsABitmap()) 01237 { 01238 pBmp = ((NodeBitmap*) pNode)->BitmapRef.GetBitmap(); 01239 if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) 01240 return FALSE; 01241 else if (pBmp != 0) 01242 return (TRUE); 01243 } 01244 01245 // Does it have a bitmap transparency fill attribute? 01246 NodeAttribute* pAttr = pNode->FindFirstAttr( &Node::IsABitmapTranspFill ); 01247 if (pAttr != 0) 01248 { 01249 pBmp = ((BitmapTranspFillAttribute*) pAttr->GetAttributeValue()) 01250 ->BitmapRef.GetBitmap(); 01251 01252 if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) 01253 return FALSE; 01254 else if (pBmp != 0) 01255 return (TRUE); 01256 } 01257 01258 // Does a bitmap colour or transparency fill attribute apply to it? 01259 pAttr = pNode->FindFirstAttr( &Node::IsABitmapFill ); 01260 if (pAttr != 0 && !pAttr->IsAFractalFill()) // fractals and plasmas don't have a bitmap!!! sjk 01261 { 01262 pBmp = ((BitmapFillAttribute*) pAttr->GetAttributeValue()) 01263 ->BitmapRef.GetBitmap(); 01264 if (pBmp != 0 && RegisterMember(pNode, pBmp->GetName()) == 0) 01265 return FALSE; 01266 else if (pBmp != 0) 01267 return (TRUE); 01268 } 01269 01270 return TRUE; 01271 } 01272 01273 01274 01275 /******************************************************************************************** 01276 > virtual BOOL SGUsedFonts::IsMember(Node* pNode, const StringBase& strName) const 01277 01278 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01279 Created: 27/6/99 01280 Inputs: pNode --- the node to test for membership 01281 strName --- the set value (name) to test for equality 01282 Returns: TRUE if the given node is a member of the given set within this group. 01283 SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; 01284 CreateDisplayScan::CreateItems::Do 01285 ********************************************************************************************/ 01286 01287 BOOL SGUsedFonts::IsMember(Node* pNode, const StringBase& strName) const 01288 { 01289 // Only consider genuine text objects. 01290 if (!pNode->IsATextChar()) return FALSE; 01291 // if (!pNode->IsABaseTextClass()) return FALSE; 01292 01293 // Does a typeface attribute apply? 01294 AttrTxtFontTypeface* pAttr = 01295 (AttrTxtFontTypeface*) pNode->FindFirstAttr( &Node::IsATypeface ); 01296 if (pAttr == 0) return FALSE; 01297 01298 // The same value? 01299 String_64 strFont; 01300 FONTMANAGER->GetFontName(pAttr->Value.HTypeface, strFont); 01301 return strFont == strName; 01302 } 01303 01304 01305 01306 /******************************************************************************************** 01307 > virtual BOOL SGUsedFonts::CreateItems(Node* pNode) 01308 01309 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01310 Created: 27/6/99 01311 Inputs: pNode --- the node to test/register for membership 01312 Purpose: Create 'Used Fonts' set items for the node, as appropriate. 01313 Returns: FALSE for an error, eg. out of memory. 01314 SeeAlso: SGNameGroup::RegisterMember; SGUsedFonts::IsMember; 01315 CreateDisplayScan::CreateItems::Do 01316 ********************************************************************************************/ 01317 01318 BOOL SGUsedFonts::CreateItems(Node* pNode) 01319 { 01320 // Only consider genuine text objects. 01321 if (!pNode->IsATextChar()) return TRUE; 01322 // if (!pNode->IsABaseTextClass()) return TRUE; 01323 01324 // Does a typeface attribute apply? 01325 AttrTxtFontTypeface* pAttr = 01326 (AttrTxtFontTypeface*) pNode->FindFirstAttr( &Node::IsATypeface ); 01327 if (pAttr == 0) return TRUE; 01328 01329 // Yes, make an item for it. 01330 String_64 strFont; 01331 FONTMANAGER->GetFontName(pAttr->Value.HTypeface, strFont); 01332 return RegisterMember(pNode, strFont) != 0; 01333 } 01334 01335 01336 01337 /******************************************************************************************** 01338 > virtual void SGUsedColourItem::CalcUiBounds(SGFormatInfo*, SGMiscInfo*) 01339 01340 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01341 Created: 27/6/99 01342 Inputs: (see SGNameGroup::CalcUiBounds) 01343 Returns: The width of a colour icon plus a little gap. 01344 SeeAlso: SGNameGroup::RegisterMember; SGUsedColours::IsMember; 01345 CreateDisplayScan::CreateItems::Do 01346 ********************************************************************************************/ 01347 01348 void SGUsedColourItem::CalcUiBounds(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) 01349 { 01350 SGNameItem::CalcUiBounds(pFormatInfo, pMiscInfo); 01351 01352 // Work out the new maximum bounds of the patch and the text. 01353 m_rPatch = m_rText; 01354 MILLIPOINT w = m_rPatch.Width(), h = m_rPatch.Height(); 01355 m_rPatch.hi.x = m_rPatch.lo.x + (h <= w ? h : w); 01356 m_rText.lo.x = m_rPatch.hi.x + SG_GapBeforeText / 2; 01357 01358 // Deflate the patch a little and pixel-align. 01359 m_rPatch.Inflate(4 * -pMiscInfo->PixelSize, 4 * -pMiscInfo->PixelSize); 01360 m_rPatch.Translate(-4, 0); 01361 GridLockRect(pMiscInfo, &m_rPatch); 01362 GridLockRect(pMiscInfo, &m_rText); 01363 } 01364 01365 01366 01367 /******************************************************************************************** 01368 > void SGUsedColourItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) 01369 01370 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01371 Created: 27/6/99 01372 Inputs: (see SGNameItem::HandleRedraw) 01373 Purpose: Renders the colour icon for this display item. 01374 SeeAlso: SGNameItem::DrawLabel 01375 ********************************************************************************************/ 01376 01377 void SGUsedColourItem::DrawLabel(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) 01378 { 01379 SGNameItem::DrawLabel(pRedrawInfo, pMiscInfo); 01380 01381 // Save the context, or we disturb the colour system. Set the outline. 01382 pRedrawInfo->Renderer->SaveContext(); 01383 pRedrawInfo->Renderer->SetLineWidth(0); 01384 pRedrawInfo->Renderer->SetLineColour(COLOUR_BLACK); 01385 01386 // Make a short-lived reference to the indexed colour. 01387 DocColour dcFill; 01388 ERROR3IF(m_picSample == 0, "SGUsedColourItem::DrawLabel: no indexed colour"); 01389 dcFill.MakeRefToIndexedColour(m_picSample); 01390 pRedrawInfo->Renderer->SetFillColour(dcFill); 01391 01392 // Render a circle for a spot colour, rectangle for others. 01393 extern void DrawCircle(RenderRegion*, DocRect&); 01394 if (m_picSample->IsSpotOrTintOfSpot()) 01395 DrawCircle(pRedrawInfo->Renderer, m_rPatch); 01396 else 01397 pRedrawInfo->Renderer->DrawRect(&m_rPatch); 01398 01399 // Restore context as per SGDisplayColour::HandleRedraw. 01400 pRedrawInfo->Renderer->RestoreContext(); 01401 } 01402 01403 01404 01405 /******************************************************************************************** 01406 > SGUsedColourItem* SGUsedColours::RegisterMember(Node* pNode, const StringBase& strName, 01407 DocColour* pCol) 01408 01409 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01410 Created: 27/6/99 01411 Purpose: Register a 'Used Colours' set item for the node. 01412 Returns: 0 for out of memory, pointer to the SGUsedColourItem if successful. 01413 SeeAlso: SGNameGroup::RegisterMember 01414 ********************************************************************************************/ 01415 01416 SGUsedColourItem* SGUsedColours::RegisterMember(Node* pNode, const StringBase& strName, 01417 DocColour* pCol) 01418 { 01419 SGUsedColourItem* pItem = 01420 (SGUsedColourItem*) SGNameGroup::RegisterMember(pNode, strName); 01421 ERROR3IF(pCol == 0, "SGUsedColours::RegisterMember: null input"); 01422 if (pItem != 0) pItem->SetPatchColour(pCol->FindParentIndexedColour()); 01423 return pItem; 01424 } 01425 01426 01427 01428 /******************************************************************************************** 01429 > static const StringBase* SGUsedColours::IsNamedColour(DocColour* pCol) 01430 01431 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01432 Created: 27/6/99 01433 Inputs: pCol --- the colour to test for nomination 01434 Outputs: strName --- name of the colour, if any 01435 Purpose: Helper to the SGUsedColours display group. 01436 Returns: Null if the colour isn't named, the address of its name if it is. 01437 SeeAlso: DocColour::FindParentIndexedColour; IndexedColour::GetName 01438 SGUsedColours::IsMember; SGUsedColours::CreateItems 01439 ********************************************************************************************/ 01440 01441 const StringBase* SGUsedColours::IsNamedColour(DocColour* pCol) 01442 { 01443 ERROR3IF(pCol == 0, "SGUsedColours::IsNamedColour: null input"); 01444 IndexedColour* pIndex = pCol->FindParentIndexedColour(); 01445 return pIndex != 0 && pIndex->IsNamed() ? pIndex->GetName() : 0; 01446 } 01447 01448 01449 01450 /******************************************************************************************** 01451 > virtual BOOL SGUsedColours::IsMember(Node* pNode, const StringBase& strName) const 01452 01453 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01454 Created: 27/6/99 01455 Inputs: pNode --- the node to test for membership 01456 strName --- the set value (name) to test for equality 01457 Returns: TRUE if the given node is a member of the given set within this group. 01458 SeeAlso: SGNameGroup::RegisterMember; SGNameItem::IsMember; 01459 CreateDisplayScan::CreateItems::Do 01460 ********************************************************************************************/ 01461 01462 BOOL SGUsedColours::IsMember(Node* pNode, const StringBase& strName) const 01463 { 01464 const StringBase* pstrCol; 01465 DocColour* pCol; 01466 AttrFillGeometry* pAttr; 01467 01468 for (pAttr = (AttrFillGeometry*) pNode->FindFirstAttr( &Node::IsAFillAttr ); 01469 pAttr != 0; 01470 pAttr = (AttrFillGeometry*) pAttr->FindNextAttr( &Node::IsAFillAttr ) ) 01471 { 01472 pCol = pAttr->GetStartColour(); 01473 if (pCol != 0) 01474 { 01475 pstrCol = IsNamedColour(pCol); 01476 if (pstrCol != 0 && *pstrCol == strName) 01477 return TRUE; 01478 } 01479 01480 pCol = pAttr->GetEndColour(); 01481 if (pCol != 0) 01482 { 01483 pstrCol = IsNamedColour(pCol); 01484 if (pstrCol != 0 && *pstrCol == strName) 01485 return TRUE; 01486 } 01487 01488 pCol = pAttr->GetEndColour2(); 01489 if (pCol != 0) 01490 { 01491 pstrCol = IsNamedColour(pCol); 01492 if (pstrCol != 0 && *pstrCol == strName) 01493 return TRUE; 01494 } 01495 01496 pCol = pAttr->GetEndColour3(); 01497 if (pCol != 0) 01498 { 01499 pstrCol = IsNamedColour(pCol); 01500 if (pstrCol != 0 && *pstrCol == strName) 01501 return TRUE; 01502 } 01503 } 01504 01505 return FALSE; 01506 } 01507 01508 01509 01510 /******************************************************************************************** 01511 > virtual BOOL SGUsedColours::CreateItems(Node* pNode) 01512 01513 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 01514 Created: 27/6/99 01515 Inputs: pNode --- the node to test/register for membership 01516 Purpose: Create 'Used Names' set items for the node, as appropriate. 01517 Returns: FALSE for an error, eg. out of memory. 01518 SeeAlso: SGNameGroup::RegisterMember; SGUsedColours::IsMember; 01519 CreateDisplayScan::CreateItems::Do 01520 ********************************************************************************************/ 01521 01522 BOOL SGUsedColours::CreateItems(Node* pNode) 01523 { 01524 const StringBase* pstrCol; 01525 DocColour* pCol; 01526 AttrFillGeometry* pAttr; 01527 01528 for (pAttr = (AttrFillGeometry*) pNode->FindFirstAttr( &Node::IsAFillAttr ); 01529 pAttr != 0; 01530 pAttr = (AttrFillGeometry*) pAttr->FindNextAttr( &Node::IsAFillAttr )) 01531 { 01532 pCol = pAttr->GetStartColour(); 01533 if (pCol != 0) 01534 { 01535 pstrCol = IsNamedColour(pCol); 01536 if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) 01537 return FALSE; 01538 } 01539 01540 pCol = pAttr->GetEndColour(); 01541 if (pCol != 0) 01542 { 01543 pstrCol = IsNamedColour(pCol); 01544 if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) 01545 return FALSE; 01546 } 01547 01548 pCol = pAttr->GetEndColour2(); 01549 if (pCol != 0) 01550 { 01551 pstrCol = IsNamedColour(pCol); 01552 if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) 01553 return FALSE; 01554 } 01555 01556 pCol = pAttr->GetEndColour3(); 01557 if (pCol != 0) 01558 { 01559 pstrCol = IsNamedColour(pCol); 01560 if (pstrCol != 0 && RegisterMember(pNode, *pstrCol, pCol) == 0) 01561 return FALSE; 01562 } 01563 } 01564 01565 return TRUE; 01566 } 01567 01568