// $Id: sglib.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ // Gallery library handling classes #include "camtypes.h" #include "sglib.h" #include #include "ccdc.h" // For render-into-dialogue support //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "grnddib.h" //#include "bitmap.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "bitmpinf.h" #include "nodebmp.h" //#include "sgscan.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "sgliboil.h" //#include "thumb.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "thumbmsg.h" //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "richard.h" //#include "richard2.h" //#include "richard3.h" #include "sglbase.h" #include "progress.h" #include "sglcart.h" #include "inetop.h" //#include "webster.h" //#include "simon.h" //#include "resource.h" // Implement the dynamic class bits... CC_IMPLEMENT_DYNAMIC(SGLibDisplayItem, SGDisplayItem) CC_IMPLEMENT_DYNAMIC(SGLibGroup, SGDisplayGroup) // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW using namespace InetUtils; // Blank space below text when in 'text underneath' modes const INT32 SG_SPACE_UNDER = SG_GapAboveText / 2; // Bodge for status line text #define GROUP_BAR_ICON_WIDTH 16500 // Should we use the virtualising system if we can ? BOOL SGLibGroup::LibraryVirtualisingEnabled = TRUE; //#if (USERNUMBER==22) //#ifdef _DEBUG // If Debug, the default is YES //BOOL SGLibGroup::LibraryVirtualisingEnabled = TRUE; //#else // Otherwise it's NO //BOOL SGLibGroup::LibraryVirtualisingEnabled = FALSE; //#endif /*********************************************************************************************** > SGLibDisplayItem::SGLibDisplayItem() Author: Jason_Williams (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Purpose: SGLibDisplayItem constructor DON'T call this constructor. It ERROR3's. Call the other constructor ***********************************************************************************************/ SGLibDisplayItem::SGLibDisplayItem() { ERROR3("Illegal call on default SGLibDisplayItem constructor - call the other one!"); TheLibraryIndex = NULL; } /*********************************************************************************************** > SGLibDisplayItem::SGLibDisplayItem(LibraryIndex LibraryIndexToDisplay) Author: Jason_Williams (Xara Group Ltd) Created: 27/1/95 (base generated in sgbase.cpp) Inputs: LibraryIndexToDisplay - A LibraryIndex indicating which library item this DisplayItem is displaying Purpose: SGLibDisplayItem constructor ***********************************************************************************************/ SGLibDisplayItem::SGLibDisplayItem(LibraryIndex LibraryIndexToDisplay, BOOL bNew) { TheLibraryIndex = LibraryIndexToDisplay; bIsDownloadingThumb = FALSE; pDownloadOp = NULL; nPercentageDownloaded = 0; bIsNew = bNew; } /*********************************************************************************************** > SGLibDisplayItem::~SGLibDisplayItem() Author: Adrian_Stoicar (Xara Group Ltd) Created: 27/1/97 Purpose: SGLibDisplayItem destructor ***********************************************************************************************/ SGLibDisplayItem::~SGLibDisplayItem() { if (IsDownloadingThumb() && pDownloadOp) pDownloadOp->Abort(); } /*********************************************************************************************** > virtual INT32 SGLibDisplayItem::GetTextWidth(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 27/3/95 Inputs: FormatInfo - The formatting info from which to calculate my position/size MiscInfo - As usual, the useful misc info struct Outputs: Width (in millipoints) required by the description text for this mode Purpose: An overridable way of returning the width of the text description ***********************************************************************************************/ INT32 SGLibDisplayItem::GetTextWidth(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo) { INT32 XSize = SG_InfiniteWidth; INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); // If we're displaying text underneath the thumbnail, add some space for it LibDisplayType DType = GetDisplayType(MiscInfo); // Extra space required by the text switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: // Text is underneath XSize = 0; break; case LibDisplay_SmallThumb: case LibDisplay_MediumThumb: case LibDisplay_LargeThumb: // No text, so no space XSize = 0; break; case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: // XSize = SG_InfiniteWidth; XSize = SG_DefaultNameText * 2; break; case LibDisplay_JustText: // Text only XSize = (SG_DefaultNameText * 4) / 3; break; default: // Text is to the right XSize = (SG_DefaultNameText * 2) / 3; break; } // Lock the current sizes to the grid XSize = GridLock(MiscInfo, XSize); // Extra Space required if selected XSize += (3 * 2 * OnePixel); return XSize; } /*********************************************************************************************** > virtual void SGLibDisplayItem::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 10/3/95 (base generated in sgbase.cpp) Inputs: FormatInfo - The formatting info from which to calculate my position/size MiscInfo - As usual, the useful misc info struct Outputs: member variable FormatRect - is returned filled in with the size/position of this LibraryIndex item's display area. This is dependent upon the current display mode and format state FormatInfo will be updated as a result of the formatting operation Purpose: Shared code for LibraryIndex items to calculate where they will appear in the grand scheme of things Notes: LibraryIndexs supply only one display mode ("full info") Scope: private (for use of SGLibDisplayItem class only) ***********************************************************************************************/ void SGLibDisplayItem::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo) { INT32 XSize = SG_InfiniteWidth; INT32 YSize = SG_DefaultLargeIcon; INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); Library *ParentLib = GetParentLibrary(); // If we're displaying text underneath the thumbnail, add some space for it LibDisplayType DType = GetDisplayType(MiscInfo); // Get width of text XSize = GetTextWidth(FormatInfo, MiscInfo); // Extra space required by the text switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: // Text is underneath YSize = SG_GapAboveText + SG_SPACE_UNDER; break; default: // Text is to the right YSize = 0; break; } // Lock the current sizes to the grid YSize = GridLock(MiscInfo, YSize); // Extra Space required if selected YSize += (3 * 2 * OnePixel); // Add in space required by the bitmap itself switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_SmallThumbText: case LibDisplay_SmallThumb: YSize += GridLock(MiscInfo, ParentLib->PreviewBMPHeight(SGThumb_Small) * OnePixel); XSize += GridLock(MiscInfo, ParentLib->PreviewBMPWidth(SGThumb_Small) * OnePixel); break; case LibDisplay_LargeThumbTextUnder: case LibDisplay_Default: case LibDisplay_LargeThumbText: case LibDisplay_LargeThumb: YSize += GridLock(MiscInfo, ParentLib->PreviewBMPHeight(SGThumb_Large) * OnePixel); XSize += GridLock(MiscInfo, ParentLib->PreviewBMPWidth(SGThumb_Large) * OnePixel); break; case LibDisplay_MediumThumbTextUnder: case LibDisplay_MediumThumbText: case LibDisplay_MediumThumb: YSize += GridLock(MiscInfo, ParentLib->PreviewBMPHeight(SGThumb_Medium) * OnePixel); XSize += GridLock(MiscInfo, ParentLib->PreviewBMPWidth(SGThumb_Medium) * OnePixel); break; case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: YSize += GridLock(MiscInfo, ParentLib->PreviewBMPHeight(SGThumb_Medium) * OnePixel); XSize += GridLock(MiscInfo, ParentLib->PreviewBMPWidth(SGThumb_Medium) * OnePixel); //XSize = SG_InfiniteWidth; break; case LibDisplay_JustText: // No description requires no text description space YSize = GridLock(MiscInfo, 18 * OnePixel); XSize = GridLock(MiscInfo, SG_DefaultNameText); break; } // Calculate a proper rectangle for the item CalculateFormatRect(FormatInfo, MiscInfo, XSize, YSize); } /*********************************************************************************************** > virtual void SGLibDisplayItem::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 10/3/95 (base generated in sgbase.cpp) Inputs: RedrawInfo - The information on the kernel-rendered redraw area MiscInfo - always provided. Contains a few useful bits of info that may be needed for all event types. [Member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item] Purpose: SGLibDisplayItem item redraw method - removed from the main HandleEvent method merely to make the code tidier. Notes: Scope: private ***********************************************************************************************/ void SGLibDisplayItem::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo) { // First, inform the system that we are about to start rendering this item StartRendering(RedrawInfo, MiscInfo); // Determine the SGSubLib library object to ask for info on this item Library *ParentLib = GetParentLibrary(); DocRect BmpRect(FormatRect); // Get my redraw position from the cached FormatRect DocRect UnscaledRect(FormatRect); RenderRegion *Renderer = RedrawInfo->Renderer; INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); INT32 TwoPixels = (INT32) DevicePixels(MiscInfo, 2); LibDisplayType DType = GetDisplayType(MiscInfo); //#ifdef _DEBUG // Show format rect // Renderer->SetFillColour(DocColour(0x40, 0x40, 0x40)); // Renderer->DrawRect(&UnscaledRect); //#endif Renderer->SetLineWidth(0); Renderer->SetLineColour(RedrawInfo->Transparent); if(DType == LibDisplay_JustText) { BmpRect.hi.x = BmpRect.lo.x + OnePixel; } else { INT32 XSize = 0; switch(DType) { case LibDisplay_MediumThumbTextUnder: case LibDisplay_MediumThumbText: case LibDisplay_MediumThumb: case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: XSize = ParentLib->PreviewBMPWidth(SGThumb_Medium); break; case LibDisplay_SmallThumbText: case LibDisplay_SmallThumbTextUnder: case LibDisplay_SmallThumb: XSize = ParentLib->PreviewBMPWidth(SGThumb_Small); break; case LibDisplay_Default: case LibDisplay_LargeThumbText: case LibDisplay_LargeThumb: case LibDisplay_LargeThumbTextUnder: default: // OnePixel bodge to get the 1:1 bitmaps inside the rectangle XSize = ParentLib->PreviewBMPWidth(SGThumb_Large); break; } // Convert pixels to millipoints XSize *= OnePixel; // Thumbnail rectangle... space around edges but don't scale thumbnail BmpRect.hi.x = BmpRect.lo.x + XSize + (6 * OnePixel); // Space for selection rectangle BmpRect.Inflate(-(TwoPixels+OnePixel)); // Exclude the space needed below the bmp rect from the bmp rect switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: BmpRect.lo.y += SG_GapAboveText + SG_SPACE_UNDER; break; default: break; } // Ensure it maps exactly to specific pixels GridLockRect(MiscInfo, &BmpRect); // Set up the colours for rendering our text, and outline it if selected if (Flags.Selected) { if(BmpRect.hi.x > UnscaledRect.hi.x) BmpRect.hi.x = UnscaledRect.hi.x; BmpRect.Inflate(TwoPixels+OnePixel); GridLockRect(MiscInfo, &BmpRect); // Ensure we're on a pixel DrawSelectionOutline(RedrawInfo, MiscInfo, &BmpRect); BmpRect.Inflate(-(TwoPixels+OnePixel)); } // Draw the thumbnail DrawItemThumbnail(RedrawInfo, MiscInfo, &BmpRect); } // Draw the text DrawItemText(Renderer, RedrawInfo, MiscInfo, &UnscaledRect, &BmpRect, Flags.Selected); // Finally, inform the system that we have completed rendering this item StopRendering(RedrawInfo, MiscInfo); } /*********************************************************************************************** > virtual void SGLibDisplayItem::DrawItemTrumbnail(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo, DocRect* pDocRect) Author: Adrian_Stoicar (Xara Group Ltd) Created: 10/3/97 Inputs: pRedrawInfo - pointer to SGRedrawInfo struct as passes to the HandleRedraw() function from whithin which this function should be called pRedrawInfo - pointer to SGMiscInfo struct as passes to the HandleRedraw() function from whithin which this function should be called pDocRect - pointer to the rect where the thumbnail should be drawn Purpose: draws the item's thumbnail Scope: protected ***********************************************************************************************/ void SGLibDisplayItem::DrawItemThumbnail(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo, DocRect* pDocRect) { RenderRegion* pRenderer = pRedrawInfo->Renderer; if (Library::BackgroundRedraw) { BOOL DrawnBitmap = DrawThumb(pRenderer, pRedrawInfo, pMiscInfo, pDocRect, FALSE); if (ShouldDownloadThumb()) DownloadThumbnail(); if (ShouldIDrawForeground(DrawnBitmap)) { if (!DrawnBitmap) { if (!DrawThumb(pRenderer, pRedrawInfo, pMiscInfo, pDocRect, TRUE)) { if (IsDownloadingThumb()) // draw grey rectangle if we're still waiting for the thumbnail DrawPlaceholder(pRenderer, pMiscInfo, pDocRect, TRUE); else // draw a crossed box DrawPlaceholder(pRenderer, pMiscInfo, pDocRect, FALSE); } } } else if (!DrawnBitmap) DrawPlaceholder(pRenderer, pMiscInfo, pDocRect, TRUE); } else if (!DrawThumb(pRenderer, pRedrawInfo, pMiscInfo, pDocRect, TRUE)) DrawPlaceholder(pRenderer, pMiscInfo, pDocRect, FALSE); } /*********************************************************************************************** > BOOL SGLibDisplayItem::ShouldIDrawForeground(BOOL ForceForeground) Author: Adrian_Stoicar (Xara Group Ltd) Created: 6/5/97 Inputs: ForceForeground - TRUE if you want to force foreground redrawing (e.g. if you know your thumbnail is cached you are better off just drawing it immediately), or FALSE to allow the operation to be backgrounded. Returns: TRUE if you should draw in the foreground (i.e. draw the item to completion), FALSE if you should draw the background stuff (i.e. draw a grey box instead of a thumbnail) - if FALSE, you'll be called back to complete the redraw later. Purpose: overrides the base class version to force foreground mode if the item is downloading its thumbnail. This is necessary to avoid flickering. SeeAlso: SGDisplayNode::ShouldIDrawForeground(BOOL ForceForeground) ***********************************************************************************************/ BOOL SGLibDisplayItem::ShouldIDrawForeground(BOOL ForceForeground) { if (pDownloadOp) return SGDisplayNode::ShouldIDrawForeground(TRUE); else return SGDisplayNode::ShouldIDrawForeground(ForceForeground); } /*********************************************************************************************** > virtual void SGLibDisplayItem::DrawItemText(RenderRegion *Renderer, SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DocRect *Rectangle, DocRect *BmpRect, BOOL Selected) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: Renderer - Pointer to RenderRegion in which to plot the bitmap rect RedrawInfo - Various bits of Redraw information such as colours MiscInfo - Miscellaneous info as passed to the redraw handler by the sgallery code Rectangle - Pointer to a DocRect the size and position of which the selected rectangle will use, so we need to draw our thumbnail inside this. BmpRect - Bitmap rectangle Selected - Should the text be drawn in a selected state ? Outputs: Returns: Purpose: Plots the item text in the position as required by the GetDisplayType. Notes: SeeAlso: SGLibDisplayItem::HandleRedraw ***********************************************************************************************/ void SGLibDisplayItem::DrawItemText(RenderRegion *Renderer, SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DocRect *Rectangle, DocRect *BmpRect, BOOL Selected) { LibDisplayType DType = GetDisplayType(MiscInfo); // Work out the text rectangle and stick it here DocRect TextRect(*Rectangle); INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: TextRect = *Rectangle; // Give some extra space above and below the clipart TextRect.lo.y = TextRect.lo.y + SG_SPACE_UNDER; TextRect.hi.y = TextRect.lo.y + SG_GapAboveText; // give the text a little space below the piccy frame, and more below to the next TextRect.Inflate(0, -OnePixel); break; case LibDisplay_SmallThumb: case LibDisplay_MediumThumb: case LibDisplay_LargeThumb: // No text return; break; default: TextRect = *Rectangle; TextRect.lo.x = BmpRect->hi.x + SG_GapBeforeText; break; } GridLockRect(MiscInfo, &TextRect); Renderer->SetLineWidth(0); Renderer->SetLineColour(RedrawInfo->Transparent); DocColour red(0xFF, 0, 0); // for new items // Set up the colours for rendering our text, and fill the background if selected if (Selected) { Renderer->SetFillColour(RedrawInfo->SelBackground); switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: Renderer->DrawRect(&TextRect); break; case LibDisplay_FullInfo: { // Two line full info selection rectangle DocRect SelRect(TextRect); // Text not in gallery, don't redraw if(TextRect.lo.x > Rectangle->hi.x) return; SelRect.hi.y = TextRect.lo.y + TextRect.Height()/2 - (OnePixel * 2); SelRect.lo.y = TextRect.lo.y + TextRect.Height()/2 + (OnePixel * 2); SelRect.hi.y += SG_DefaultLargeIcon + OnePixel*4; SelRect.lo.y -= (SG_DefaultLargeIcon + OnePixel*5); SelRect.hi.x = TextRect.hi.x; GridLockRect(MiscInfo, &SelRect); Renderer->DrawRect(&SelRect); } break; default: { DocRect SelRect(TextRect); // Text not in gallery, don't redraw if(TextRect.lo.x > Rectangle->hi.x) return; SelRect.hi.y = TextRect.lo.y + TextRect.Height()/2 - (OnePixel * 2); SelRect.lo.y = TextRect.lo.y + TextRect.Height()/2 + (OnePixel * 2); SelRect.hi.y += SG_DefaultLargeIcon/2; SelRect.lo.y -= (SG_DefaultLargeIcon/2 + OnePixel); SelRect.hi.x = TextRect.hi.x; GridLockRect(MiscInfo, &SelRect); Renderer->DrawRect(&SelRect); } break; } Renderer->SetFixedSystemTextColours(&RedrawInfo->SelForeground, &RedrawInfo->SelBackground); } else Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background); // No point drawing the text, etc... if(TextRect.lo.x + (OnePixel * 4) > Rectangle->hi.x) return; // Get the text into the text strings... String_256 DisplayText; String_256 DisplayText2; switch(DType) { case LibDisplay_FullInfo: // Work out proper text strings to display and display it // This string is also used by the sorting code, so use a common function to get it... if(!GetActualDisplayedText(&DisplayText, 1)) DisplayText = TEXT(""); if(!GetActualDisplayedText(&DisplayText2, 2)) DisplayText2 = TEXT(""); break; default: if(!GetActualDisplayedText(&DisplayText, 0)) DisplayText = TEXT(""); break; } if (bIsNew) { String_256 strTemp(_R(IDS_FOLDERNEW)); strTemp += _T(" "); strTemp += DisplayText; DisplayText = strTemp; } // And finally plot the text itself switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: { // Centred plot // Get the size of the text string DocRect TextBoundRect; Renderer->GetFixedSystemTextSize(&DisplayText, &TextBoundRect); // Centre the TextBoundRect about the TextRect TextBoundRect.Translate(TextRect.lo.x + (TextRect.Width()-TextBoundRect.Width())/2, TextRect.lo.y + (TextRect.Height()-TextBoundRect.Height())/2); // Ooops, too big... Use initial rectangle if(TextBoundRect.Width() > TextRect.Width() || TextBoundRect.Height() > TextRect.Height()) TextBoundRect = TextRect; // Draw the text Renderer->DrawFixedSystemText(&DisplayText, TextBoundRect); if (bIsNew) { *camStrchr(DisplayText, _T(' ')) = 0x00; Renderer->SetFixedSystemTextColours(&red, &RedrawInfo->Background); Renderer->DrawFixedSystemText(&DisplayText, TextBoundRect); Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background); } } break; case LibDisplay_FullInfo: { // Two line full info plot // Get the size of the text string DocRect TextBoundRect; Renderer->GetFixedSystemTextSize(&DisplayText, &TextBoundRect); // Work out the two bounding rectangles TextRect.lo.x += (OnePixel * 4); DocRect TopTextRect(TextRect); DocRect BottomTextRect(TextRect); INT32 Shift = (TextBoundRect.Height()/2) + (OnePixel * 2); TopTextRect.lo.y += Shift; TopTextRect.hi.y += Shift; BottomTextRect.lo.y -= Shift; BottomTextRect.hi.y -= Shift; // Draw the text Renderer->DrawFixedSystemText(&DisplayText, TopTextRect); if (bIsNew) { *camStrchr(DisplayText, _T(' ')) = 0x00; Renderer->SetFixedSystemTextColours(&red, &RedrawInfo->Background); Renderer->DrawFixedSystemText(&DisplayText, TopTextRect); Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background); } Renderer->DrawFixedSystemText(&DisplayText2, BottomTextRect); } break; default: // Left justified plot TextRect.lo.x += (OnePixel * 4); //SG_GapBeforeText; Renderer->DrawFixedSystemText(&DisplayText, TextRect); if (bIsNew) { *camStrchr(DisplayText, _T(' ')) = 0x00; Renderer->SetFixedSystemTextColours(&red, &RedrawInfo->Background); Renderer->DrawFixedSystemText(&DisplayText, TextRect); Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background); } break; } } /*********************************************************************************************** > BOOL SGLibDisplayItem::GetThumbSize(SGMiscInfo *MiscInfo, DocRect *Rectangle, KernelBitmap *Bitmap, INT32 *XSize, INT32 *YSize, double *Scale = NULL, INT32 *XTrans = NULL, INT32 *YTrans = NULL, BOOL *Outline = NULL) Author: Richard_Millican (Xara Group Ltd) Created: 27/4/95 Inputs: MiscInfo - Miscellaneous info as passed to the redraw handler by the sgallery code Rectangle - Pointer to a DocRect the size and position of which the selected rectangle will use, so we need to draw our thumbnail inside this. Background - TRUE if redrawing in backgrounding - return FALSE if not in buffer Outputs: XSize - Returned size of thumbnail to use in millipoints YSize - Returned size of thumbnail to use in millipoints Scale - Returns the Scale factor used XTrans - X translation required to centre image in rectangle YTrans - Y translation required to centre image in rectangle Outline - TRUE if the aspect ratio is such that we should put a rectangle round the item Returns: TRUE if things went OK, FALSE otherwise Purpose: Returns the size of thumbnail to render. For thumbnails, drawing them at a 1:1 aspect ratio looks much better than simply squashing them into an arbitrary rectangle. This code handles that... Notes: Going for the record number of parameters to a function ! SeeAlso: SGLibDisplayItem::HandleRedraw ***********************************************************************************************/ BOOL SGLibDisplayItem::GetThumbSize(SGMiscInfo *MiscInfo, DocRect *Rectangle, KernelBitmap *Bitmap, INT32 *XSize, INT32 *YSize, double *Scale, INT32 *XTrans, INT32 *YTrans, BOOL *Outline) { if( MiscInfo == NULL || Bitmap == NULL || Rectangle == NULL || Bitmap->ActualBitmap == NULL || XSize == NULL || YSize == NULL) { ERROR3("SGLibDisplayItem::GetThumbSize given null params"); return FALSE; } // Get the bitmap's dimensions BitmapInfo Info; BOOL InfoOK = Bitmap->ActualBitmap->GetInfo( &Info ); if(InfoOK == FALSE) { ERROR3("SGLibDisplayItem::GetThumbSize can't get bitmap info - corrupt bitmap ?"); return FALSE; } MILLIPOINT BmpWidth = 0; MILLIPOINT BmpHeight = 0; INT32 OnePixel = DevicePixels(MiscInfo, 1); BmpWidth = Info.PixelWidth * OnePixel; BmpHeight = Info.PixelHeight * OnePixel; MILLIPOINT BoundWidth = 0; MILLIPOINT BoundHeight = 0; // Get the details of the bounding rectangle // Slight bodge so we round up slightly in the division... Gets the pixel plan right BoundWidth = Rectangle->Width();// + 400; BoundHeight = Rectangle->Height();// + 400; double XScale = (double)BmpWidth / (double)BoundWidth; double YScale = (double)BmpHeight / (double)BoundHeight; double TheScale = 1.0; // Which is the greatest ? if(XScale > YScale) TheScale = XScale; else TheScale = YScale; // If we're nearly at the correct size for the thumb, don't rescale it - looks better if(TheScale > 0.8 && TheScale < 1.0) TheScale = (double)1.0; // Arg... don't want divide by zero show-stoppers, thank you very much ! if(TheScale == 0) return FALSE; *XSize = (INT32)(BmpWidth / TheScale); *YSize = (INT32)(BmpHeight / TheScale); if(Scale != NULL) *Scale = TheScale; if(XTrans != NULL) *XTrans = Rectangle->lo.x + ((BoundWidth - ((INT32)(BmpWidth / TheScale))) / 2); if(YTrans != NULL) *YTrans = Rectangle->lo.y + ((BoundHeight - ((INT32)(BmpHeight / TheScale))) / 2); if(Outline != NULL && (XScale/YScale) > 1.6) *Outline = TRUE; return TRUE; } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::DrawThumb(RenderRegion *Renderer, SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: Renderer - Pointer to RenderRegion in which to plot the bitmap rect RedrawInfo - Various bits of Redraw information such as colours MiscInfo - Miscellaneous info as passed to the redraw handler by the sgallery code Rectangle - Pointer to a DocRect the size and position of which the selected rectangle will use, so we need to draw our thumbnail inside this. Background - TRUE if redrawing in backgrounding - return FALSE if not in buffer Outputs: Returns: TRUE if things went OK, FALSE otherwise Purpose: Draws a thumbnail for the library item. This can be overridden, so the colour library for instance would plot a rectangle instead of a bitmap. For bitmaps, drawing them at a 1:1 aspect ratio looks much better than simply squashing them into an arbitrary rectangle. Notes: SeeAlso: SGLibDisplayItem::HandleRedraw ***********************************************************************************************/ BOOL SGLibDisplayItem::DrawThumb(RenderRegion *Renderer, SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) { KernelBitmap *Bitmap = GetDisplayedKernelBitmap(MiscInfo, Background); // Bitmap not there... if(Bitmap == NULL) return FALSE; INT32 XSize = 0; INT32 YSize = 0; double Scale = (double)1; INT32 XTrans = 0; INT32 YTrans = 0; BOOL Outline = FALSE; if(!GetThumbSize(MiscInfo, Rectangle, Bitmap, &XSize, &YSize, &Scale, &XTrans, &YTrans, &Outline)) return FALSE; DocRect BmpRect(0, 0, XSize, YSize); BmpRect.Translate(XTrans, YTrans); #if 0 // Setup the bitmap ready for plotting UINT32 InputBPP = Bitmap->GetBPP(); if(InputBPP >= 24) { CDC *pDC = Renderer->GetRenderDC(); INT32 OutputBPP = pDC->GetDeviceCaps(BITSPIXEL); if(OutputBPP == 8) { //ERROR3("Given a 32\\24bpp bitmap to plot on an 8bpp device"); } } #endif // Create a path with the bitmap in, ready for plotting... NodeBitmap *DummyBmp = new NodeBitmap(); if(DummyBmp == NULL) { ERROR3("SGLibDisplayItem::DrawThumb can't get node bitmap - not enough memory ?"); return FALSE; } DummyBmp->SetUpPath(); DummyBmp->CreateShape(BmpRect); DummyBmp->GetBitmapRef()->SetBitmap(Bitmap); // Plot white background rectangle... //Renderer->SetFillColour(RedrawInfo->Background); //Renderer->SetLineColour(COLOUR_TRANS); //RedrawInfo->Background); //Renderer->DrawRect(Rectangle); // Now render the bitmap DummyBmp->Render(Renderer); delete DummyBmp; // If we're displaying text underneath the thumbnail, add some space for it LibDisplayType DType = GetDisplayType(MiscInfo); // Extra space required by the text switch(DType) { case LibDisplay_SmallThumbTextUnder: case LibDisplay_MediumThumbTextUnder: case LibDisplay_LargeThumbTextUnder: // Text is underneath // Border around small objects if(Outline) { INT32 OnePixel = DevicePixels(MiscInfo, 1); Renderer->SetLineWidth(0); Renderer->SetLineColour(DocColour(COLOUR_TRANS)); Renderer->SetFillColour(DocColour(COLOUR_GREY)); DocRect TempRect(*Rectangle); // Left TempRect.Inflate(OnePixel); TempRect.hi.x = TempRect.lo.x + OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Top TempRect.Inflate(OnePixel); TempRect.lo.y = TempRect.hi.y - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Right TempRect.Inflate(OnePixel); TempRect.lo.x = TempRect.hi.x - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Bottom TempRect.Inflate(OnePixel); TempRect.hi.y = TempRect.lo.y + OnePixel; Renderer->DrawRect(&TempRect); } break; default: // don't add a rectangle unless the text is below - hence a long way away break; } // Drawn bitmap preview ok return TRUE; } /*********************************************************************************************** > static void SGLibDisplayItem::DrawNullBitmapRect(RenderRegion *Renderer, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: Renderer - Pointer to RenderRegion in which to plot the bitmap rect MiscInfo - Miscellaneous info as passed to the redraw handler by the sgallery code Rectangle - Pointer to a DocRect the size and position of where the bitmap would be positioned normally Background - If true, draw a background redrawing, not plotted proper thumbnail rectangle Outputs: Returns: Purpose: Draws a rectangle with two lines crossing it, to signify that the thumbnail could not be found, or could not be generated. Notes: SeeAlso: SGLibDisplayItem::HandleRedraw ***********************************************************************************************/ void SGLibDisplayItem::DrawNullBitmapRect(RenderRegion *Renderer, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) { if(Renderer == NULL || MiscInfo == NULL || Rectangle == NULL) { ERROR3("SGLibDisplayItem::DrawNullBitmapRect null params are BAD"); return; } // Draw the 'blank' bitmap if(!Background) Renderer->SetFillColour(COLOUR_GREY); else { DocColour NullBitmapColour(230L, 230L, 230L); Renderer->SetFillColour(NullBitmapColour); } GridLockRect(MiscInfo, Rectangle); Renderer->DrawRect(Rectangle); // Yes I know it's horrible, but since we're now a static, DevicePixels doesn't seem to work INT32 OnePixel = MiscInfo->PixelSize; Renderer->SetLineWidth(0); Renderer->SetLineColour(DocColour(COLOUR_TRANS)); Renderer->SetFillColour(DocColour(COLOUR_BLACK)); DocRect TempRect(*Rectangle); // Left TempRect.hi.x = TempRect.lo.x + OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Top TempRect.lo.y = TempRect.hi.y - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Right TempRect.lo.x = TempRect.hi.x - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Bottom TempRect.hi.y = TempRect.lo.y + OnePixel; Renderer->DrawRect(&TempRect); if(!Background) { // Pop two intersecting lines through the centre of the rectangle to signify // that the item doesn't have a thumbnail TempRect = *Rectangle; // Middle X TempRect.hi.y = TempRect.lo.y + (TempRect.Height() / 2); TempRect.lo.y = TempRect.hi.y; GridLockRect(MiscInfo, &TempRect); TempRect.hi.y += OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Middle Y TempRect.hi.x = TempRect.lo.x + (TempRect.Width() / 2); TempRect.lo.x = TempRect.hi.x; GridLockRect(MiscInfo, &TempRect); TempRect.hi.x += OnePixel; Renderer->DrawRect(&TempRect); } } /*********************************************************************************************** > virtual LibDisplayType SGLibDisplayItem::GetDisplayType(SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: MiscInfo - Contains a few useful bits of info that may be needed for all event types. Outputs: Returns: The display mode type to use (position of text, and size of thumb) Purpose: Return the display type to use - this should be overridden by the library gallery using the code. Notes: There is the possibility that the MiscInfo passed only has a valid DisplayMode setup - the rest might be garbage ***********************************************************************************************/ LibDisplayType SGLibDisplayItem::GetDisplayType(SGMiscInfo *MiscInfo) { switch(MiscInfo->DisplayMode) { case 1: return LibDisplay_SmallThumbText; break; case 2: return LibDisplay_FullInfo; break; case 0: default: return LibDisplay_LargeThumbTextUnder; break; } return LibDisplay_LargeThumbTextUnder; } /*********************************************************************************************** > virtual void SGLibDisplayItem::GetFileName(String_256 *Result); Author: Richard_Millican (Xara Group Ltd) Created: 27/10/95 Inputs: Outputs: Result - String to place resulting filename in Purpose: Returns the filename (without path) for the given item This is needed by the searching code ***********************************************************************************************/ void SGLibDisplayItem::GetFileName(String_256 *Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetFileName given a NULL param"); // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); if (Lib != NULL) { Lib->GetFilename(TheLibraryIndex, Result, FALSE); } else { *Result = ""; } } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::GetFileName(String_256 *Result); Author: Richard_Millican (Xara Group Ltd) Created: 27/10/95 Inputs: Outputs: Result - String to place resulting filename in Purpose: Returns the filename (without path) for the given item This is needed by the searching code Notes: Quicker than previous String_256 version... ***********************************************************************************************/ BOOL SGLibDisplayItem::GetFileNamePtr(TCHAR **Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetFileName given a NULL param"); BOOL ok = FALSE; // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); if (Lib != NULL) ok = Lib->GetFilename(TheLibraryIndex, Result); else ok = FALSE; return (ok); } /*********************************************************************************************** > virtual void SGLibDisplayItem::GetNameText(String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: Outputs: Result - String to place resulting text in Returns: The display mode type to use (position of text, and size of thumb) Purpose: Returns the name text for this item, to support simple searching and sorting operations, and generic redraw methods for library items. ***********************************************************************************************/ void SGLibDisplayItem::GetNameText(String_256 *Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetNameText given a NULL param"); // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); if (Lib != NULL) { if(!Lib->GetTitle(TheLibraryIndex, Result)) Lib->GetFilename(TheLibraryIndex, Result, FALSE); } else { *Result = ""; } } /*********************************************************************************************** > BOOL SGLibDisplayItem::GetNameTextPtr(TCHAR **Result) Author: Richard_Millican (Xara Group Ltd) Created: 3/5/95 Inputs: Outputs: Result - points to name in memory if the index file is cached Returns: TRUE if index was cached and name found ok, etc... Purpose: Returns a pointer to the filename for this item... The main use of this call is to speed sorting up, since passing pointers about is much quicker than constructing strings.... Notes: BEWARE: If the index file is not in memory this call will probably fail ! ***********************************************************************************************/ BOOL SGLibDisplayItem::GetNameTextPtr(TCHAR **Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetNameText given a NULL param"); // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); BOOL ok = FALSE; if (Lib != NULL) { ok = Lib->GetTitle(TheLibraryIndex, Result); if(!ok) ok = Lib->GetFilename(TheLibraryIndex, Result); } return ok; } /*********************************************************************************************** > virtual void SGLibDisplayItem::GetFullInfoText(String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Outputs: Result - String to place resulting text in Purpose: Returns the full-info text for this item, to support simple searching operations, and generic redraw methods for library items. Notes: This overrides the sgdisplaynode version to give full information... SeeAlso: ***********************************************************************************************/ void SGLibDisplayItem::GetFullInfoText(String_256 *Result) { // Call the below function to get a full line of text... GetFullInfoText(Result, 0); } /*********************************************************************************************** > virtual void SGLibDisplayItem::GetFullInfoText(String_256 *Result, INT32 Line = 0) Author: Richard_Millican (Xara Group Ltd) Created: 14/3/95 Inputs: Line - Line number for multi-line strings. All multi-liners start from 1, and return FALSE if an invalid line is supplied. Setting Line to 0 will return all the text information, String_256 permitting of course... Outputs: Result - String to place resulting text in Purpose: Returns the full-info text for this item, to support simple searching operations, and generic redraw methods for library items. Notes: SeeAlso: ***********************************************************************************************/ void SGLibDisplayItem::GetFullInfoText(String_256 *Result, INT32 Line) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetFullInfoText given a NULL param"); // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); if (Lib == NULL) { ERROR3("Lib == NULL in GetFullInfoText"); *Result = ""; } else { // No text if Line is set to something weird... *Result = TEXT(""); String_256 Text; // Full description and title, as given in the index if(Line < 2 && Line >= 0) { GetDisplayedTextDescription(&Text); BOOL FullDescription = (Text.Length() > 0); *Result = Text; // Title used in normal display modes if(Lib->GetTitle(TheLibraryIndex, &Text)) { if(FullDescription) { // " (Text)" String_256 TmpResult; TmpResult.MakeMsg(_R(IDS_SGLIB_FULLDESCRIPTION), (TCHAR *)Text); *Result += TmpResult; } else *Result += Text; } } // Trivial bit of logic made tricky here... // If the first line was blank, give it the Filename, else only give the second // line the filename BOOL GiveLineFileName = FALSE; if((Line == 0) || (Line == 1 && Result->Length() == 0)) GiveLineFileName = TRUE; if(Line == 2) { GiveLineFileName = FALSE; GetDisplayedTextDescription(&Text); if(Text.Length() > 0) GiveLineFileName = TRUE; // Title used in normal display modes if(Lib->GetTitle(TheLibraryIndex, &Text)) if(Text.Length() > 0) GiveLineFileName = TRUE; } // The line needs the filename... if(GiveLineFileName) { // Filename of file without the path Lib->GetFilename(TheLibraryIndex, &Text, FALSE); /* if(Line == 0) *Result += TEXT(", "); *Result += TEXT("'"); *Result += Text; *Result += TEXT("'"); if(Line != 1) *Result += TEXT(", ");*/ String_256 FileNameBit; switch(Line) { case 0: FileNameBit.MakeMsg(_R(IDS_SGLIB_FNAMEBIT_LINE0), (TCHAR *)Text); //", '#1%s', " break; case 1: FileNameBit.MakeMsg(_R(IDS_SGLIB_FNAMEBIT_LINE1), (TCHAR *)Text); //"'#1%s'" break; default: FileNameBit.MakeMsg(_R(IDS_SGLIB_FNAMEBIT_DEFAULT), (TCHAR *)Text); //"'#1%s', " break; } *Result += FileNameBit; } // Filesize of file, expressed in a pleasant textual format if((Line == 0) || (Line == 2)) { INT32 FileSize = GetFileSize(Lib); if(Convert::BytesToString(&Text, (UINT32)FileSize)) { *Result += Text; } } } } /*********************************************************************************************** > virtual void SGLibDisplayItem::GetKeyWords(String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 30/3/95 Outputs: On exit, the string pointed at by Result will contain either a blank string, or a list of | seperated keywords associated with the item Purpose: To determine the keywords for this node. Generally, this is used for a simple searching mechanism. Notes: The base class returns a blank string. If you can provide a better name string, then override the base class method to do so. SeeAlso: SGDisplayNode::GetFullInfoText ***********************************************************************************************/ void SGLibDisplayItem::GetKeyWords(String_256 *Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetKeyWords given a NULL param"); if(Result == NULL) return; *Result = ""; //SGDisplayGroup *SGGroup = (SGDisplayGroup *) GetParent(); SuperGallery *Parent = (SuperGallery *)GetParentGallery(); if(Parent != NULL) { if(Parent->CanSearchKeywords()) { Library *Lib = GetParentLibrary(); if (Lib != NULL) { String_64 Key(_R(IDS_LIBRARIES_INDEX_ITEM_KEY)); Lib->GetSingleField(TheLibraryIndex, &Key, Result); } } } } /*********************************************************************************************** > INT32 SGLibDisplayItem::GetFileSize(Library *Lib == NULL) Author: Richard_Millican (Xara Group Ltd) Created: 13/4/95 Inputs: Lib can optionally point to the library to use - we can get it if it doesn't. Outputs: On exit, the string pointed at by Result will contain either a blank string, or a list of | seperated keywords associated with the item Purpose: To determine the keywords for this node. Generally, this is used for a simple searching mechanism. Notes: The base class returns a blank string. If you can provide a better name string, then override the base class method to do so. SeeAlso: SGDisplayNode::GetFullInfoText ***********************************************************************************************/ INT32 SGLibDisplayItem::GetFileSize(Library *Lib) { // Check the index file first... if (Lib == NULL) Lib = GetParentLibrary(); if (Lib != NULL) { String_64 SizeTxt(_R(IDS_LIBRARIES_INDEX_ITEM_SIZE)); String_64 Result; if(Lib->GetSingleField(TheLibraryIndex, &SizeTxt, &Result)) { INT32 size = _ttoi((TCHAR *)Result); if(size > 0) return size; } } // If the index info is not available, or the size was 0 in the index, // resort to using the OS on the file PathName ItemPath; GetFileName(&ItemPath); return SGLibOil::FileSize(&ItemPath); } /******************************************************************************************** > virtual BOOL SGLibDisplayItem::GetBubbleHelp(DocCoord *MousePos, String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 1/6/95 Inputs: MousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a bubble help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when bubble help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetStatusLineHelp ********************************************************************************************/ BOOL SGLibDisplayItem::GetBubbleHelp(DocCoord *MousePos, String_256 *Result) { ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params"); return FALSE; } /******************************************************************************************** > virtual BOOL SGLibDisplayItem::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 6/1/95 Inputs: MousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a status line help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when status line help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetBubbleHelp ********************************************************************************************/ BOOL SGLibDisplayItem::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result) { ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params"); GetNameText(Result); // Filesize of file, expressed in a pleasant textual format String_32 SizeString; INT32 FileSize = GetFileSize(NULL); if(Convert::BytesToString(&SizeString, (UINT32)GetFileSize(NULL))) { String_32 TmpStr; TmpStr.MakeMsg(_R(IDS_SGLIB_STAT_LINE_SIZE), (TCHAR *)SizeString); *Result += TmpStr; // " (Size)" } /* Double click to open this file, or drag and drop */ String_256 DClick(_R(IDS_LIBRARY_DOUBLE_CLICK_OPEN)); *Result += String_8(_R(IDS_SGFONTS_STATUS_LINE_SEP)); // "; " *Result += DClick; return(TRUE); } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 27/1/95 Inputs: EventType - An enumerated value describing what type of event is to be processed EventInfo - A structure describing the event (may be NULL). The exact thing pointed at by this pointer depends upon the event type: MonoOn Event Thing EventInfo points at SGEVENT_FORMAT (SGFormatInfo *) SGEVENT_REDRAW (SGRedrawInfo *) SGEVENT_MOUSECLICK (SGMouseInfo *) MonoOff Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this information - they provide useful error/type checking, and hide the cast MiscInfo - always provided. Contains a few useful bits of info that may be needed for all event types. Outputs: FormatInfo is updated as appropriate Returns: TRUE if the event was handled successfully FALSE if it was not Purpose: Handles a SuperGallery DisplayTree event Notes: This overrides the pure virtual SGDisplayNode::HandleEvent method A node need not handle a specific event - if it does not handle it, it should return FALSE. Redraw and Formatting handlers should never return TRUE, as this will prevent the event from continuing through the tree. Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order to pass the event dow the tree. THIS node is a leaf-node, so it doesn't. SeeAlso: SGDisplayNode::HandleEvent ***********************************************************************************************/ BOOL SGLibDisplayItem::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) { switch (EventType) { case SGEVENT_FORMAT: { SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo); CalculateMyRect(FormatInfo, MiscInfo); // Cache our FormatRect for later use } break; case SGEVENT_REDRAW: { DocRect MyRect(FormatRect); // Rely on FormatRect being cached from above SGRedrawInfo *RedrawInfo = GetRedrawInfo(EventType, EventInfo); if (IMustRedraw(RedrawInfo)) // only redraw if we intersect the clip rect HandleRedraw(RedrawInfo, MiscInfo); } break; // exit and return FALSE to pass the redraw event on case SGEVENT_MOUSECLICK: { SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo); if (FormatRect.ContainsCoord(Mouse->Position)) { // No drag, so move on to normal selection click handling DefaultClickHandler(Mouse, MiscInfo); return(TRUE); } } break; default: return(SGDisplayItem::HandleEvent(EventType, EventInfo, MiscInfo)); break; } // Default return value: We do not claim this event, so it will be passed on to others return(FALSE); } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::StartDrag(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo, INT32 *XSize, INT32 *YSize) Author: Richard_Millican (Xara Group Ltd) Created: 18/12/95 Inputs: EventType - An enumerated value describing what type of event is to be processed EventInfo - A structure describing the event MiscInfo - always provided. Contains a few useful bits of info that may be needed for all event types. Outputs: XSize, YSize - Dimensions of object to drag Returns: TRUE if it was a drag, false if double-click Purpose: Sets the TmpDraggingBitmap up, and returns the sizes to the caller. Notes: If this returns FALSE, don't try to create the drag object because something bad has happened. If it returns TRUE though, you should create the DragInfo object and call DragManagerOp::StartDrag(DragClipart); ***********************************************************************************************/ BOOL SGLibDisplayItem::StartDrag(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo, INT32 *XSize, INT32 *YSize) { SGMouseInfo *Mouse = GetMouseInfo(EventType, EventInfo); if (Mouse->DoubleClick) { DefaultClickHandler(Mouse, MiscInfo); return FALSE; } else { DefaultPreDragHandler(Mouse, MiscInfo); // Grab a copy of the bitmap required for dragging KernelBitmap *DispBmp = GetDisplayedKernelBitmap(MiscInfo, TRUE); if(DispBmp) LibraryGallery::TmpDraggingBitmap = DIBUtil::CopyKernelBitmap(DispBmp, TRUE); else LibraryGallery::TmpDraggingBitmap = NULL; // Find the displayed pixel sizes of the bitmap to drag Library *ParentLib = GetParentLibrary(); if(ParentLib != 0) { // Thumbnail cache for library SGThumbs *Thumbs = ParentLib->Thumbnails; if(Thumbs != NULL) { // Get current size from thumbnail cache SGThumbSize ThumbSize = SGThumb_Large; if(Thumbs->GetSize(&ThumbSize)) { *XSize = ParentLib->PreviewBMPWidth(ThumbSize); *YSize = ParentLib->PreviewBMPHeight(ThumbSize); if(LibraryGallery::TmpDraggingBitmap != NULL) { INT32 OnePixel = (INT32) DevicePixels(MiscInfo, 1); DocRect Rectangle(0, 0, (*XSize) * OnePixel, (*YSize) * OnePixel); // Get the proper aspect ratio'd clipped XSize and YSize (MILLIPOINTS) if(!GetThumbSize(MiscInfo, &Rectangle, LibraryGallery::TmpDraggingBitmap, XSize, YSize)) { *YSize = 0; *XSize = 0; } else { // Convert Millipoint values into pixel values *XSize = (*XSize) / OnePixel; *YSize = (*YSize) / OnePixel; } } } } } } return TRUE; } /*********************************************************************************************** > Library *SGLibDisplayItem::GetParentLibrary(void) Author: Richard_Millican (Xara Group Ltd) Created: 21/2/95 Returns: NULL if a serious error occurred (ERROR2 reported) else a pointer to the parent SGSubLib library object Purpose: Finds the library for which this DisplayItem displays an item. ***********************************************************************************************/ Library *SGLibDisplayItem::GetParentLibrary(void) { SGDisplayGroup *Parent = (SGDisplayGroup *) GetParent(); if (Parent == NULL) { ERROR2RAW("Infeasible gallery display tree structure detected"); return(NULL); } Library *ParentLib = Parent->GetParentLibrary(); /*if (ParentLib == NULL) { ERROR2RAW("Supergallery library display item has no attached library!"); return(NULL); }*/ return(ParentLib); } /******************************************************************************************** > KernelBitmap *SGLibDisplayItem::GetDisplayedKernelBitmap(SGMiscInfo *MiscInfo, BOOL Background) Author: Richard_Millican (Xara Group Ltd) Created: 19/02/95 Inputs: MiscInfo - misc info given to the gallery redraw code Background - if false then redrawing in foreground - only return bmp if in cache Outputs: Returns: A pointer to the KernelBitmap which this Display Item is used to display, or NULL if there is no thumbnail (e.g. a colour library has no thumbs), or the thumbnail failed to load/cache Purpose: To find out the KernelBitmap this object is responsible for displaying ********************************************************************************************/ KernelBitmap *SGLibDisplayItem::GetDisplayedKernelBitmap(SGMiscInfo *MiscInfo, BOOL Background) { KernelBitmap *BM = NULL; SGThumbSize Size = SGThumb_Large; // Get the current display mode type LibDisplayType DType = GetDisplayType(MiscInfo); // Which thumbnail should we be asking the thumb cache for ? switch(DType) { case LibDisplay_MediumThumbText: case LibDisplay_MediumThumbTextUnder: case LibDisplay_MediumThumb: case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: Size = SGThumb_Medium; break; case LibDisplay_SmallThumbText: case LibDisplay_SmallThumbTextUnder: case LibDisplay_SmallThumb: Size = SGThumb_Small; break; case LibDisplay_JustText: return NULL; default: Size = SGThumb_Large; break; } // If we can get a Library from an item, we're sorted... Library *Lib = GetParentLibrary(); // For background redraws we want the bitmap, but for foreground ones we only want // it if it's in the cache... BOOL GotIt = FALSE; if (Lib != NULL) GotIt = Lib->GetThumbnail(TheLibraryIndex, Size, Background, &BM); if(GotIt) return(BM); else return NULL; } /******************************************************************************************** > BOOL SGLibDisplayItem::GetDisplayedTextDescription(String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 19/02/95 Outputs: Result - will be filled in with the Description string which this Display Item uses. Returns: FALSE if it failed, else TRUE Purpose: To find the Text description for this object ********************************************************************************************/ BOOL SGLibDisplayItem::GetDisplayedTextDescription(String_256 *Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetDisplayedTextDescription - NULL param is illegal"); BOOL ok = FALSE; Library *Lib = GetParentLibrary(); // Get the name using our library code if (Lib != NULL) ok = Lib->GetTextname(TheLibraryIndex, Result); // Ensure String wiped if any problems if(!ok) *Result = TEXT(""); return ok; } /******************************************************************************************** > BOOL SGLibDisplayItem::GetDisplayedTextDescription(TCHAR **Result) Author: Richard_Millican (Xara Group Ltd) Created: 18/05/95 Outputs: Result - will be filled in with the Description string which this Display Item uses. Returns: FALSE if it failed, else TRUE Purpose: To find the Text description for this object Notes: Will return false if the index is not in memory... ********************************************************************************************/ BOOL SGLibDisplayItem::GetDisplayedTextDescription(TCHAR **Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetDisplayedTextDescription - NULL param is illegal"); Library *Lib = GetParentLibrary(); // Get the name using our library code if (Lib != NULL) return(Lib->GetTextname(TheLibraryIndex, Result)); return(FALSE); } /******************************************************************************************** > BOOL SGLibDisplayItem::GetFileName(PathName *Result) Author: Richard_Millican (Xara Group Ltd) Created: 17/03/95 Outputs: Result - will be filled in with the full filename of the object Returns: FALSE if it failed, else TRUE Purpose: To find the corresponding filename for this object ********************************************************************************************/ BOOL SGLibDisplayItem::GetFileName(PathName *Result) { ERROR3IF(Result == NULL, "SGLibDisplayItem::GetFileName - NULL param is illegal"); Library *Lib = GetParentLibrary(); Result->SetPathName(String_8(""), FALSE); // Ensure path wiped if we fail //Error::ClearError(); // Get the name using our library code if (Lib != NULL) { String_256 TmpPath; BOOL ok = Lib->GetFilename(TheLibraryIndex, &TmpPath, TRUE); Result->SetPathName(TmpPath); // Dodgy pathname if(!ok && !Result->IsValid()) ok = FALSE; return ok; } return FALSE; } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::GetActualDisplayedText(String_256 *String, INT32 Line = 0) Author: Richard_Millican (Xara Group Ltd) Created: 22/5/95 Inputs: Line - Line number for multi-line strings. All multi-liners start from 1, and return FALSE if an invalid line is supplied. Setting Line to 0 will return all the text information, String_256 permitting of course... Outputs: String - Returns the string that will actually be displayed in the current mode Returns: TRUE if all went ok Purpose: Returns the mode-sensitive string that will actually be displayed. This is handy for sorting methods, etc... ***********************************************************************************************/ BOOL SGLibDisplayItem::GetActualDisplayedText(String_256 *String, INT32 Line) { ERROR3IF(String == NULL, "SGLibDisplayItem::GetActualDisplayedText with params is a real recipe for disaster"); // We're going to do something horrible here... SGMiscInfo MiscInfo; SuperGallery *ParentGal = GetParentGallery(); ERROR3IF(ParentGal == NULL, "SGLibDisplayItem::GetActualDisplayedText with null parent gallery"); MiscInfo.DisplayMode = ParentGal->GetDisplayMode(); LibDisplayType DType = GetDisplayType(&MiscInfo); // Work out proper text string to display and display it switch(DType) { case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: // Use the full info description GetFullInfoText(String, Line); break; default: // Just use the normal text description GetNameText(String); break; } return TRUE; } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::GetActualDisplayedTextPtr(TCHAR **String, INT32 Line = 0) Author: Richard_Millican (Xara Group Ltd) Created: 22/5/95 Inputs: Line - Line number for multi-line strings. All multi-liners start from 1, and return FALSE if an invalid line is supplied. Setting Line to 0 will return all the text information, String_256 permitting of course... Outputs: String - Returns a ptr to the string that will actually be displayed in the current mode Returns: TRUE if all went ok Purpose: Returns the mode-sensitive string ptr that will actually be displayed. This is handy for sorting methods, etc... ***********************************************************************************************/ BOOL SGLibDisplayItem::GetActualDisplayedTextPtr(TCHAR **String, INT32 Line) { ERROR3IF(String == NULL, "SGLibDisplayItem::GetActualDisplayedText with params is a real recipe for disaster"); // We're going to do something horrible here... SGMiscInfo MiscInfo; SuperGallery *ParentGal = GetParentGallery(); ERROR3IF(ParentGal == NULL, "SGLibDisplayItem::GetActualDisplayedText with null parent gallery"); MiscInfo.DisplayMode = ParentGal->GetDisplayMode(); LibDisplayType DType = GetDisplayType(&MiscInfo); // Work out proper text string to display and display it switch(DType) { case LibDisplay_FullInfo: case LibDisplay_SingleLineFullInfo: // Use the full info description - can't do this in memory return FALSE; default: // Just use the normal text description return GetNameTextPtr(String); } return FALSE; } /*********************************************************************************************** > virtual INT32 SGLibDisplayItem::CompareTo(SGDisplayNode *Other, INT32 SortKey) Author: Richard_Millican (Xara Group Ltd) Created: 13/4/95 Inputs: Other - the node to compare this node to SortKey - An integer identifying how to compare the items 0 = No sorting (always returns 0) 1 = Sort-by-name 2 = sort by size (memory size) 3 = sort by name length 4 = sort by type 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) Purpose: 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. SeeAlso: SGDisplayNode::AddItem ***********************************************************************************************/ INT32 SGLibDisplayItem::CompareTo(SGDisplayNode *Other, INT32 SortKey) { switch(SortKey) { case 1: // Sort by name - override default and make 'FRED' and 'fred' equal... // Note - we should really make "'Fred'" and "Fred'" equal, since full info sorting // can be a bit rampant if you don't know what's going on... { BOOL FoundPtr = FALSE; #ifndef _BATCHING // Normal, quick alphabetic sorting TCHAR *pOurName = NULL; TCHAR *pTheirName = NULL; FoundPtr = GetActualDisplayedTextPtr(&pOurName); if(FoundPtr) { FoundPtr = ((SGLibDisplayItem *)Other)->GetActualDisplayedTextPtr(&pTheirName); if(FoundPtr) { // Two TCHAR *'s... INT32 Value = 0; // This little beastie (below) is the DBCS string comparison flob which we should // be using for the Jap's, and so forth... // 1 if pOurName < pTheirName // 2 if pOutName == pTheirName // 3 if pOutName > pTheirName Value = CompareString(LOCALE_USER_DEFAULT, (NORM_IGNORECASE | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH), pOurName, -1, pTheirName, -1); // 1.42 Value -= 2; return (Value); } } // Fields not found, or index file not cached in memory String_256 MyName; String_256 ItsName; GetActualDisplayedText(&MyName); MyName.toLower(); ((SGLibDisplayItem *)Other)->GetActualDisplayedText(&ItsName); ItsName.toLower(); return(MyName.CompareTo(ItsName)); #else // Not so quick, special alphabetic sorting (fred20 > fred10 > fred5 > fred) String_256 MyName; String_256 ItsName; GetActualDisplayedText(&MyName); MyName.toLower(); ((SGLibDisplayItem *)Other)->GetActualDisplayedText(&ItsName); ItsName.toLower(); if(Library::MaxFieldCacheEntries == 50 && MyName == ItsName) { ERROR3_PF(("Identical sort entries found: '%s'", (TCHAR *)MyName)); } INT32 FSize = GetFileSize(NULL); if(FSize == 0) { ERROR3_PF(("Filesize <= 0 found: '%s'", (TCHAR *)MyName)); } INT32 MRCount = MyName.Length() - 1; BOOL MFound = FALSE; TCHAR TheChar = ((TCHAR *)MyName)[MRCount]; while(((TheChar == ' ') || (TheChar >= '0' && TheChar <= '9')) && MRCount > 0) { if(TheChar != ' ') MFound = TRUE; TheChar = ((TCHAR *)MyName)[--MRCount]; } INT32 IRCount = ItsName.Length() - 1; BOOL IFound = FALSE; TheChar = ((TCHAR *)ItsName)[IRCount]; while(((TheChar == ' ') || (TheChar >= '0' && TheChar <= '9')) && IRCount > 0) { if(TheChar != ' ') IFound = TRUE; TheChar = ((TCHAR *)ItsName)[--IRCount]; } if(IFound && MFound) { String_256 MyLeft; String_256 ItsLeft; MyName.Left(&MyLeft, MRCount + 1); ItsName.Left(&ItsLeft, IRCount + 1); if(MyLeft == ItsLeft) { String_256 MyRight; String_256 ItsRight; MyName.Right(&MyRight, MyName.Length() - MRCount - 1); ItsName.Right(&ItsRight, ItsName.Length() - IRCount - 1); INT32 Me = _ttoi((TCHAR *)MyRight); INT32 It = _ttoi((TCHAR *)ItsRight); if(Me > It) return 1; else if(Me < It) return -1; } } return(MyName.CompareTo(ItsName, FALSE)); #endif } case 2: // Sort by size { Library *Lib = GetParentLibrary(); return(GetFileSize(Lib) - ((SGLibDisplayItem *)Other)->GetFileSize(Lib)); } case 3: // Sort by name length { String_256 MyName; String_256 ItsName; GetActualDisplayedText(&MyName); ((SGLibDisplayItem *)Other)->GetActualDisplayedText(&ItsName); return (MyName.Length() - ItsName.Length()); } break; case 4: // Sort by file type { PathName MyPath; PathName ItsPath; GetFileName(&MyPath); ((SGLibDisplayItem *)Other)->GetFileName(&ItsPath); Error::ClearError(); if(MyPath.IsValid() && ItsPath.IsValid()) { String_8 MyType(MyPath.GetType()); String_8 ItsType(ItsPath.GetType()); return(MyType.CompareTo(ItsType, FALSE)); } } break; } return (SGDisplayNode::CompareTo(Other, SortKey)); } /*********************************************************************************************** > virtual void SGLibDisplayItem::DragWasReallyAClick(SGMouseInfo *Mouse, SGMiscInfo *MiscInfo) Author: Will_Cowling (Xara Group Ltd) Created: 8/4/95 Inputs: Mouse - The mouse info passed to the original click handler MiscInfo - The misc info passed to the original click handler Purpose: Handles a mouse click event. This is a callback function - drags of bitmaps from galleries will call this function back if the drag turns out to just be a click. SeeAlso: SGFillsItem::HandleEvent; GalleryFillsDragInfo::OnClick ***********************************************************************************************/ void SGLibDisplayItem::DragWasReallyAClick(SGMouseInfo *Mouse, SGMiscInfo *MiscInfo) { // Just get default selection action to be applied for this click DefaultClickHandler(Mouse, MiscInfo, TRUE); } /*********************************************************************************************** > SGLibGroup::SGLibGroup(SuperGallery *ParentGal, Document *ParentDoc = NULL, Library *ParentLib = NULL, String_64 *Text) Author: Richard_Millican (Xara Group Ltd) Created: 20/4/95 Inputs: ParentGal - points to the SuperGallery object which 'owns' this node ParentDoc - NULL, or a pointer to the document this group references ParentLib - NULL, or a pointer to the library this group references Purpose: SGLibGroup constructor. Initialises the Group's parent pointers to point at its parent(s). Note that generally speaking, one of ParentDoc, ParentLib will be NULL, and the other will be non-NULL. Notes: This constructor does nothing - jusat passes the call on to the baseclass constructor of identical proportions. SeeAlso: SGDisplayGroup::SGDisplayGroup ***********************************************************************************************/ SGLibGroup::SGLibGroup(SuperGallery *ParentGal, Document *ParentDoc, Library *ParentLib) : SGDisplayGroup(ParentGal, ParentDoc, ParentLib) { // Library groups can be selected Flags.CanSelect = TRUE; SetVirtualisedState(FALSE); } /*********************************************************************************************** > void SGLibGroup::ReadGroupTitle(void) Author: Richard_Millican (Xara Group Ltd) Created: 20/4/95 Inputs: - Outputs: - Purpose: Since we now store the group text with the group, we have to overwrite the normal ReadGroupTitle member. This new one simply does nothing. ***********************************************************************************************/ void SGLibGroup::ReadGroupTitle(void) { } /*********************************************************************************************** > virtual BOOL SGLibGroup::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) Author: Richard_Millican (Xara Group Ltd) Created: 20/4/95 Inputs: EventType - An enumerated value describing what type of event is to be processed EventInfo - A structure describing the event (may be NULL). The exact thing pointed at by this pointer depends upon the event type: MonoOn Event Thing EventInfo points at SGEVENT_FORMAT (SGFormatInfo *) SGEVENT_REDRAW (SGRedrawInfo *) SGEVENT_MOUSECLICK (SGMouseInfo *) MonoOff Use the provided SGDisplayNode::Get[Format]Info() inlines to retrieve this information - they provide useful error/type checking, and hide the cast MiscInfo - always provided. Contains a few useful bits of info that may be needed for all event types. Outputs: Returns: TRUE if the event was handled successfully FALSE if it was not Purpose: Handles a library group event - thumbnail resizing, etc... SeeAlso: SGDisplayNode::HandleEvent ***********************************************************************************************/ BOOL SGLibGroup::HandleEvent(SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) { switch (EventType) { case SGEVENT_THUMBMSG: { ThumbMessage *Msg = (ThumbMessage *) EventInfo; if(Msg != NULL) { switch (Msg->State) { // Resize the library thumbnail cache case ThumbMessage::ThumbState::CACHESIZECHANGED: { Library *TheLib = GetParentLibrary(); if(TheLib == NULL) { ERROR3("SGLibGroup::HandleEvent Library == NULL for library group - bad !!!"); } else { // Thumbnail cache associated with library SGThumbs *Thumbs = TheLib->Thumbnails; if(Thumbs != NULL) { // Rip the details out of the old cache PathName OldPath(*(Thumbs->GetDirectory())); SGLibType OldType = Thumbs->GetType(); SGThumbSize OldSize; Thumbs->GetSize(&OldSize); // Just check the new cache will know it's maximum size SGThumbs::MaxThumbnails = Msg->NewSize; // Kill off the old cache and reclaim all the memory delete Thumbs; // Create the new cache Thumbs = new SGThumbs(&OldPath, OldType, OldSize); // Assign the new cache to the library TheLib->Thumbnails = Thumbs; } } } break; case ThumbMessage::ThumbState::KILLCACHE: { Library *TheLib = GetParentLibrary(); if(TheLib == NULL) { ERROR3("SGLibGroup::HandleEvent Library == NULL for library group - bad !!!"); } else { // Thumbnail cache associated with library SGThumbs *Thumbs = TheLib->Thumbnails; if(Thumbs != NULL) { if(Thumbs->GetType() == Msg->Type) { // Reclaim thumbnail cache memory Thumbs->DeleteThumbnails(); } } } } break; } } } break; } // Pass back the event return SGDisplayGroup::HandleEvent(EventType, EventInfo, MiscInfo); } /******************************************************************************************** > virtual BOOL SGLibGroup::GetBubbleHelp(DocCoord *MousePos, String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 1/6/95 Inputs: MousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a bubble help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when bubble help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetStatusLineHelp ********************************************************************************************/ BOOL SGLibGroup::GetBubbleHelp(DocCoord *MousePos, String_256 *Result) { ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params"); return FALSE; } /******************************************************************************************** > virtual BOOL SGLibGroup::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result) Author: Richard_Millican (Xara Group Ltd) Created: 6/1/95 Inputs: MousePos - The current mouse position. This will generally be expected to lie inside this item's FormatRect. With it, this item can provide help on specific areas of an item. Outputs: On exit, if the return value is TRUE, the string pointed at by Result will contain a status line help string for this item Returns: TRUE if it filled in the string, FALSE if it did not Purpose: Called by the parent gallery when status line help is needed. The parent gallery will do a hit test to determine which node contains the pointer, and will then ask that node to supply bubble/status-line help. Notes: The base class returns FALSE (i.e. provides no help) If you can provide help, then override the base class method to do so. SeeAlso: SGDisplayNode::GetBubbleHelp ********************************************************************************************/ BOOL SGLibGroup::GetStatusLineHelp(DocCoord *MousePos, String_256 *Result) { ERROR3IF(MousePos == NULL || Result == NULL, "Invalid NULL params"); if(MousePos->x <= GROUP_BAR_ICON_WIDTH) { if(Flags.Folded) /* "Click to open this section of the gallery"; */ Result->MakeMsg(_R(IDS_LIBRARY_FOLDER_CLICK_TO_OPEN)); else /* "Click to close this section of the gallery"; */ Result->MakeMsg(_R(IDS_LIBRARY_FOLDER_CLICK_TO_CLOSE)); } else { if(Flags.Selected) { /* "Ctrl-Click to deselect" */ Result->MakeMsg(_R(IDS_LIBRARY_SECTION_CLICK_SELECTED)); *Result += String_8(_R(IDS_SGFONTS_STATUS_LINE_SEP)); // "; " } else if(Flags.CanSelect) { /* "Click to select" */ Result->MakeMsg(_R(IDS_LIBRARY_SECTION_CLICK_DESELECTED)); *Result += String_8(_R(IDS_SGFONTS_STATUS_LINE_SEP)); // "; " } String_256 DClick; if(Flags.Folded) /* "Double click to open this section of the gallery"; */ DClick.MakeMsg(_R(IDS_LIBRARY_SECTION_DCLICK_TO_OPEN)); else /* "Double click to close this section of the gallery"; */ DClick.MakeMsg(_R(IDS_LIBRARY_SECTION_DCLICK_TO_CLOSE)); *Result += DClick; } return(TRUE); } /******************************************************************************************** > virtual BOOL SGLibGroup::CanVirtualise(void); Author: Richard_Millican (Xara Group Ltd) Created: 4/1/95 Returns: TRUE if it can Purpose: Some groups shouldn't virtualise out to disk (the installed font group for example). Such groups should override this and return FALSE. ********************************************************************************************/ BOOL SGLibGroup::CanVirtualise(void) { return SGLibGroup::LibraryVirtualisingEnabled; } /******************************************************************************************** > virtual BOOL SGLibGroup::DeVirtualise(void); Author: Richard_Millican (Xara Group Ltd) Created: 4/1/95 Returns: TRUE if it devirtualised back in OK Purpose: Virtualise a group back into memory. ********************************************************************************************/ BOOL SGLibGroup::DeVirtualise(void) { if(!IsVirtualised()) return TRUE; // On older machines this can take a couple of seconds, so we need some feedback... Progress ProgMsg(_R(IDS_GALLERY_PREPARE_FOR_UNFOLD), -1/*, FALSE*/); ParentLibrary->ProgressBar = &ProgMsg; // ::Init will call update if this is non-null INT32 Count = ParentLibrary->CreateItems(); #ifdef _DEBUG ForceRedrawOfMyselfAndChildren(); #endif ParentLibrary->ProgressBar = NULL; return (Count > 0); } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::ShouldDownloadThumb() Author: Adrian_Stoicar (Xara Group Ltd) Created: 6/02/97 Inputs: - Outputs: - Returns: TRUE if we should download the thumbnail for this item, false otherwise Purpose: Used to decide whether or not to (re)start a thumbnail download ***********************************************************************************************/ BOOL SGLibDisplayItem::ShouldDownloadThumb() { Library* pLibrary = GetParentLibrary(); ERROR2IF(!pLibrary, FALSE, "Illegal NULL pointer"); // Check if we belong to a web folder String_256 thumbPath; if (pLibrary->IsWebLibrary()) { GetThumbFileName(&thumbPath); return (_access((TCHAR*) thumbPath, 0) == -1 && !IsDownloadingThumb() && (!((LibraryGallery*) GetParentGallery())->IsThumbDownloadingSuspended()) && !OpThumbDownload::GetLastError(this)); } else { return FALSE; } } /*********************************************************************************************** > virtual BOOL SGLibDisplayItem::DownloadThumbnail() Author: Adrian_Stoicar (Xara Group Ltd) Created: 6/02/97 Inputs: - Outputs: - Returns: TRUE the download was started succesfully, false otherwise Purpose: Starts to download the item's thumbnail ***********************************************************************************************/ BOOL SGLibDisplayItem::DownloadThumbnail() { nPercentageDownloaded = 0; OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpThumbDownload)); if (pOpDesc != NULL) { ThumbDownloadParam* Param = new ThumbDownloadParam; ERROR3IF(!Param, "Memory allocation error"); Param->pItem = this; Param->type = GetParentLibrary()->GetType(); // Invoke the operation pOpDesc->Invoke((OpParam*) Param); if (Param->bSuccess) { pDownloadOp = Param->pOp; bIsDownloadingThumb = TRUE; return TRUE; } } return FALSE; } /*********************************************************************************************** > virtual void SGLibDisplayItem::OnThumbDownloadComplete() Author: Adrian_Stoicar (Xara Group Ltd) Created: 6/02/97 Inputs: - Outputs: - Returns: - Purpose: Should be called when the thumbnail download is over - it will force a redraw among other things ***********************************************************************************************/ void SGLibDisplayItem::OnThumbDownloadComplete() { bIsDownloadingThumb = FALSE; ForceRedrawOfMyself(); GetParentGallery()->PaintListNow(); pDownloadOp = NULL; } /*********************************************************************************************** > virtual void SGLibDisplayItem::OnThumbDownloadProgress(const INT32 nPercentageCompleted) Author: Adrian_Stoicar (Xara Group Ltd) Created: 6/02/97 Inputs: - Outputs: - Returns: - Purpose: Called on thumbnail download progress - it will update the thumbnail's placeholder. NB: the background is not erased to prevent flickering ***********************************************************************************************/ void SGLibDisplayItem::OnThumbDownloadProgress(const INT32 nPercentageCompleted) { nPercentageDownloaded = nPercentageCompleted; ForceRedrawOfMyself(FALSE); GetParentGallery()->PaintListNow(); } /*********************************************************************************************** > virtual void SGLibDisplayItem::DrawPlaceholder(RenderRegion *Renderer, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) Author: Adrian_Stoicar (Xara Group Ltd) Created: 128/4/97 Inputs: Renderer - Pointer to RenderRegion in which to plot the bitmap rect MiscInfo - Miscellaneous info as passed to the redraw handler by the sgallery code Rectangle - Pointer to a DocRect the size and position of where the bitmap would be positioned normally Background - If true, draw a background redrawing, not plotted proper thumbnail rectangle Outputs: Returns: Purpose: Draws a thumbnail placeholder if the actual thumbnail is not available. If the thumb is downloading, it displays the percentage downloaded so far Notes: If the OS is not Windows this function will simply call DrawNullBitmapRect SeeAlso: SGLibDisplayItem::HandleRedraw ***********************************************************************************************/ void SGLibDisplayItem::DrawPlaceholder(RenderRegion *Renderer, SGMiscInfo *MiscInfo, DocRect *Rectangle, BOOL Background) { if (Renderer == NULL || MiscInfo == NULL || Rectangle == NULL) { ERROR3("Illegal NULL pointer"); return; } #ifdef _WIN32 if (Background) { DocColour NullBitmapColour(230L, 230L, 230L); Renderer->SetFillColour(NullBitmapColour); GridLockRect(MiscInfo, Rectangle); Renderer->DrawRect(Rectangle); INT32 OnePixel = MiscInfo->PixelSize; Renderer->SetLineWidth(0); Renderer->SetLineColour(DocColour(COLOUR_TRANS)); Renderer->SetFillColour(DocColour(COLOUR_BLACK)); DocRect TempRect(*Rectangle); // Left TempRect.hi.x = TempRect.lo.x + OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Top TempRect.lo.y = TempRect.hi.y - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Right TempRect.lo.x = TempRect.hi.x - OnePixel; Renderer->DrawRect(&TempRect); TempRect = *Rectangle; // Bottom TempRect.hi.y = TempRect.lo.y + OnePixel; Renderer->DrawRect(&TempRect); if (IsDownloadingThumb()) { String_32 strLabel(GetStringField(0, _R(IDS_LOADINGTHUMB))); DocRect rcText; Renderer->DrawFixedSystemText(&strLabel, rcText, FORMAT_NOPREFIX | FORMAT_CALCRECT | FORMAT_SINGLELINE | FORMAT_CENTER | FORMAT_VCENTER); if (rcText.Width() >= Rectangle->Width()) // we have to draw multiline { camSprintf((TCHAR*) strLabel, _T("%s%d%%"), (TCHAR*) (String_256) GetStringField(1, _R(IDS_LOADINGTHUMB)), nPercentageDownloaded); // DrawFixedSystemText can't center multiline text, so we'll have to adjust the rect Renderer->DrawFixedSystemText(&strLabel, rcText, FORMAT_NOPREFIX | FORMAT_CALCRECT); DocRect rcAdjusted = *Rectangle; rcAdjusted.hi.y -= ((rcAdjusted.hi.y - rcAdjusted.lo.y) - (rcText.hi.y - rcText.lo.y))/2; Renderer->DrawFixedSystemText(&strLabel, rcAdjusted, FORMAT_NOPREFIX | FORMAT_CENTER); } else { camSprintf((TCHAR*) strLabel, _T("%s%d%%"), (TCHAR*) (String_256) GetStringField(2, _R(IDS_LOADINGTHUMB)), nPercentageDownloaded); Renderer->DrawFixedSystemText(&strLabel, *Rectangle, FORMAT_NOPREFIX | FORMAT_SINGLELINE | FORMAT_CENTER | FORMAT_VCENTER); } } } else { DrawNullBitmapRect(Renderer, MiscInfo, Rectangle, Background); } #else DrawNullBitmapRect(Renderer, MiscInfo, Rectangle, Background); #endif } /******************************************************************************************** > BOOL SGLibDisplayItem::GetThumbFileName(PathName *Result) (WEBSTER) Author: Adrian_Stoicar (Xara Group Ltd) Created: 11/12/96 Outputs: Result - will be filled in with the full filename of the object's thumb file Returns: FALSE if it failed, else TRUE Purpose: To find the corresponding filename for this object's thumb ********************************************************************************************/ BOOL SGLibDisplayItem::GetThumbFileName(String_256* path) { PathName filePath; GetFileName(&filePath); Library* pLibrary = GetParentLibrary(); if (!pLibrary) { ERROR3("Ilegal NULL pointer!"); return FALSE; } if (!pLibrary->IsWebLibrary()) { ERROR3("This function should only be called for web folders"); return FALSE; } PathName indexPath(*(pLibrary->ReturnIndexLocation())); String_256 thumbPath(indexPath.GetLocation()); thumbPath += filePath.GetFileName(FALSE); thumbPath += _T(".png"); // thumbnails for web files will always be PNGs *path = thumbPath; return TRUE; }