#include <colormgr.h>
Inheritance diagram for ColourManager:

Public Member Functions | |
| ColourManager () | |
| Constructs a ColourManager object. | |
Static Public Member Functions | |
| static BOOL | Init (void) |
| Initialises the entire colour system. This includes the colour manager, colour contexts, and colour dialogues, etc. Notes: Should only be called once ever. Called by Application::Init(). | |
| static void | Deinit (void) |
| De-Initlialises the entire colour system. This includes the colour manager, colour contexts, and colour dialogues, etc. Notes: Should only be called once ever. Called by Application::Deinit(). | |
| static ColourList * | GetColourList (BOOL InvalidateCache=FALSE) |
| To obtain the ColourList of IndexedColours in the SelectedDocument (the colours which the user can use within the document; this is the set of colours displayed by the colour bar and edited by the ColourMgrDlg) Note that an ordered list is used so that multiple display orders can be used (e.g. for the ColourMgrDlg and ColourBar, etc). | |
| static ColourList * | GetCurrentColourList (void) |
| To obtain the ColourList of IndexedColours in the CurrentDocument. | |
| static ColourContext * | GetColourContext (ColourModel Model, Document *ScopeDocument=NULL) |
| To easily find an appropriate colour context to use when converting colours. There are global contexts, but in order to supply special document-specific colour corrections etc, each document actually has its own private set of contexts. Thus, you should call this function to determine the most appropriate context to use. | |
| static ColourContext * | GetColourContext (ColourModel Model, View *ScopeView) |
| To easily find an appropriate colour context to use when converting colours. There are global contexts, but in order to supply special view-specific colour corrections etc, each document view actually has its own private set of contexts. Thus, you should call this function to determine the most appropriate context to use. | |
| static void | SelViewContextHasChanged (void) |
| To redraw all windows which depend upon the Selected View's colour context. i.e. The selected view, and also the colour editor, gallery, & line. (and maybe other windows in the future, e.g. object properties, grad fill editors, etc). | |
| static void | ColourHasChanged (Document *ScopeDoc, ColourList *ColList, IndexedColour *Col) |
| Indicates to all interested parties that the given IndexedColour has been changed (sends a COLOURUPDATED message) e.g. Causes the ColourBar and document to redraw themselves. | |
| static void | ColourHasChangedInvisible (Document *ScopeDoc, ColourList *ColList, IndexedColour *Col) |
| Indicates to all interested parties that the given IndexedColour has been changed (sends a COLOURUPDATEDINVISIBLE message) e.g. Causes the ColourBar to redraw itself. | |
| static void | ColourListHasChanged (ColourList *ColList) |
| To inform all interested parties that the given list of IndexedColours has changed by item(s) being added, deleted, or moved to a new position. e.g This causes the ColourBar and ColourMgrDlg to update their displays to reflect the new state of the list, if the list is the one which they are currently displaying. | |
| static BOOL | HideColours (ColourList *ColList, IndexedColour **ColourArray, BOOL ForceDelete) |
| This 'deletes' colours by creating an undoable operation to hide them. It is assumed that the colours are not in use by the time you call this function - An ENSURE failure will occur if any are. After invoking the 'hide' operation, this function calls ColourListHasChanged. | |
| static BOOL | UnHideColours (ColourList *ColList, IndexedColour **ColourArray) |
| This un-'deletes' colours by creating an undoable operation to unhide them. This is used when creating a new colour to 'unhide' it (which has no immediate effect on the colour) - this creates an undo record that will hide the colour if the 'new' is undone. | |
| static BOOL | ChangeColour (ColourList *ColList, IndexedColour *NewDefn, IndexedColour *Target, BOOL ChangeisInvisible=FALSE) |
| This changes the colour 'Target' to be the same as 'NewDefn'. To achieve undo of this operation, the data members of the two colours are swapped (as the colour being changed must stay at the same memory location), and the NewDefn is used again as the undo record of this colour. Whenever the colour is changed, including during the execution of this funciton, and also by undo/redo, a ColourChangingMsg will be broadcast (either COLOURUPDATED or COLOURUPDATEDINVISIBLE, depending on the state of the ChangeIsInvisible flag). | |
| static void | ForceRedrawOfChangedColours (Document *ScopeDoc, IndexedColour **Colours) |
| Scans the document tree of the given scope document, and causes a redraw of all objects which are affected by any attributes which contain references to any of the colours in the given NULL-terminated list of colours. If none of the colours are in use in the document tree, nothing should result. (i.e. it force redraws any areas of the document containing any of the given colours). | |
| static IndexedColour * | GenerateNewNamedColour (ColourList *ParentList, IndexedColour *SourceColour) |
| Creates a new named IndexedColour. If possible, this colour is copied from the given SourceColour, but if this is not available, an attempt to find a useful colour to copy will be made - if this fails, a battleship grey will be created. i.e. apart from abject failure, this always creates a new colour. | |
| static IndexedColour * | GenerateNewUnnamedColour (ColourList *ParentList, DocColour *SourceColour) |
| Creates a new named IndexedColour. If possible, this colour is copied from the given SourceColour, but if this is not available, an attempt to find a useful colour to copy will be made - if this fails, a battleship grey will be created. i.e. apart from abject failure, this always creates a new colour. | |
| static void | EnsureColourIsInDocument (Document *SourceDoc, Document *DestDoc, DocColour *SourceAndResultCol) |
| Ensures that the given DocColour references a "safe" colour to use within the given document. This may mean doing nothing to the colour, or it may be necessary to copy the colour (and possibly linked parent colour(s) as well!) into the DestDoc. Whatever happens, ResultCol will be filled in with something that you can use with confidence. | |
| static BOOL | GetCurrentLineAndFillAttrs (AttrStrokeColour **LineAttr, AttrFillGeometry **FillAttr) |
| Determines the current line and fill colour attributes. These are the default ones, or if there is a selection, the attrs which are common to all selected objects. If there are many different attributes of the same type associated with the selection, NULL is returned. Notes: The ColourBar works exclusively on the SELECTED Doc. Change with care This function ensures that Current == Selected during its operation. | |
| static BOOL | GetCurrentLineAndFillColours (DocColour **LineCol, DocColour **FillCol, DocColour **EndGradFill=NULL) |
| Finds the current line and fill attributes, and dereferences them to find the current line and fill DocColours. These may be returned NULL if there are no current attributes (no document/many colours selected). | |
| static void | FindColourOfInterestToUser (IndexedColour **ResultCol, ColourList **ResultList=NULL) |
| Several things (Colour editor whenever the selection changes, generation of a new colour) need to know a 'useful' colour to display/copy. Rather than just showing the current default colour or something, they need to interactively update to show an appropriate colour from the selection and suchlike. | |
| static void | FindColourOfInterestToUser (DocColour *ResultCol, ColourList **ResultList=NULL, BOOL WantLineColour=FALSE) |
| Several things (Colour editor whenever the selection changes, generation of a new colour) need to know a 'useful' colour to display/copy. Rather than just showing the current default colour or something, they need to interactively update to show an appropriate colour from the selection and suchlike. | |
Protected Member Functions | |
| MsgResult | Message (Msg *Msg) |
| Process messages sent to the ColourManager Some messages (DocChanging) will cause new broadcasts indicating that the colour system has changed (new colour list has been paged in, etc). | |
Static Protected Attributes | |
| static ColourList * | CurrentColourList |
| static Document * | ScopeDocument |
This is the Indexed Colour list for the SelectedDocument (if any). It is displayed by the colour bar, and/or edited by the Colour Manager Dialogue.
Find a suitable global or document-specific colour context to use
Handle colour system state changes
Messages are sent whenever the current list changes. This happens when:
1) A colour is inserted/deleted/edited in the SelectedDocument,
2) The SelectedDocument changes,
3) The Colour List is deselected (i.e. when there is no SelectedDocument, there is no available list)
These messages allow the colour manager dialogues and colour bar (and other clients) to update their contents (or hide, etc) when such changes occur.
Other processing (invalidating colour caches, etc) may also occur in some cases. This is all handled internally by the ColourManager.
Copy or create new colours
Find "Useful" colours for the editor to edit and the colour line/gallery to display.
Miscellaneous other useful functions. See colormgr.h for details of currently available functions
Definition at line 168 of file colormgr.h.
|
|
Constructs a ColourManager object.
Definition at line 168 of file colormgr.cpp. 00169 : MessageHandler(CC_RUNTIME_CLASS(MessageHandler), TRUE) 00170 { 00171 }
|
|
||||||||||||||||||||
|
This changes the colour 'Target' to be the same as 'NewDefn'. To achieve undo of this operation, the data members of the two colours are swapped (as the colour being changed must stay at the same memory location), and the NewDefn is used again as the undo record of this colour. Whenever the colour is changed, including during the execution of this funciton, and also by undo/redo, a ColourChangingMsg will be broadcast (either COLOURUPDATED or COLOURUPDATEDINVISIBLE, depending on the state of the ChangeIsInvisible flag).
Definition at line 2124 of file colormgr.cpp. 02127 { 02128 #if !defined(EXCLUDE_FROM_RALPH) 02129 ERROR3IF(ColList == NULL || NewDefn == NULL || Target == NULL, 02130 "ColourManager::ChangeColour - illegal NULL param(s)"); 02131 02132 OpDescriptor* OpDesc = 02133 OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpColourChange)); 02134 02135 if (OpDesc != NULL) 02136 { 02137 ColourChangeInfo Param; 02138 02139 Param.ParentList = ColList; 02140 Param.Target = Target; 02141 Param.NewDefn = NewDefn; 02142 Param.InvisibleChange = ChangeIsInvisible; 02143 02144 OpDesc->Invoke((OpParam *) &Param); 02145 } 02146 #endif 02147 return(TRUE); 02148 }
|
|
||||||||||||||||
|
Indicates to all interested parties that the given IndexedColour has been changed (sends a COLOURUPDATED message) e.g. Causes the ColourBar and document to redraw themselves.
Notes: If you are recieving messages, and wish to act on COLOURUPDATEDINVISIBLE, you should sit on BOTH COLOURUPDATED messages. Otherwise, you should only sit on COLOURUPDATED messages. The ColourManager will force-redraw the parst of the ScopeDoc which rely on the changed colour, or any colour liked to the changed colour. If ColList == the current colour list then entities such as the colour bar will redraw themselves to show the new state of this colour.
Definition at line 1867 of file colormgr.cpp. 01869 { 01870 ERROR3IF(ScopeDoc == NULL || ColList == NULL || Col == NULL, 01871 "ColourManager::ColourHasChanged - NULL parameters are illegal!\n"); 01872 01873 ColList->InvalidateInheritanceCache(); 01874 01875 BROADCAST_TO_ALL(ColourChangingMsg(ScopeDoc, ColList, Col, 01876 ColourChangingMsg::COLOURUPDATED)); 01877 }
|
|
||||||||||||||||
|
Indicates to all interested parties that the given IndexedColour has been changed (sends a COLOURUPDATEDINVISIBLE message) e.g. Causes the ColourBar to redraw itself.
If 'visible' information has changed, use ColourHasChanged instead. Notes: If you are recieving messages, and wish to act on COLOURUPDATEDINVISIBLE, you should sit on BOTH COLOURUPDATED messages. ColList really should point to the list in which the colour resides. If ColList == NULL or ColList == the current colour list, then entities such as the colour bar will redraw themselves to show the new state of this colour. If ColList is not NULL, then all its sort orders will be marked invalid so that they are re-sorted the next time they are used. (If an incorrect pointer (or NULL) is passed in, unnecessary redraws of colour bars etc may take place, so it is most preferable that you pass in the correct list pointer if you know it)
Definition at line 1924 of file colormgr.cpp. 01926 { 01927 ColList->InvalidateInheritanceCache(); 01928 BROADCAST_TO_ALL(ColourChangingMsg(ScopeDoc, ColList, Col, 01929 ColourChangingMsg::COLOURUPDATEDINVISIBLE)); 01930 }
|
|
|
To inform all interested parties that the given list of IndexedColours has changed by item(s) being added, deleted, or moved to a new position. e.g This causes the ColourBar and ColourMgrDlg to update their displays to reflect the new state of the list, if the list is the one which they are currently displaying.
Definition at line 1959 of file colormgr.cpp. 01960 { 01961 ERROR3IF(ColList == NULL, "ColourManager::ColourListHasChanged: NULL parameter is illegal"); 01962 01963 // Inform the colour gallery ahead of everyone else 01964 // ColourGallery::ColourListHasChanged(ColList); 01965 01966 // And inform the plebs 01967 ColList->InvalidateInheritanceCache(); 01968 01969 Document *ParentDoc = (Document *) ColList->GetParentDocument(); 01970 BROADCAST_TO_ALL(ColourChangingMsg(ParentDoc, ColList, NULL, 01971 ColourChangingMsg::LISTUPDATED)); 01972 }
|
|
|
De-Initlialises the entire colour system. This includes the colour manager, colour contexts, and colour dialogues, etc. Notes: Should only be called once ever. Called by Application::Deinit().
Definition at line 233 of file colormgr.cpp. 00234 { 00235 // shut down the colour contexts 00236 ColourContextList::DeinitColourContexts(); 00237 }
|
|
||||||||||||||||
|
Ensures that the given DocColour references a "safe" colour to use within the given document. This may mean doing nothing to the colour, or it may be necessary to copy the colour (and possibly linked parent colour(s) as well!) into the DestDoc. Whatever happens, ResultCol will be filled in with something that you can use with confidence.
ResultCol - should point at a DocColour defining the colour you want to put in this document. It may be an immediate DocColour, or a reference to an IndexedColour. (this param may NOT be NULL)
What do you mean this should be in the colour manager? Have you seen how many files it rebuilds?! Eeek! (OK, so I've moved it now)
Definition at line 1784 of file colormgr.cpp. 01786 { 01787 ERROR3IF(ResultCol == NULL || DestDoc == NULL, "Illegal NULL param"); 01788 01789 if (SourceDoc == DestDoc) // Completely safe - into the same doc 01790 return; 01791 01792 // Find the indexed colour (if any) that the given colour references 01793 IndexedColour *ColourToApply = ResultCol->FindParentIndexedColour(); 01794 01795 if (ColourToApply == NULL) // It's a simple DocColour, so safe 01796 return; 01797 01798 // It's an IndexedColour. We must copy it to the dest doc, and use the copy. 01799 if (DestDoc != NULL) 01800 { 01801 // We're applying the colour into a different document! 01802 // We must duplicate (with merging) this colour into the dest doc before applying 01803 ColourListComponent *ColComp = (ColourListComponent *) 01804 DestDoc->GetDocComponent(CC_RUNTIME_CLASS(ColourListComponent)); 01805 01806 // Start the copy 01807 if (ColComp != NULL && ColComp->StartComponentCopy()) 01808 { 01809 DocColour RefCol; 01810 RefCol.MakeRefToIndexedColour(ColourToApply); 01811 01812 // Copy this colour (and any linked parents if necessary). RefCol now 01813 // references the destination colour, so we point ColourToApply at it 01814 ColComp->CopyColourAcross(&RefCol); 01815 ColourToApply = RefCol.FindParentIndexedColour(); 01816 01817 // And clean up, merging the colour into the other document's colour list 01818 ColComp->EndComponentCopy(NULL, FALSE); 01819 01820 // We've got an IndexedColour, so set ResultCol on it, and return 01821 ResultCol->MakeRefToIndexedColour(ColourToApply); 01822 return; 01823 } 01824 } 01825 01826 // We've failed to copy the colour across, so set it to simple 'no colour' 01827 *ResultCol = DocColour(COLOUR_BLACK); 01828 }
|
|
||||||||||||||||
|
Several things (Colour editor whenever the selection changes, generation of a new colour) need to know a 'useful' colour to display/copy. Rather than just showing the current default colour or something, they need to interactively update to show an appropriate colour from the selection and suchlike.
This is used to determine the colour definition for a colour to use when editing "local colours" in the colour editor. The exact colour returned will be NULL (in dire emergency, usually only occurs if there are no documents open), or will be chosen from this priority list of possible contenders: MonoOn (1) Colour of first selected fill-blob found (if !WantLineColour), (2) Fill-Colour of selection (if !WantLineColour), (3) current/default fill colour (if !WantLineColour), (4) line-Colour of selection (If WantLineColour), (5) current/default line colour (if WantLineColour), (6) COLOUR_BLACK MonoOff Notes: 'Colour of selection' is determined by using (if possible) the last object selected, or the frontmost selected object if this fails. If you are not interested in the ResultList return value, pass in NULL (use the default) for this parameter. Camelot will not return a 'no fill' default colour (conditions 3 and 6) but Webster does because the Webster colour editor wants to handle this situation. Definition at line 1202 of file colormgr.cpp. 01204 { 01205 ERROR3IF(ResultCol == NULL, "ColourManager::FindColourOfInterestToUser - ResultCol is NULL!"); 01206 01207 // Ensure safe return values 01208 *ResultCol = DocColour(COLOUR_BLACK); 01209 if (ResultList != NULL) 01210 *ResultList = NULL; 01211 01212 // If there are no documents available, then we can't find a colour - Return NULLs 01213 if (Document::GetSelected() == NULL) 01214 return; 01215 01216 // Ensure CurrentDoc == SelectedDoc 01217 Document *OldCurrentDoc = SetCurrentDoc(); 01218 01219 // Get the colour list. Just in case, we invalidate the cache (as this method is 01220 // called on document chnages and suchlike, so it is best to make sure we don't use 01221 // cached values for a no-longer-present document!) 01222 ColourList *ColList = ColourManager::GetColourList(TRUE); 01223 BOOL FoundUsefulColour = FALSE; 01224 01225 // First, check if there is a VISIBLE selected fill blob, and use the colour of 01226 // the first one that we find, if we are lucky enough to find one. 01227 if (!WantLineColour && AttrFillGeometry::CountSelectionControlPoints() > 0) 01228 { 01229 // Yep. There is at least 1 visible selected fill blob... 01230 AttrFillGeometry* Fill = AttrFillGeometry::FindFirstSelectedAttr(); 01231 while (Fill != NULL && !FoundUsefulColour) 01232 { 01233 if (Fill->GetSelectionCount() > 0) 01234 { 01235 // CGS .... 01236 01237 // DMc's multi stage fills (blobs) do not dynamically update the colour edit 01238 // dialog when they are clicked on. This has now been 01239 // fixed (by me!). Problem was to do with the fact that this function never 01240 // even considered them .... 01241 01242 FillRamp* pFillRamp = Fill->GetFillRamp (); 01243 01244 if (pFillRamp != NULL) 01245 { 01246 UINT32 NumberSelected = pFillRamp->CountSelBlobs (); 01247 01248 if (NumberSelected > 0) 01249 { 01250 INT32 SelectedIndex = pFillRamp->GetSelectedIndex (); 01251 ColRampItem* TheItem = (ColRampItem*) pFillRamp->GetValidIndexedItem (SelectedIndex); 01252 01253 if (TheItem != NULL) 01254 { 01255 FoundUsefulColour = TRUE; 01256 *ResultCol = TheItem->GetColour (); 01257 } 01258 } 01259 } 01260 01261 if (Fill->IsSelected(FILLCONTROL_STARTPOINT) && Fill->GetStartColour() != NULL) 01262 { 01263 // Use Fill Start Colour 01264 FoundUsefulColour = TRUE; 01265 *ResultCol = *(Fill->GetStartColour()); 01266 break; 01267 } 01268 01269 if (Fill->IsSelected(FILLCONTROL_ENDPOINT) && Fill->GetEndColour() != NULL) 01270 { 01271 // Use Fill End Colour 01272 FoundUsefulColour = TRUE; 01273 *ResultCol = *(Fill->GetEndColour()); 01274 break; 01275 } 01276 01277 if (Fill->IsSelected(FILLCONTROL_ENDPOINT2) && Fill->GetEndColour2() != NULL) 01278 { 01279 // Use Fill End Colour 01280 FoundUsefulColour = TRUE; 01281 *ResultCol = *(Fill->GetEndColour2()); 01282 break; 01283 } 01284 01285 if (Fill->IsSelected(FILLCONTROL_ENDPOINT3) && Fill->GetEndColour3() != NULL) 01286 { 01287 // Use Fill End Colour 01288 FoundUsefulColour = TRUE; 01289 *ResultCol = *(Fill->GetEndColour3()); 01290 break; 01291 } 01292 } 01293 01294 Fill = AttrFillGeometry::FindNextSelectedAttr(); 01295 } 01296 } 01297 01298 if (!FoundUsefulColour) 01299 { 01300 // Find the last node which was made selected (if any) 01301 // Scan back from this to find the nearest previous NodeAttribute which contains 01302 // colour(s), and make ResultColour ref the first IndexedColour which we find in this search. 01303 SelRange *Selection = GetApplication()->FindSelection(); 01304 01305 // If there are any selected nodes, then... 01306 if (Selection != NULL && Selection->Count() > 0) 01307 { 01308 Node *pNode = Selection->GetLastSelectedNode(); 01309 01310 // If the SelRange doesn't know what was last made selected, then see if anything 01311 // is selected, and if so, grab the last (topmost) selected object instead 01312 if (pNode == NULL) 01313 pNode = Selection->FindLast(); 01314 01315 // Now search through the attributes applied to this node, to see if we can 01316 // find an IndexedColour FILL (i.e. we ignore stroke colours for now) - we 01317 // will use the first one that we find 01318 NodeAttribute *pAttr = NULL; 01319 01320 if (!WantLineColour) 01321 { 01322 if (pNode != NULL) 01323 pAttr = NodeAttribute::FindFirstAppliedAttr(pNode); 01324 01325 while (pAttr != NULL && !FoundUsefulColour) 01326 { 01327 // Scan each NodeAttribute in turn to see if any of them contain any colours 01328 DocColour *pColour; 01329 UINT32 Context = 0; 01330 01331 // Only check non-line-colour attributes 01332 if (!(IS_A(pAttr, AttrStrokeColour))) 01333 { 01334 do 01335 { 01336 // Get the next colour field (if any) from the attribute, and find the 01337 // IndexedColour (if any) to which it refers 01338 pColour = pAttr->EnumerateColourFields(Context++); 01339 if (pColour != NULL) 01340 { 01341 FoundUsefulColour = TRUE; 01342 *ResultCol = *pColour; 01343 } 01344 01345 } while (pColour != NULL && !FoundUsefulColour); 01346 } 01347 01348 pAttr = NodeAttribute::FindPrevAppliedAttr(pAttr); 01349 } 01350 } 01351 else 01352 { 01353 // If we still haven't found a colour, try for a line/stroke colour instead 01354 if (pNode != NULL && !FoundUsefulColour) 01355 pAttr = NodeAttribute::FindFirstAppliedAttr(pNode); 01356 01357 while (pAttr != NULL && !FoundUsefulColour) 01358 { 01359 // Scan each NodeAttribute in turn to see if any of them contain any colours 01360 DocColour *pColour; 01361 UINT32 Context = 0; 01362 01363 // Only check line-colour attributes 01364 if (IS_A(pAttr, AttrStrokeColour)) 01365 { 01366 do 01367 { 01368 // Get the next colour field (if any) from the attribute, and find the 01369 // IndexedColour (if any) to which it refers 01370 pColour = pAttr->EnumerateColourFields(Context++); 01371 if (pColour != NULL) 01372 { 01373 FoundUsefulColour = TRUE; 01374 *ResultCol = *pColour; 01375 } 01376 01377 } while (pColour != NULL && !FoundUsefulColour); 01378 } 01379 01380 pAttr = NodeAttribute::FindPrevAppliedAttr(pAttr); 01381 } 01382 } 01383 01384 } 01385 } 01386 01387 if (!FoundUsefulColour) 01388 { 01389 // OK, then. let's see if there is a default fill colour, or failing that 01390 // (eg it could be 'no colour') a default line colour, which we can edit. 01391 AttributeManager &AttrMgr = Document::GetSelected()->GetAttributeMgr(); 01392 01393 DocColour LineCol; 01394 DocColour FillCol; 01395 01396 AttrMgr.GetCurrentLineAndFillColour(CC_RUNTIME_CLASS(NodeRenderableInk), 01397 &LineCol, &FillCol); 01398 01399 if (!WantLineColour) 01400 { 01401 // Webster wants the colour even if it is 'no fill' 01402 #ifndef WEBSTER 01403 if (!FillCol.IsTransparent()) 01404 #endif //WEBSTER 01405 { 01406 *ResultCol = FillCol; 01407 FoundUsefulColour = TRUE; 01408 } 01409 } 01410 else 01411 { 01412 #ifndef WEBSTER 01413 if (!LineCol.IsTransparent()) 01414 #endif //WEBSTER 01415 { 01416 *ResultCol = LineCol; 01417 FoundUsefulColour = TRUE; 01418 } 01419 } 01420 } 01421 01422 if (!FoundUsefulColour) 01423 { 01424 // Ok, we're rapidly approaching a moment of panic. Try the first non-deleted named 01425 // colour in the selected document's colour list. If nothing else, there should 01426 // always be a default Black that we can use 01427 01428 if (ColList != NULL) 01429 { 01430 IndexedColour *Ptr = (IndexedColour *) ColList->GetHead(); 01431 while (Ptr != NULL && !FoundUsefulColour) 01432 { 01433 if (Ptr->IsNamed() && !Ptr->IsDeleted()) 01434 { 01435 FoundUsefulColour = TRUE; 01436 ResultCol->MakeRefToIndexedColour(Ptr); 01437 } 01438 01439 Ptr = (IndexedColour *) ColList->GetNext(Ptr); 01440 } 01441 } 01442 } 01443 01444 // Fill in the return results 01445 if (ResultList != NULL) 01446 *ResultList = ColList; 01447 01448 // And restore the previous CurrentDocument state 01449 RestoreCurrentDoc(OldCurrentDoc); 01450 }
|
|
||||||||||||
|
Several things (Colour editor whenever the selection changes, generation of a new colour) need to know a 'useful' colour to display/copy. Rather than just showing the current default colour or something, they need to interactively update to show an appropriate colour from the selection and suchlike.
The exact colour returned will be NULL (in dire emergency, usually only occurs if there are no documents open), or will be chosen from this priority list of possible contenders: MonoOn (1) Colour of first selected fill-blob found, (2) Fill-Colour of selection, (3) current/default fill colour, (4) line-Colour of selection, (5) current/default line colour, (6) the first active named colour in the document's colour list, (7) NULL MonoOff Notes: 'Colour of selection' is determined by using (if possible) the last object selected, or the frontmost selected object if this fails. If you are not interested in the ResultList return value, pass in NULL (use the default) for this parameter. In debug builds only, extra checks are made which can cause an ERROR3 if the colour found was not in the selected document's ColourList. Definition at line 932 of file colormgr.cpp. 00933 { 00934 ERROR3IF(ResultCol == NULL, "ColourManager::FindColourOfInterestToUser - ResultCol is NULL!"); 00935 00936 // Ensure safe return values 00937 *ResultCol = NULL; 00938 if (ResultList != NULL) 00939 *ResultList = NULL; 00940 00941 // If there are no documents available, then we can't find a colour - Return NULLs 00942 if (Document::GetSelected() == NULL) 00943 return; 00944 00945 // Ensure CurrentDoc == SelectedDoc 00946 Document *OldCurrentDoc = SetCurrentDoc(); 00947 00948 // Get the colour list. Just in case, we invalidate the cache (as this method is 00949 // called on document chnages and suchlike, so it is best to make sure we don't use 00950 // cached values for a no-longer-present document!) 00951 ColourList *ColList = ColourManager::GetColourList(TRUE); 00952 IndexedColour *UsefulColour = NULL; 00953 00954 // First, check if there is a VISIBLE selected fill blob, and use the colour of 00955 // the first one that we find, if we are lucky enough to find one. 00956 if (AttrFillGeometry::CountSelectionControlPoints() > 0) 00957 { 00958 // Yep. There is at least 1 visible selected fill blob... 00959 AttrFillGeometry* Fill = AttrFillGeometry::FindFirstSelectedAttr(); 00960 while (Fill != NULL && UsefulColour == NULL) 00961 { 00962 if (Fill->GetSelectionCount() > 0) 00963 { 00964 if (Fill->IsSelected(FILLCONTROL_STARTPOINT) && Fill->GetStartColour() != NULL) 00965 { 00966 // Use Fill Start Colour 00967 UsefulColour = Fill->GetStartColour()->FindParentIndexedColour(); 00968 break; 00969 } 00970 00971 if (Fill->IsSelected(FILLCONTROL_ENDPOINT) && Fill->GetEndColour() != NULL) 00972 { 00973 // Use Fill End Colour 00974 UsefulColour = Fill->GetEndColour()->FindParentIndexedColour(); 00975 break; 00976 } 00977 00978 if (Fill->IsSelected(FILLCONTROL_ENDPOINT2) && Fill->GetEndColour2() != NULL) 00979 { 00980 // Use Fill End Colour 00981 UsefulColour = Fill->GetEndColour2()->FindParentIndexedColour(); 00982 break; 00983 } 00984 00985 if (Fill->IsSelected(FILLCONTROL_ENDPOINT3) && Fill->GetEndColour3() != NULL) 00986 { 00987 // Use Fill End Colour 00988 UsefulColour = Fill->GetEndColour3()->FindParentIndexedColour(); 00989 break; 00990 } 00991 } 00992 00993 Fill = AttrFillGeometry::FindNextSelectedAttr(); 00994 } 00995 } 00996 00997 if (UsefulColour == NULL) 00998 { 00999 // Find the last node which was made selected (if any) 01000 // Scan back from this to find the nearest previous NodeAttribute which contains 01001 // colour(s), and make UsefulColour the first IndexedColour which we find in this search. 01002 SelRange *Selection = GetApplication()->FindSelection(); 01003 01004 if (Selection != NULL) 01005 { 01006 Node *pNode = Selection->GetLastSelectedNode(); 01007 // If the SelRange doesn't know what was last made selected, then see if anything 01008 // is selected, and if so, grab the last (topmost) selected object instead 01009 if (pNode == NULL) 01010 pNode = Selection->FindLast(); 01011 01012 // Now search through the attributes applied to this node, to see if we can 01013 // find an IndexedColour FILL (i.e. we ignore stroke colours for now) - we 01014 // will use the first one that we find 01015 NodeAttribute *pAttr = NULL; 01016 if (pNode != NULL) 01017 pAttr = NodeAttribute::FindFirstAppliedAttr(pNode); 01018 01019 while (pAttr != NULL && UsefulColour == NULL) 01020 { 01021 // Scan each NodeAttribute in turn to see if any of them contain any colours 01022 DocColour *pColour; 01023 UINT32 Context = 0; 01024 01025 // Only check non-line-colour attributes 01026 if (!(IS_A(pAttr, AttrStrokeColour))) 01027 { 01028 do 01029 { 01030 // Get the next colour field (if any) from the attribute, and find the 01031 // IndexedColour (if any) to which it refers 01032 pColour = pAttr->EnumerateColourFields(Context++); 01033 if (pColour != NULL) 01034 UsefulColour = pColour->FindParentIndexedColour(); 01035 01036 } while (pColour != NULL && UsefulColour == NULL); 01037 } 01038 01039 pAttr = NodeAttribute::FindPrevAppliedAttr(pAttr); 01040 } 01041 01042 01043 // If we still haven't found a colour, try for a line/stroke colour instead 01044 if (pNode != NULL && UsefulColour == NULL) 01045 pAttr = NodeAttribute::FindFirstAppliedAttr(pNode); 01046 01047 while (pAttr != NULL && UsefulColour == NULL) 01048 { 01049 // Scan each NodeAttribute in turn to see if any of them contain any colours 01050 DocColour *pColour; 01051 UINT32 Context = 0; 01052 01053 // Only check line-colour attributes 01054 if (IS_A(pAttr, AttrStrokeColour)) 01055 { 01056 do 01057 { 01058 // Get the next colour field (if any) from the attribute, and find the 01059 // IndexedColour (if any) to which it refers 01060 pColour = pAttr->EnumerateColourFields(Context++); 01061 if (pColour != NULL) 01062 UsefulColour = pColour->FindParentIndexedColour(); 01063 01064 } while (pColour != NULL && UsefulColour == NULL); 01065 } 01066 01067 pAttr = NodeAttribute::FindPrevAppliedAttr(pAttr); 01068 } 01069 01070 } 01071 } 01072 01073 if (UsefulColour == NULL) 01074 { 01075 // OK, then. let's see if there is a default fill colour, or failing that 01076 // (eg it could be 'no colour') a default line colour, which we can edit. 01077 AttributeManager &AttrMgr = Document::GetSelected()->GetAttributeMgr(); 01078 01079 DocColour LineCol; 01080 DocColour FillCol; 01081 01082 AttrMgr.GetCurrentLineAndFillColour(CC_RUNTIME_CLASS(NodeRenderableInk), 01083 &LineCol, &FillCol); 01084 01085 UsefulColour = FillCol.FindParentIndexedColour(); 01086 if (UsefulColour == NULL) 01087 UsefulColour = LineCol.FindParentIndexedColour(); 01088 } 01089 01090 if (UsefulColour == NULL) 01091 { 01092 // Ok, we're rapidly approaching a moment of panic. Try the first non-deleted named 01093 // colour in the selected document's colour list. If nothing else, there should 01094 // always be a default Black that we can use 01095 01096 if (ColList != NULL) 01097 { 01098 IndexedColour *Ptr = (IndexedColour *) ColList->GetHead(); 01099 while (Ptr != NULL && UsefulColour == NULL) 01100 { 01101 if (Ptr->IsNamed() && !Ptr->IsDeleted()) 01102 UsefulColour = Ptr; 01103 01104 Ptr = (IndexedColour *) ColList->GetNext(Ptr); 01105 } 01106 } 01107 } 01108 01109 // Sanity check. Should never ever ever be the case, ever. 01110 if (UsefulColour != NULL) 01111 ERROR3IF(UsefulColour->IsDeleted(), 01112 "ColourManager::FindColourOfInterestToUser - Colour found is DELETED!"); 01113 01114 // Fill in the return results 01115 *ResultCol = UsefulColour; 01116 if (UsefulColour != NULL && ResultList != NULL) 01117 *ResultList = ColList; 01118 01119 #ifdef _DEBUG 01120 // In debug builds, verify that the returned colour is in the list we 01121 // expect it to be in! 01122 01123 if (ColList != NULL && UsefulColour != NULL) 01124 { 01125 IndexedColour *Ptr = (IndexedColour *) ColList->GetHead(); 01126 while (Ptr != NULL && Ptr != UsefulColour) 01127 Ptr = (IndexedColour *) ColList->GetNext(Ptr); 01128 01129 if (Ptr == NULL) 01130 { 01131 Ptr = (IndexedColour *) ColList->GetUnnamedColours()->GetHead(); 01132 while (Ptr != NULL && Ptr != UsefulColour) 01133 Ptr = (IndexedColour *) ColList->GetUnnamedColours()->GetNext(Ptr); 01134 } 01135 01136 ERROR3IF(Ptr != UsefulColour, 01137 "ColourManager::FindColourOfInterestToUser" 01138 " - Colour found is not in the current colour list!"); 01139 } 01140 #endif 01141 01142 // And restore the previous CurrentDocument state 01143 RestoreCurrentDoc(OldCurrentDoc); 01144 }
|
|
||||||||||||
|
Scans the document tree of the given scope document, and causes a redraw of all objects which are affected by any attributes which contain references to any of the colours in the given NULL-terminated list of colours. If none of the colours are in use in the document tree, nothing should result. (i.e. it force redraws any areas of the document containing any of the given colours).
Definition at line 261 of file colormgr.cpp. 00262 { 00263 #if !defined(EXCLUDE_FROM_RALPH) 00264 // Sanity check 00265 if (ScopeDoc == NULL) 00266 { 00267 ERROR3("Illegal NULL param"); 00268 return; 00269 } 00270 00271 OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_REDRAWCOLOURS); 00272 00273 if (OpDesc != NULL) 00274 { 00275 OpRedrawColoursInfo Info; 00276 Info.ScopeDoc = ScopeDoc; 00277 Info.Colours = Colours; 00278 00279 OpDesc->Invoke((OpParam *) &Info); 00280 } 00281 #endif 00282 }
|
|
||||||||||||
|
Creates a new named IndexedColour. If possible, this colour is copied from the given SourceColour, but if this is not available, an attempt to find a useful colour to copy will be made - if this fails, a battleship grey will be created. i.e. apart from abject failure, this always creates a new colour.
NOTE that the user is prompted for a new name, and has the opportunity to cancel creation of the colour, in which case, NULL will be returned. You must therefore handle a NULL return *quietly*. Notes: This code is used by the ColourBar and ColourGallery "new colour" code to generate a new named colour.
Definition at line 1499 of file colormgr.cpp. 01501 { 01502 ERROR3IF(ParentList == NULL, "ColourManager::GenerateNamedColour - NULL ParentList!"); 01503 01504 IndexedColour *NewCol = NULL; 01505 01506 if (SourceColour != NULL) 01507 { 01508 // Copy the source colour 01509 NewCol = new IndexedColour(*SourceColour); 01510 01511 // If parent is named and not tint/linked colour, remember where we copied 01512 // it from so that we can give a useful default parent in the colour editor 01513 // if the user decides to make it a tint/linked colour later on. 01514 if (NewCol->IsNamed() && NewCol->FindLinkedParent() == NULL) 01515 NewCol->SetLinkedParent(SourceColour, NewCol->GetType()); 01516 } 01517 else 01518 { 01519 IndexedColour *UsefulColour; 01520 FindColourOfInterestToUser(&UsefulColour); 01521 01522 if (UsefulColour != NULL) 01523 { 01524 NewCol = new IndexedColour(*UsefulColour); 01525 01526 // If parent is named and not tint/linked colour, remember where we copied 01527 // it from so that we can give a useful default parent in the colour editor 01528 // if the user decides to make it a tint/linked colour later on. 01529 if (NewCol->IsNamed() && NewCol->FindLinkedParent() == NULL) 01530 NewCol->SetLinkedParent(UsefulColour, NewCol->GetType()); 01531 } 01532 else 01533 { 01534 // Create a mid-grey HSV colour for them to edit 01535 ColourHSVT Bob; 01536 Bob.Hue = Bob.Saturation = Bob.Transparent = 0; 01537 Bob.Value = FIXED24(0.5); 01538 01539 NewCol = new INDEXEDCOLOUR_HSVT(&Bob); 01540 } 01541 } 01542 01543 if (NewCol == NULL) // Serious memory failure! 01544 return(NULL); 01545 01546 // Set the colour's name (1 to make it named, and 2 so it is not 01547 // the same as the colour it was copied from) 01548 /* 01549 String_64 NewName; 01550 01551 if (NewCol->IsNamed()) 01552 { 01553 // Is named, so is a copy: Name it "New Colour (Copy of WXYZ)" 01554 String_64 OldName = *NewCol->GetName(); 01555 String_64 TruncOldName; // Truncate old name to 32 chars 01556 OldName.Left(&TruncOldName, 32); // and add it into the new name 01557 NewName.MakeMsg(_R(IDS_NEWCOLOUR_COPY), (TCHAR *)TruncOldName); 01558 } 01559 else 01560 NewName.MakeMsg(_R(IDS_NEWCOLOUR)); // No name, so make it named: "New colour" 01561 */ 01562 01563 #if !defined(EXCLUDE_FROM_RALPH) 01564 #ifndef STANDALONE 01565 // Ask for a new name for the colour. This also gives the user a chance 01566 // to back out of the deal without losing their deposit (though if they didn't 01567 // tick the small box in the small print, we'll continue sending them junk mail ;-) 01568 if (!NewColourDlg::InvokeDialog(ParentList, NewCol, NEWCOLOUR_MUSTBENAMED)) 01569 { 01570 delete NewCol; // Bummer. They cancelled their subscription 01571 return(NULL); 01572 } 01573 #endif 01574 #endif 01575 01576 // NewCol->SetName(NewName); 01577 01578 // Add the new colour (also ensuring that the colour has a unique name) 01579 ParentList->AddItem(NewCol); 01580 01581 // Create an undo record, but only if it is a colour style (named) 01582 IndexedColour *UnHideList[2]; 01583 UnHideList[0] = NewCol; 01584 UnHideList[1] = NULL; 01585 ColourManager::UnHideColours(ParentList, UnHideList); 01586 01587 return(NewCol); 01588 }
|
|
||||||||||||
|
Creates a new named IndexedColour. If possible, this colour is copied from the given SourceColour, but if this is not available, an attempt to find a useful colour to copy will be made - if this fails, a battleship grey will be created. i.e. apart from abject failure, this always creates a new colour.
|