SGDisplayNode Class Reference

This DisplayTree node type is used by the SuperGallery This is a virtual class from which all nodes in the DisplayTree are derived. More...

#include <sgtree.h>

Inheritance diagram for SGDisplayNode:

CCObject SimpleCCObject SGDisplayGroup SGDisplayItem SGDisplayRoot LineAttrGroup SGDisplayColourGroup SGFontsGroup SGLayerGroup SGLibGroup SGNameGroup SGNameGroup LineAttrItem SGDisplayColour SGDisplayDATATYPE SGDisplayKernelBitmap SGDisplayLayer SGDisplayPreviewFonts SGLibDisplayItem SGNameItem SGNameItem SGDisplayRootScroll List of all members.

Public Member Functions

 SGDisplayNode ()
 SGDisplayNode constructor.
 ~SGDisplayNode ()
 SGDisplayNode destructor.
SGDisplayNodeGetParent () const
 Finds the parent of this DisplayTree Node. Returns NULL if you have reached the boundary of the tree.
virtual SGDisplayNodeGetChild () const
 Finds the child of this DisplayTree Node. Returns NULL if you have reached the boundary of the tree.
SGDisplayNodeGetNext () const
 Finds the next (right) sibling of this DisplayTree Node. Returns NULL if you have reached the boundary of the tree.
SGDisplayNodeGetPrevious () const
 Finds the previous (left) sibling of this DisplayTree Node. Returns NULL if you have reached the boundary of the tree.
virtual SuperGalleryGetParentGallery () const
 Recursively scans up the tree asking each parent node in turn for the parent gallery. It is expected that a node (eg SGDisplayRoot or SGDisplayGroup) will be found somewhere on this path which will know who our parent gallery is. (If not, there is a serious tree problem!).
virtual void AddItem (SGDisplayNode *NodeToInsert, SGSortKey *SortInfo=NULL)
 Inserts the given node/subtree into this subtree. If SortInfo == NULL or NodeToInsert is not an SGDisplayItem, it is added as the last child of this node. Otherwise, it is inserted into the subtree of SGDisplayItems at the point 'specified' by SortInfo (By asking each DisplayItem in turn to compare itself to the one being added, until one is found which is considered "greater than" this one according to the sort mode).
virtual void InsertAfter (SGDisplayNode *NodeToInsert)
 Inserts the given node into the DisplayTree as the next (right) sibling of this node.
virtual void InsertBefore (SGDisplayNode *NodeToInsert)
 Inserts the given node into the DisplayTree as the previous (left) sibling of this node.
virtual void MoveAfter (SGDisplayNode *NodeToInsert)
 MOVES the given node (to a different position in the DisplayTree) as the previous (left) sibling of this node. If the node is not linked into a tree, it is effectively just inserted.
virtual void MoveBefore (SGDisplayNode *NodeToInsert)
 MOVES the given node (to a different position in the DisplayTree) as the previous (left) sibling of this node. If the node is not linked into a tree, it is effectively just inserted.
virtual void RemoveFromTree (void)
 De-links this node/subtree from the DisplayTree. This DOES NOT DELETE the node, just unlinks it in preparation for being deleted.
virtual void DestroySubtree (BOOL IncludingThisNode=TRUE)
 DESTROYS the subtree starting at (and including, if IncludingThisNode is TRUE) this node. This does a depth-first recursive scan of the subtree, delinking each item, and then CALLING EACH ITEMS DESTRUCTOR.
virtual SGDisplayGroupFindSubtree (SuperGallery *ParentGal, Document *ParentDoc, Library *ParentLib)
 Searches this node and its subtree for any SGDisplayGroup nodes which have parent pointers which exactly match the input parameters. This is used to find the subtree for a given document or library.
virtual BOOL SetFoldedState (BOOL NewState, BOOL ForceRedraw=TRUE)
 Folds or unfolds a display node.
BOOL IsSelected (void)
 Returns TRUE if this item is selected, FALSE if it is not.
virtual void SetSelected (BOOL IsSelected=TRUE)
 Sets the selection state of a SuperGallery Display Item tree node. Note that this does not cause a redraw of the gallery list box or anything. After setting the state(s) of item(s) you must therefore redraw them.
virtual INT32 CompareTo (SGDisplayNode *Other, INT32 SortKey)
 Compares this node to the 'other' node, to determine their relative positions in the display tree. Returns a value which usually indicates that the other node should be inserted before (-1, or 0) or after (+1) this item.
virtual void GetNameText (String_256 *Result)
 To determine a name string for this node. Generally, this is used for a simple mechanism which searches for display items whose names match given search parameters in some way. It is also used in libraries to provide default redraw methods.
virtual void GetFullInfoText (String_256 *Result)
 To determine a full-info string for this node. Generally, this is used for a simple mechanism which searches for display items whose info matches given search parameters in some way. It is also used in libraries to provide default redraw methods.
virtual void GetKeyWords (String_256 *Result)
 To determine the keywords for this node. Generally, this is used for a simple searching mechanism.
virtual BOOL GetBubbleHelp (DocCoord *MousePos, String_256 *Result)
 Called by the parent gallery when bubble help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help.
virtual BOOL GetStatusLineHelp (DocCoord *MousePos, String_256 *Result)
 Called by the parent gallery when status line help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help.
virtual void StartRendering (SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo)
 MUST be called by all derived node types when they are about to start rendering. This allows us to do things like using GRenderRegions to small bitmaps (a region for each item rather than one region for the whole window) and other fabby things.
virtual void StopRendering (SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo)
 MUST be called by all derived node types when they have finished rendering. This allows us to do things like using GRenderRegions to small bitmaps (a region for each item rather than one region for the whole window) and other fabby things.
SGFormatInfoGetFormatInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
SGRedrawInfoGetRedrawInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
SGMouseInfoGetMouseInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
DragMessageGetDragInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
SGClaimPointInfoGetClaimPointInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
ThumbMessageGetThumbMsgInfo (SGEventType EventType, void *EventInfo)
 Extracts certain event information from the event information passed in to a SGDisplayNode::HandleEvent() method. Not only gets the info for you, but checks the validity (ERROR3's if you've asked for the wrong type of information for the current event type, and if the information is NULL).
virtual BOOL HandleEvent (SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo)
 Handles a generic display tree event. Events of interest trigger specific actions.
virtual void DragWasReallyAClick (SGMouseInfo *Mouse, SGMiscInfo *MiscInfo)
 Handles a mouse click event. This is a callback function - drags of items from galleries will call this function back if the drag turns out to just be a click.
virtual void GetFormatRect (DocRect *LayoutRect)
 Determines where this item wants to redraw itself within the logical window DocCoord coordinates. If this is not a visible node type, or if someone neglected to cache the value in overridden methods, returns (0,0,0,0).
virtual void ForceRedrawOfMyself (BOOL bEraseBkg=TRUE)
 Uses the cached FormatRect to force-redraw the appropriate part of the SuperGallery display window to cause myself (only) to be redrawn.
virtual void ForceRedrawOfMyselfAndChildren (void)
 Uses the cached FormatRect to force-redraw the appropriate part of the SuperGallery display window to cause myself to be redrawn - derived classes may override this to also redraw their children (SGDisplayNode).
virtual void SelectItems (BOOL SelectThem, BOOL Exclusive=FALSE, Document *ParentDocument=NULL, Library *ParentLibrary=NULL)
 To select/deselect groups of display items in this Gallery display. All items whose state changes will force redraw themselves.
virtual void SelectGroups (BOOL SelectThem, BOOL Exclusive, Document *ParentDocument, Library *ParentLibrary)
 To select/deselect sets of display groups in this Gallery display. All groups whose state changes will force redraw themselves.
virtual void SelectRangeGroups (SGDisplayGroup *PrimeNode, SGDisplayGroup *AnchorNode)
 Selects the PrimeNode, and if possible, all sibling items between it and the Anchor node. If Anchor == NULL or is not found, only PrimeNode is selected. Does not deselect any items - you should call SelectItems first to clear the seln.
virtual void SelectRangeItems (SGDisplayItem *PrimeNode, SGDisplayItem *AnchorNode)
 Selects the PrimeNode, and if possible, all sibling items between it and the Anchor node. If Anchor == NULL or is not found, only PrimeNode is selected. Does not deselect any items - you should call SelectItems first to clear the seln.
SGDisplayNodeDoBGRedrawPass (SGMiscInfo *MiscInfo)
 Applies a background rendering pass to the display tree. This will scan the tree from this node onwards looking for a node to background render.
virtual BOOL DefaultPreDragHandler (SGMouseInfo *Mouse, SGMiscInfo *MiscInfo)
 Provides part 1 of the default selection model for clicks on gallery display nodes. Should be called by all derived gallery DisplayItems to handle clicks upon them, when multiple-selection support is desired.
virtual BOOL DefaultClickHandler (SGMouseInfo *Mouse, SGMiscInfo *MiscInfo, BOOL AfterDrag=FALSE, BOOL AdjustDoubleClick=TRUE)
 Provides the default selection model for clicks on gallery display nodes. Should be called by all derived gallery DisplayItems to handle clicks upon them, when multiple-selection support is desired.

Public Attributes

SGDisplayFlags Flags

Protected Member Functions

virtual void SetChild (SGDisplayNode *NewChild)
 Sets the child of this DisplayTree Node.
virtual void InsertInternal (SGDisplayNode *NodeToInsert, SGDisplayNode *PrevNode, SGDisplayNode *NextNode)
 Inserts the given node/subtree into this subtree, between PrevNode and NextNode. One of these two nodes may be NULL if you are trying to insert at the head/tail of a sibling list.
virtual BOOL GiveEventToMyChildren (SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo)
 Causes the entire subtree below this node to check their formatting, and handle the given event. Once a node returns TRUE from its HandleEvent method, the event will NOT be passed on.
virtual void NewLine (SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo)
 Resets the formatting info structure to default values for the start of the next 'line'.
virtual void CalculateFormatRect (SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo, INT32 ItemWidth, INT32 ItemHeight)
 Given current formatting information, generates the rectangle within which this node and its subtree should be redrawn.
BOOL IMustRedraw (SGRedrawInfo *RedrawInfo)
 To determine if a given item needs to be redrawn. This is done by determining if its bounding rectangle ('FormatRect') overlaps the bounding rectangle of the area to be redrawn as specified by RedrawInfo->Bounds.
INT32 DevicePixels (SGMiscInfo *MiscInfo, INT32 NumPixels)
 Because we work in millipoints, it is difficult to get the right values for 'thin' lines (1-device pixel thick) or thin gaps (e.g. 1 or 2 pixels) This function uses the FormatInfo to determine the size, in millipoints, of device pixels, and multiplies this by the input parameter, to give the size in millipoints of that many device pixels.
void DrawPlinth (SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DialogColourInfo *RedrawColours, DocRect *ButtonRect, BOOL Indented=FALSE, UINT32 GlyphResourceID=0)
 Draws a plinth (2 white lines and 2 dark grey lines) around the inside edge of the given rectangle, in order to give a Windows 95 like button plinth. It can include a button glyph bitmap. It's static so anybody can call it if they so desire.
void DrawSelectionOutline (SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DocRect *BoundsRect, INT32 Width=0)
 Draws a black 2-pixel-thick frame-rectangle just inside the given Rect. This is the normal selection-rectangle outline which should go outside an icon or thumbnail when an item is selected.
void DrawBitmap (RenderRegion *Renderer, DocRect *BoundsRect, UINT32 ResID)
 Draws the given bitmap to screen in the given DocRect of the supergallery display list. (Used to be necessary before RR:DrawBitmap came along).
CWindowID GetListWindow (void)
 Returns the window id of the list box window of the parent gallery.
virtual void RegisterForBGRedraw (void)
 Called by derived classes to register themselves for background redraw.
virtual BOOL DoBGRedraw (SGMiscInfo *MiscInfo)
 Forces an immediate redraw of a given node, if it is pending for background redraw.
virtual void DeregisterForBGRedraw (void)
 Ensures that this node is not pending background redraw (resets it) This is called in response to SGEVENT_BGFLUSH, when flushing BG redraws.
virtual BOOL ShouldIDrawForeground (BOOL ForceForeground=FALSE)
 Call this method in derived class redraw methods. Your code should go like this: MonoOn if (ShouldIDrawForeground(ByGollyIveGotAThumbnailCachedAlready) DrawTheItemFully(); else DrawAGreyBox(); MonoOff.

Static Protected Member Functions

static INT32 GridLock (SGMiscInfo *MiscInfo, INT32 Coordinate)
 In order to avoid rounding errors in the mapping between millipoints and output device pixels from causing coordinates to alias to different pixels when in different positions, all SuperGallery display coordinates must be snapped onto a grid of pixel-positions. This function does this snapping.
static void GridLockRect (SGMiscInfo *MiscInfo, DocRect *Rect)
 Given a rectangle and the normal FormatInfo, this ensures that all points of the rectangle are snapped onto a grid of the destination device pixels. This ensures that aliasing effects, due to rounding errors when mapping to the output pixel coordinates, do not occur.

Protected Attributes

DocRect FormatRect

Static Protected Attributes

static SGDisplayNodeCurrentBGRenderNode = NULL
static BOOL BGRenderClaimed = FALSE
static BOOL BkgEraseMode = TRUE

Private Attributes

SGDisplayNodeParent
SGDisplayNodeNext
SGDisplayNodePrevious

Detailed Description

This DisplayTree node type is used by the SuperGallery This is a virtual class from which all nodes in the DisplayTree are derived.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
Before using DisplayTrees, or deriving classes from this one, please read Docs.doc, which has a section on how these nodes function.

See also:
SuperGallery; SGDisplayGroup; SGDisplayList

Definition at line 595 of file sgtree.h.


Constructor & Destructor Documentation

SGDisplayNode::SGDisplayNode  ) 
 

SGDisplayNode constructor.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
See also:
SuperGallery; SGDisplayGroup; SGDisplayItem

Definition at line 162 of file sgtree.cpp.

00163 {
00164     Parent = Next = Previous = NULL;
00165 
00166     Flags.Invisible = Flags.ReadOnly = Flags.Modified = FALSE;
00167     Flags.CanSelect = Flags.Selected = FALSE;
00168     Flags.Folded = Flags.RedrawPending = FALSE;
00169     Flags.Virtualised = FALSE;
00170 
00171     Flags.HandleEventCount = 0;
00172 
00173     Flags.Reserved = 0;
00174 
00175     FormatRect = DocRect(0,0,0,0);
00176 }

SGDisplayNode::~SGDisplayNode  ) 
 

SGDisplayNode destructor.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
See also:
SuperGallery; SGDisplayGroup; SGDisplayItem

Definition at line 191 of file sgtree.cpp.

00192 {
00193     ERROR3IF(Flags.HandleEventCount > 0, "AWOOGA! SGDisplayNode deleted while in its own HandleEvent method - Alert Jason!");
00194     ERROR3IF(Flags.HandleEventCount != 0, "Deleted SGDisplayNode had a corrupted HandleEventCount");
00195 
00196     if (Parent != NULL || GetChild() != NULL || Next != NULL || Previous != NULL)
00197     {
00198         ERROR3("Destructing SGDisplayNode which is still linked into a tree! I'll try to delink it first\n");
00199         RemoveFromTree();
00200     }
00201 }


Member Function Documentation

void SGDisplayNode::AddItem SGDisplayNode NodeToInsert,
SGSortKey SortInfo = NULL
[virtual]
 

Inserts the given node/subtree into this subtree. If SortInfo == NULL or NodeToInsert is not an SGDisplayItem, it is added as the last child of this node. Otherwise, it is inserted into the subtree of SGDisplayItems at the point 'specified' by SortInfo (By asking each DisplayItem in turn to compare itself to the one being added, until one is found which is considered "greater than" this one according to the sort mode).

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/10/94
Parameters:
NodeToInsert - the node/subtree to be inserted [INPUTS] SortInfo - NULL, or an array of MaxSGSortKeys sort key structures which describe how the item should be inserted. [NOTE that this parameter is only used for insertion of SGDisplayItem and derived classes]
Returns:
Errors: ERROR3s will be reported in debug builds for NULL NodeToInsert, or if NodeToInsert is linked into another tree (has non-null parent/next/previous pointers). It is perfectly legal for it to have a child subtree, though.
See also:
SuperGallery; SGDisplayNode::InsertAfter; SGDisplayNode::InsertBefore

Reimplemented in SGDisplayItem.

Definition at line 377 of file sgtree.cpp.

00378 {
00379     if (NodeToInsert == NULL)
00380     {
00381         ERROR3("Attempt to add a NULL node to a tree was ignored");
00382         return;
00383     }
00384 
00385     // The node cannot have parent, next, prev, but can have children
00386     ERROR3IF(NodeToInsert->Parent != NULL ||
00387              NodeToInsert->Next != NULL   || NodeToInsert->Previous != NULL,
00388              "Illegal attempt to link an already-linked node into a tree");
00389 
00390     if (GetChild() == NULL) // We have no children, so there is only one place for this node!
00391     {
00392         SetChild(NodeToInsert);                     // Add it as our first child and return
00393         NodeToInsert->Parent = this;
00394 
00395         // Because we have recreated part of the tree, we must inform the gallery that the
00396         // cached format is incorrect and needs to be recalculated.
00397         SuperGallery *ParentGallery = GetParentGallery();
00398         if (ParentGallery != NULL)
00399             ParentGallery->InvalidateCachedFormat();
00400         return;
00401     }
00402 
00403     SGDisplayNode *Ptr  = GetChild();
00404     SGDisplayNode *Last = NULL;
00405 
00406     if (SortInfo == NULL || SortInfo[0].SortKey == 0 ||
00407             !NodeToInsert->IsKindOf(CC_RUNTIME_CLASS(SGDisplayItem)) ||
00408             !IsKindOf(CC_RUNTIME_CLASS(SGDisplayGroup)))
00409     {
00410         // There is no requested sort mode, or it is sort-by-none, or the node being inserted
00411         // is not a DisplayItem, or I am not a DisplayGroup, so I just add the item to the end
00412         // of my child list
00413 
00414         while (Ptr != NULL)     // Find the end of the sibling list
00415         {
00416             Last = Ptr;
00417             Ptr  = Ptr->Next;
00418         }
00419 
00420         // This ENSURE should never occur, as we checked for no-children above
00421         ERROR3IF(Last == NULL, "Something screwy has happened in SGDisplayNode:AddItem!");
00422         InsertInternal(NodeToInsert, Last, NULL);   // Insert it as the last child
00423     }
00424     else
00425     {
00426         // While searching givvus a parent! (bodge so libraries can sort whilst adding)
00427         NodeToInsert->Parent = this;
00428 
00429         // We can add with sorting, so add the item at an appropriate position based upon
00430         // the provided sort mode
00431         INT32 Result;
00432         while (Ptr != NULL)     // Search the sibling list for the first appropriate insertion point
00433         {
00434             Last = Ptr;
00435 
00436             // Compare using sort key 1
00437             Result = Ptr->CompareTo(NodeToInsert, SortInfo[0].SortKey);
00438             if (SortInfo[0].Reversed)
00439                 Result = -Result;
00440 
00441             // If they are equal, and we have multi-key sort, use key 2
00442             if (Result == 0 && SortInfo[1].SortKey != 0)
00443             {
00444                 Result = Ptr->CompareTo(NodeToInsert, SortInfo[1].SortKey);
00445                 if (SortInfo[1].Reversed)
00446                     Result = -Result;
00447             }
00448         
00449             // We have compared - if the current item is "greater" than the one being
00450             // inserted, then we can stop and insert it before that item
00451             if (Result > 0)
00452                 break;
00453 
00454             Ptr = Ptr->Next;
00455         }
00456 
00457         // Delink the parent since it shouldn't really be connected yet
00458         NodeToInsert->Parent = NULL;
00459         
00460         if (Ptr == NULL)
00461         {
00462             // We must have run off the end of the list - insert at the end
00463             ERROR3IF(Last == NULL, "Something screwy has happened in SGDisplayNode:AddItem!");
00464             InsertInternal(NodeToInsert, Last, NULL);
00465         }
00466         else
00467         {
00468             // We found an item to insert before, so insert before it
00469             InsertInternal(NodeToInsert, Ptr->GetPrevious(), Ptr);
00470         }
00471     }
00472 }

void SGDisplayNode::CalculateFormatRect SGFormatInfo FormatInfo,
SGMiscInfo MiscInfo,
INT32  ItemWidth,
INT32  ItemHeight
[protected, virtual]
 

Given current formatting information, generates the rectangle within which this node and its subtree should be redrawn.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
24/10/94
Parameters:
FormatInfo - A structure containing all relevant information for items to [INPUTS] calculate their formatted positions in the display list. NOTE this is also an output! (As passed into HandleEvent for SGEVENT_FORMAT events)
MiscInfo - Miscellaneous information needed for formatting; as passed into all HandleEvent calls

ItemWidth - The width of this item in millipoints, or 0 if this item is 'infinite' width (fills the entire line). If there is not enough space left on this line for the item, a new line is started.

ItemHeight - The height of this item in millipoints. Sibling items are currently expected to have equal heights; although line formatting will cope with different heights, redraw may miss strips below items for the time being.

Parameters:
FormatInfo - updated as appropriate [OUTPUTS] Member variable FormatRect now contains the format rectangle
Returns:
TRUE if the resulting rectangle overlaps RedrawInfo->Bounds (i.e. if the node would need to redraw itself if handling a redraw request) else FALSE if the node need not be redrawn
Notes: This relies upon the cached formatting information in this node being correct - this function can only be called once per node during a pass through the tree... the second call would give a different result.

If you do not use this function to do all the formatting work for you, then you must remember to either updaet the 'FormatRect' member variable, or override the 'GetFormatRect' member function to supply this information to the caller properly.

See also:
SGDisplayNode::HandleEvent; SGDisplayRoot::HandleEvent; SGDisplayGroup::HandleEvent; SGDisplayItem::HandleEvent

Definition at line 1050 of file sgtree.cpp.

01052 {
01053     ERROR3IF(FormatInfo == NULL || MiscInfo == NULL,
01054              "NULL parameter(s) passed to SGDisplayNode::CalculateFormatRect");
01055 
01056     if (Previous == NULL                        ||  // Is first child node, so go to a new line
01057         FormatInfo->AvailableWidth <= 0         ||  // No room left at all on this line
01058         FormatInfo->AvailableWidth < ItemWidth  ||  // Not enough room on the line for this item
01059         ItemWidth == 0)                             // This item is infinitely wide
01060     {
01061             NewLine(FormatInfo, MiscInfo);
01062     }
01063 
01064     // If items do not fill the entire width, add a 2-pixel gap at the right edge, so that
01065     // adjacent items have a small gap between them. (see below)
01066     if (ItemWidth != 0)
01067         ItemWidth += MiscInfo->PixelSize * 2;
01068 
01069     ItemWidth  = GridLock(MiscInfo, ItemWidth);
01070     ItemHeight = GridLock(MiscInfo, ItemHeight);
01071 
01072     // We must now have enough room for this item across the current line, so plonk it in!
01073     // Update the height of the current line
01074     if (FormatInfo->LineHeight < ItemHeight)
01075     {
01076         // if (LineHeight != 0) AWOOGA! Line height has increased! Must go back and fill in
01077         // the background colour below the previous items on this line, to ensure the entire
01078         // line is fully redrawn.
01079 
01080         ERROR3IF(FormatInfo->LineHeight != 0,
01081             "Sibling Display Item heights are not equal! Jason must upgrade the redraw code");
01082 
01083         FormatInfo->LineHeight = ItemHeight;
01084     }
01085 
01086     // Generate the position rectangle. Note that this may be wider than MaxWidth - it is the
01087     // actual rectangle the item has (so scaling into the returned rect will always work,
01088     // even if part of the rectangle is clipped out of view). However, if the item was
01089     // requested as infinite width, it is returned as MaxWidth.
01090     INT32 ActualWidth = (ItemWidth == 0) ? FormatInfo->AvailableWidth : ItemWidth;
01091 
01092     // Ensure it is clipped within the available window space
01093     if (ActualWidth > FormatInfo->AvailableWidth)
01094         ActualWidth = FormatInfo->AvailableWidth;
01095     
01096     DocRect OldFormatRect(FormatRect);
01097     FormatRect.lo.x = MiscInfo->MaxWidth - FormatInfo->AvailableWidth;
01098     FormatRect.hi.x = FormatRect.lo.x + ActualWidth;
01099     FormatRect.lo.y = FormatInfo->LinePos - FormatInfo->LineHeight;
01100     FormatRect.hi.y = FormatInfo->LinePos;
01101 
01102     // If items do not fill the entire width, add a 2-pixel gap at the right edge, so that
01103     // adjacent items have a small gap between them. (see above)
01104     if (ActualWidth < FormatInfo->AvailableWidth)
01105         FormatRect.hi.x -= MiscInfo->PixelSize * 2;
01106 
01107     GridLockRect(MiscInfo, &FormatRect);    // And ensure it is locked onto the grid
01108 
01109     // If this node is no longer in the same position as it was last time we formatted,
01110     // then accumulate its Y bounds into the 'InvalidBounds' rect, to allow the gallery
01111     // to redraw only those regions of the list which are invalid
01112     if (FormatInfo->AccumulateBounds)
01113     {
01114         if (OldFormatRect != FormatRect)
01115         {
01116             FormatInfo->LastInvalidNode = this;     // We are the last node found to have invalid bounds
01117 
01118             if (FormatInfo->InvalidBounds.hi.y > 0) // If we haven't found an invalid item before
01119                 FormatInfo->InvalidBounds.hi.y = FormatRect.hi.y;
01120 
01121             if (FormatInfo->InvalidBounds.lo.y > FormatRect.lo.y)
01122                 FormatInfo->InvalidBounds.lo.y = FormatRect.lo.y;
01123         }
01124         else
01125         {
01126             if (FormatInfo->LastInvalidNode != NULL)
01127             {
01128                 // The immediately previous node had invalid bounds. If we lie below the current
01129                 // invalid bounds, then we extend them to touch the top of us, to include any gap
01130                 // between them and us.
01131 
01132                 ERROR3IF(FormatInfo->InvalidBounds.hi.y > 0,
01133                             "Gallery display formatting error - LastInvalidNode should be NULL "
01134                             "if there haven't been any invalid nodes yet");
01135 
01136                 if (FormatInfo->InvalidBounds.lo.y > FormatRect.hi.y)
01137                     FormatInfo->InvalidBounds.lo.y = FormatRect.hi.y;
01138 
01139                 FormatInfo->LastInvalidNode = NULL;     // Reset LastInvalid node so that the next node doesn't extend!
01140             }
01141         }
01142     }
01143 
01144 //  if (Flags.Invisible)
01145 //  {
01146 //      FormatRect.hi.x = FormatRect.lo.x;
01147 //      FormatRect.hi.y = FormatRect.lo.y;
01148 //  }
01149 
01150     // Update the free width on the end of this line. Note that this may now be 0 or -ve,
01151     // but this will be sorted out on the next call to this method, in the clauses above.
01152 //  if (!Flags.Invisible)
01153 //  {
01154         FormatInfo->AvailableWidth -= ActualWidth;
01155         GridLock(MiscInfo, FormatInfo->AvailableWidth);
01156 //  }
01157 }

INT32 SGDisplayNode::CompareTo SGDisplayNode Other,
INT32  SortKey
[virtual]
 

Compares this node to the 'other' node, to determine their relative positions in the display tree. Returns a value which usually indicates that the other node should be inserted before (-1, or 0) or after (+1) this item.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
26/10/94
Parameters:
Other - the node to compare this node to [INPUTS] SortKey - An integer identifying how to compare the items 0 = No sorting (always returns 0) 1 = Sort-by-name Other values will return 0, unless the derived class overrides this method in order to provide other sort modes.
Returns:
negative (I am lesser), 0 (we are equal), or positive (I am greater)
See also:
SGDisplayNode::AddItem

Reimplemented in SGNameItem, SGDisplayColour, SGDisplayLibColour, SGLibDisplayItem, SGDisplayPreviewFonts, and SGLibFontItem.

Definition at line 1799 of file sgtree.cpp.

01800 {
01801     ERROR3IF(Other == NULL, "Illegal NULL parameter");
01802 
01803     switch (SortKey)
01804     {
01805         case SGSORTKEY_BYNAME:
01806             {
01807                 String_256 MyName;
01808                 String_256 ItsName;
01809 
01810                 GetNameText(&MyName);
01811                 Other->GetNameText(&ItsName);
01812 
01813                 return(MyName.CompareTo(ItsName));
01814             }
01815             break;
01816     }
01817 
01818     // No sorting (SGSORTKEY_NONE - 0), or 
01819     return(0);
01820 }

BOOL SGDisplayNode::DefaultClickHandler SGMouseInfo Mouse,
SGMiscInfo MiscInfo,
BOOL  AfterDrag = FALSE,
BOOL  AdjustDoubleClick = TRUE
[virtual]
 

Provides the default selection model for clicks on gallery display nodes. Should be called by all derived gallery DisplayItems to handle clicks upon them, when multiple-selection support is desired.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
9/2/94
Parameters:
Mouse - Information on the mouse state for this click [INPUTS] MiscInfo - the normal info as passed to event handlers
AfterDrag - TRUE if this is being called when a drag turns into a click, and you called DefaultPreDragHandler before the drag started

AdjustDoubleClick - TRUE to do normal adjust-double-click handling (which closes the gallery after applying the item) FALSE to not close the gallery (used by the colour gallery to stop the gallery closing when applying with adjust as it applies line colour, so overrides the default behaviour)

Returns:
TRUE if the click caused any action to be taken (selection state to change) FALSE if the click was ignored for whatever reason
See also:
SuperGallery; SGDisplayNode::InsertAfter; SGDisplayNode::InsertBefore

Reimplemented in SGDisplayItem.

Definition at line 2712 of file sgtree.cpp.

02714 {
02715     TRACEUSER( "Matt", _T("SGDisplyaNode::DefaultClickHandler called\n"));
02716     SuperGallery *ParentGallery = GetParentGallery();
02717 
02718     if (!AfterDrag)
02719     {
02720         // This was not called after having previously called DefaultPreDragHandler, 
02721         // so we have to do both halves of the processing. If PreDrag deals with it,
02722         // we don't need to do anything further.
02723         if (DefaultPreDragHandler(Mouse, MiscInfo))
02724             return(TRUE);
02725     }
02726 
02727     if (Mouse->DoubleClick && !Flags.Invisible)
02728     {
02729         // On double-click, this item becomes the only selected item, and
02730         // it is applied (if that action is supported by the parent gallery)
02731 
02732         ParentGallery->SelectItems(FALSE);  // Deselect everything else
02733         ParentGallery->SelectGroups(FALSE); // Deselect all groups
02734 
02735         // Repaint the list box now. This is because if there is a large
02736         // distance between the old selection and the new one, we get a huge
02737         // redraw cliprect, so get a (slow) complete redraw, instead of two
02738         // small redraws. It is thus better to break the redraw into 2 steps
02739         // so that we are more likely to get 2 fast redraws than one slow one.
02740         ParentGallery->PaintListNow();
02741     
02742         // And select myself, and do an immediate redraw
02743         SetSelected(TRUE);
02744         ParentGallery->PaintListNow();
02745 
02746         // Update the ParentGallery to know that we are the new multi-selection anchor
02747         ParentGallery->SetLastSelectedNode(this);
02748 
02749         // And inform the parent gallery that the selection may have changed
02750         ParentGallery->SelectionHasChanged();
02751     
02752         if (Mouse->Adjust)
02753         {
02754             BOOL ActionApplied = ParentGallery->ApplyAction(SGACTION_APPLYADJUST);
02755             if (!ActionApplied)
02756                 ActionApplied = ParentGallery->ApplyAction(SGACTION_APPLY);
02757 
02758             if (ActionApplied && AdjustDoubleClick)
02759             {
02760                 // Adjust/Ctrl double click of an item. This applies the item and then
02761                 // auto closes the gallery (just like RISC OS and Win95)
02762                 ParentGallery->SetVisibility(FALSE);
02763 
02764                 DialogBarOp::SetSystemStateChanged();   // Ensure toolbar button pops out again
02765             }
02766         }
02767 PORTNOTE("galleries", "Disabled clipart gallery")
02768 #ifndef EXCLUDE_FROM_XARALX
02769         else if (ParentGallery->IsKindOf(CC_RUNTIME_CLASS(LibFillsSGallery)))
02770                          LibClipartSGallery::ImportClipart(TRUE, (LibraryGallery*) ParentGallery);
02771 #endif
02772         else
02773             ParentGallery->ApplyAction(SGACTION_APPLY);
02774 
02775         return(TRUE);
02776     }
02777 
02778     // If this was an adjust click, it should toggle the selection state
02779     if (Mouse->Adjust)
02780     {
02781         BOOL AreWeSelected = IsSelected();
02782 
02783         // Mutual exclusion stuff... If we're a group, deselect all items, etc...
02784         if(this->IS_KIND_OF(SGDisplayGroup))
02785             ParentGallery->SelectItems(FALSE);
02786         else if(this->IS_KIND_OF(SGDisplayItem))
02787             ParentGallery->SelectGroups(FALSE);
02788         else
02789             ERROR3("What are we if we're not a group or an item ?");                
02790 
02791         // Invert my selection state, and do an immediate redraw
02792         SetSelected(!AreWeSelected);
02793         ParentGallery->PaintListNow();
02794 
02795         // Update the ParentGallery to know that we are the new multi-selection anchor
02796         ParentGallery->SetLastSelectedNode(this);
02797 
02798         // And inform the parent gallery that the selection may have changed
02799         ParentGallery->SelectionHasChanged();
02800 
02801         return(TRUE);
02802     }
02803     return(FALSE);
02804 }

BOOL SGDisplayNode::DefaultPreDragHandler SGMouseInfo Mouse,
SGMiscInfo MiscInfo
[virtual]
 

Provides part 1 of the default selection model for clicks on gallery display nodes. Should be called by all derived gallery DisplayItems to handle clicks upon them, when multiple-selection support is desired.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
16/4/95
Parameters:
Mouse - Information on the mouse state for this click [INPUTS] MiscInfo - the normal info as passed to event handlers
Returns:
TRUE if the click caused any action to be taken (selection state to change) FALSE if the click was ignored for whatever reason
You should call this method immediately prior to starting a drag as a result of a click event. Note that it is paired with DefaultClickHandler (which should be called when the drag you start turns out to be a click, if you want multiple-selection capability).

See the SGDisplayColour (kernel.cpp) for an example of use

See also:
SGDisplayItem::DefaultClickHandler; SGDisplayColour::HandleEvent

Reimplemented in SGDisplayGroup, and SGDisplayItem.

Definition at line 2573 of file sgtree.cpp.

02574 {
02575     if (Mouse->Adjust)      // Drags cannot be started with adjust
02576         return(FALSE);
02577 
02578     SuperGallery *ParentGallery = GetParentGallery();
02579 
02580     if (Mouse->Extend)
02581     {
02582         BOOL Handled = TRUE;
02583 
02584         // This was a click to extend the selection to the clicked item
02585 #if FALSE
02586 /* I was led to believe that this was how shift-select worked, but it isn't (thank God)
02587    so I have removed this case again - Jason
02588 
02589         if (IsSelected())
02590         {
02591             // If this item is selected, then shift-clicking it acts to leave it
02592             // selected, and deselect every other item.
02593             
02594             ParentGallery->SelectItems(FALSE);  // Deselect everything else
02595             ParentGallery->SelectGroups(FALSE); // Deselect all groups
02596 
02597             // Repaint the list box now. This is because if there is a large
02598             // distance between the old selection and the new one, we get a huge
02599             // redraw cliprect, so get a (slow) complete redraw, instead of two
02600             // small redraws. It is thus better to break the redraw into 2 steps
02601             // so that we are more likely to get 2 fast redraws than one slow one.
02602             ParentGallery->PaintListNow();
02603         
02604             // And select myself, with immediate redraw
02605             SetSelected(TRUE);
02606             ParentGallery->PaintListNow();
02607 
02608             // Update the ParentGallery to know that we are the new multi-selection anchor
02609             ParentGallery->SetLastSelectedNode(this);
02610 
02611             // And inform the parent gallery that the selection may have changed
02612             ParentGallery->SelectionHasChanged();
02613 
02614             return(TRUE);
02615         }
02616         else
02617 */
02618 #endif
02619         {
02620             if (ParentGallery->GetSelectedItemCount() == 0 && ParentGallery->GetSelectedGroupCount() == 0)
02621                 Handled = FALSE;    // No selection - treat extend-click as a normal click
02622             else
02623             {
02624                 ParentGallery->SelectItems(FALSE);  // Deselect all items
02625                 ParentGallery->SelectGroups(FALSE); // Deselect all groups
02626 
02627                 ParentGallery->SelectRange(this, ParentGallery->GetLastSelectedNode());
02628             }
02629         }
02630 
02631         if (Handled)
02632             return(TRUE);
02633     }
02634     
02635     
02636     if (!Flags.Selected)
02637     {
02638         if (!Mouse->Adjust)
02639         {
02640             // If it's not an adjust-click, deselect all other items and groups
02641             ParentGallery->SelectItems(FALSE);
02642             ParentGallery->SelectGroups(FALSE);
02643 
02644             // Repaint the list box now. This is because if there is a large
02645             // distance between the old selection and the new one, we get a huge
02646             // redraw cliprect, so get a (slow) complete redraw, instead of two
02647             // small redraws. It is thus better to break the redraw into 2 steps
02648             // so that we are more likely to get 2 fast redraws than one slow one.
02649             ParentGallery->PaintListNow();
02650         }
02651         else
02652         {
02653             // Mutual exclusion stuff... If we're a group, deselect all items, etc...
02654             if(this->IS_KIND_OF(SGDisplayGroup))
02655                 ParentGallery->SelectItems(FALSE);
02656             else if(this->IS_KIND_OF(SGDisplayItem))
02657                 ParentGallery->SelectGroups(FALSE);
02658             else
02659                 ERROR3("What are we if we're not a group or an item ?");                
02660         }
02661     
02662         // And select myself, and do an immediate redraw
02663         SetSelected(TRUE);
02664         ParentGallery->PaintListNow();
02665 
02666         // Update the ParentGallery to know that we are the new multi-selection anchor
02667         ParentGallery->SetLastSelectedNode(this);
02668 
02669         // And inform the parent gallery that the selection may have changed
02670         ParentGallery->SelectionHasChanged();
02671 
02672         return(TRUE);
02673     }
02674 
02675     return(FALSE);
02676 }

void SGDisplayNode::DeregisterForBGRedraw void   )  [protected, virtual]
 

Ensures that this node is not pending background redraw (resets it) This is called in response to SGEVENT_BGFLUSH, when flushing BG redraws.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/4/95
DO NOT call this method directly - see ShouldIDrawForeground()

Notes: DO NOT TOUCH the Flags.RedrawPending member variable directly!

See also:
SGDisplayNode::RegisterForBGRedraw; SGDisplayNode::ShouldIDrawForeground

Definition at line 1627 of file sgtree.cpp.

01628 {
01629     if (Flags.RedrawPending /*&& !Flags.Invisible*/)
01630     {
01631         SuperGallery *ParentGallery = GetParentGallery();
01632 
01633         if (ParentGallery != NULL)
01634             ParentGallery->DecrementPendingRedraws();
01635 
01636         Flags.RedrawPending = FALSE;        // And finally, turn off pending flag
01637     }
01638 }

void SGDisplayNode::DestroySubtree BOOL  IncludingThisNode = TRUE  )  [virtual]
 

DESTROYS the subtree starting at (and including, if IncludingThisNode is TRUE) this node. This does a depth-first recursive scan of the subtree, delinking each item, and then CALLING EACH ITEMS DESTRUCTOR.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
21/10/94
Parameters:
IncludingThisNode - TRUE (The default) to delete this node (the root of [INPUTS] the subtree) as well as all its children. FALSE to delete its children only (This leaves this node untouched, but vapes all child nodes)
Notes: If you destroy at the root node, the entire tree is destroyed. The root node will be deleted, but note that the reference(s) to the root node (e.g. in the parent SuperGallery) will NOT be de-linked, so be *very* careful!

However, if the root node is a derived SGDisplayRoot node, it will refuse to delete itself in this case,

Returns:
Errors: May be generated by the RemoveFromTree and destructor calls if the subtree is in some way corrupt - see these calls for details.
An ERROR3 may be caused by the destructor if you are trying to delete a tree item from within that item's event handler!

See also:
SuperGallery; SGDisplayNode::RemoveFromTree; SGDisplayNode::~SGDisplayNode

Reimplemented in SGDisplayRoot.

Definition at line 754 of file sgtree.cpp.

00755 {
00756     while (GetChild() != NULL)          // Recurse depth-first down the subtree, destroying it
00757         GetChild()->DestroySubtree();   // Destroy child. Child now points at the next child
00758 
00759     if (IncludingThisNode)          // If this node is included in the destruction...
00760     {
00761         RemoveFromTree();           // Delink ourself from the tree
00762         delete this;                // and invoke our own destructor
00763     }
00764 }

INT32 SGDisplayNode::DevicePixels SGMiscInfo MiscInfo,
INT32  NumPixels
[inline, protected]
 

Because we work in millipoints, it is difficult to get the right values for 'thin' lines (1-device pixel thick) or thin gaps (e.g. 1 or 2 pixels) This function uses the FormatInfo to determine the size, in millipoints, of device pixels, and multiplies this by the input parameter, to give the size in millipoints of that many device pixels.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/10/94
Parameters:
MiscInfo - A structure containing information relevant to gridlocking. [INPUTS] This is passed into all HandleEvent calls.
NumPixels - the number of 'pixels' you want

See also:
SGDisplayNode::GridLock; SGDisplayNode::GridLockRect

Definition at line 952 of file sgtree.h.

00953 {
00954     return(NumPixels * MiscInfo->PixelSize);
00955 }

BOOL SGDisplayNode::DoBGRedraw SGMiscInfo MiscInfo  )  [protected, virtual]
 

Forces an immediate redraw of a given node, if it is pending for background redraw.

Author:
Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
Date:
1/4/95
Parameters:
MiscInfo - the usual [INPUTS]
Returns:
TRUE to claim the redraw event, FALSE to not claim it
This is used by the base-class system to render items waiting for BG redraw, but can also be used by derived classes to force a given item to be visible immediately. e.g. This might be done if your item is clicked while waiting to be redrawn.

DO NOT call this method directly - see ShouldIDrawForeground()

Notes: DO NOT TOUCH the Flags.RedrawPending member variable directly!

See also:
SGDisplayNode::RegisterForBGRedraw; SGDisplayNode::ShouldIDrawForeground

Definition at line 1512 of file sgtree.cpp.

01513 {
01514     BGRenderClaimed = FALSE;            
01515 
01516     if (Flags.RedrawPending /*&& !Flags.Invisible*/)
01517     {
01518         SuperGallery *ParentGallery = GetParentGallery();
01519 
01520         if (ParentGallery != NULL)
01521         {
01522             // Interlock the redraw with the drag manager to make sure the screen isn't
01523             // screwed up by us redrawing over a solid drag
01524             DocRect KernelRect(FormatRect);
01525             BOOL NeedInterlock = ParentGallery->ConvertFromVirtualCoords(MiscInfo, &KernelRec