// $Id: sgline.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============================ */ // sgline.cpp - Line SuperGallery classes - LineGallery and the LineAttrItem base class. /* */ #include "camtypes.h" // global types //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "range.h" // selection & attributes - in camtypes.h [AUTOMATICALLY REMOVED] #include "qualattr.h" //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "ccdc.h" // render-into-dialogue support //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "grnddib.h" //#include "galres.h" // super-gallery support //#include "galstr.h" #include "sginit.h" #include "sgline.h" #include "sgline2.h" #include "sgmenu.h" #include "sglinepr.h" #include "sgldrag.h" // dragging support #include "dragmgr.h" #include "lattrops.h" // gadgets and resources //#include "justin.h" //#include "mario.h" // for _R(IDE_NOMORE_MEMORY) //#include "richard2.h" // for yet more strings #ifdef VECTOR_STROKING #include "sgstroke.h" // Stroke attribute items #include "strkattr.h" // Stroke attributes #include "ppstroke.h" // PathProcessorStroke #include "ppairbsh.h" // PathProcessorStrokeAirbrush #include "ppvecstr.h" // PathProcessorStrokeVector #include "valfunc.h" // ValueFunctions #endif #include "helpuser.h" //#include "xshelpid.h" //#include "helppath.h" #include "brshcomp.h" // for the new style brushes #include "ppbrush.h" #include "brshattr.h" #include "sgbrush.h" #include "lineattr.h" //#include "rik.h" #include "brushmsg.h" #include "brshname.h" //#include "resdll.h" #include "fileutil.h" #include "brushop.h" //#include "freehres.h" //_R(IDS_FEATURENOTIMPLEMENTED) //#include "resource.h" //_R(IDS_OK) //#include "linegal.h" // Version control. DECLARE_SOURCE("$Revision: 1282 $"); // Implement the dynamic class bits... CC_IMPLEMENT_DYNCREATE(LineGallery, SuperGallery) CC_IMPLEMENT_DYNAMIC(LineAttrItem, SGDisplayItem) CC_IMPLEMENT_DYNCREATE(OpDisplayLineGallery, Operation); // This line mustn't go before any CC_IMPLEMENT_... macros #define new CAM_DEBUG_NEW // This always points to the line gallery, or NULL if it doesn't exist. LineGallery* LineGallery::m_pTheGallery = NULL; // These are the default scaling factors for the four stock sizes of arrowheads. double LineGallery::m_anArrowScales[4] = { 3.0, 8.0, 13.0, 18.0 }; // initialise the array that holds the filenames of the default brush files String_256* LineGallery::m_pFileNameArray = NULL; UINT32 LineGallery::m_NumDefaultFiles = 0; /******************************************************************************************** > LineAttrItem::LineAttrItem(const String& strDescription, LineAttritem::TextPosition eTextPos) Author: Justin_Flude (Xara Group Ltd) Created: 27/3/95 Inputs: strDescription text description of this item, eg "0.5 pt" eTextPos the default position for this item's text description Outputs: - Returns: - Purpose: Default constructor for a LineAttrItem. Errors: - SeeAlso: SGDisplayItem::SGDisplayItem ********************************************************************************************/ LineAttrItem::LineAttrItem(const String& strDescription, LineAttrItem::TextPosition eTextPos) : m_strDescription(strDescription), m_eDefaultTextPosition(eTextPos), m_fIsCurrentAttrib(FALSE) { // Empty. } /******************************************************************************************** > static BOOL LineAttrItem::UpdateCurrentAttribStatus() Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: TRUE if no problems encountered, eg. out of memory. Purpose: Updates the "current attribute" status flag of every LineAttrItem within the line gallery, setting it to whether each item represents an attribute value applying to the current selection. Errors: Out of memory. SeeAlso: LineAttrItem::GetRuntimeClass; LineAttrItem::IsEqualValue ********************************************************************************************/ BOOL LineAttrItem::UpdateCurrentAttribStatus() { // If the line gallery isn't running then we don't bother. if (!LineGallery::IsActive()) return TRUE; // For each group in the line gallery, try to match the current attribute of the // selection with the group's items. SGDisplayRoot* pRoot = LineGallery::GetInstance()->GetDisplayTree(); if (pRoot == NULL) return FALSE; for (LineAttrGroup* pGroup = (LineAttrGroup*) pRoot->GetChild(); pGroup != NULL; pGroup = (LineAttrGroup*) pGroup->GetNext()) { // Get a pointer to the first item within the group, if any. LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); if (pItem == NULL) continue; // Get a pointer to the null-terminated array of pointers to run-time classes that // this type of item can represent. CCRuntimeClass** ppAttribClasses = pItem->GetAttribRuntimeClasses(); ERROR3IF(ppAttribClasses == NULL, "No attribute run-time classes in LineAttrItem::UpdateCurrentAttribStatus"); // Count how many types of classes the item represents. Note the null statement. CCRuntimeClass** pprtc; for (pprtc = ppAttribClasses; *pprtc != NULL; pprtc++); INT32 nAttribClasses = pprtc - ppAttribClasses; // Allocate an array of NodeAttribute pointers for each run-time class. typedef NodeAttribute* PATTRIBUTE; NodeAttribute** ppCommonAttribs = new PATTRIBUTE[nAttribClasses]; ERRORIF(ppCommonAttribs == NULL, _R(IDE_NOMORE_MEMORY), FALSE); // For each run-time class that appears in *ppAttribClasses, try to find an // attribute of the same class that currently applies to the selection. for (INT32 i = 0; i < nAttribClasses; i++) { NodeAttribute* pattr = NULL; // sjk SelRange::CommonAttribResult eResult; eResult = GetApplication()-> FindSelection()-> FindCommonAttribute(ppAttribClasses[i], &pattr); // See if we found either a common attribute or the "default attribute". if (pattr != NULL) { // Check for nothing really brain-damaged happening. ERROR3IF(pattr->GetRuntimeClass() != ppAttribClasses[i], "Wrong kind of attribute in LineAttrItem::" "UpdateCurrentAttribStatus"); // There is just one attribute applying, and we got it. ppCommonAttribs[i] = pattr; } else { // There are either many or none applying, so we aren't interested. ppCommonAttribs[i] = NULL; } } // OK, so now we have an array of all the attributes this type of item is // interested in. Ask each item within the group to compare itself against // each attribute we have found, to see if it represents it or not. for (; pItem != NULL; pItem = (LineAttrItem*) pItem->GetNext()) { BOOL fOldState = pItem->m_fIsCurrentAttrib; pItem->m_fIsCurrentAttrib = pItem->IsEqualValueToAny(ppCommonAttribs); if (pItem->m_fIsCurrentAttrib != fOldState) pItem->ForceRedrawOfMyself(); } // All done, we are finished with these kinds of attributes. delete[] ppCommonAttribs; } // Everything went OK. return TRUE; } /*********************************************************************************************** > virtual void LineAttrItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Inputs: pFormatInfo - The formatting info from which to calculate my position/size pMiscInfo - As usual, the useful misc info struct Outputs: member variable FormatRect - is returned filled in with the size/position of this LineAttrItem 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 LineAttrItem items to calculate where they will appear in the grand scheme of things Notes: LineAttrItems supply only one display mode ("full info") Scope: private (for use of LineAttrItem class only) ***********************************************************************************************/ void LineAttrItem::CalculateMyRect(SGFormatInfo* pFormatInfo, SGMiscInfo* pMiscInfo) { // Find out the extent of this item, including a gap for formatting. MILLIPOINT xSize, ySize; GetSize(m_eDefaultTextPosition, &xSize, &ySize); if (xSize != SG_InfiniteWidth) xSize += GetHorzGap(); ySize += GetVertGap(); // Let the base class do what it needs to do with this. CalculateFormatRect(pFormatInfo, pMiscInfo, xSize, ySize); } /******************************************************************************************** > void LineAttrItem::GetSize(LineAttrItem::TextPosition eTextPos, MILLIPOINT* pxSize, MILLIPOINT* pySize) const Author: Justin_Flude (Xara Group Ltd) Created: 19/4/95 Inputs: eTextPos where this item's text description should go Outputs: pxSize where to store the width of the item pySize where to store the height of the item Returns: - Purpose: Used to calculate how large this item is, in millipoints. Errors: - SeeAlso: LineAttrItem::CalculateMyRect ********************************************************************************************/ void LineAttrItem::GetSize(LineAttrItem::TextPosition eTextPos, MILLIPOINT* pxSize, MILLIPOINT* pySize) const { // Make sure we can put the results somewhere. ERROR3IF(pxSize == NULL || pySize == NULL, "Null* passed in LineAttrItem::GetSize"); // Get the basic size and add in a possible text size as well. *pxSize = GetWidth(); *pySize = GetHeight(); switch (eTextPos) { case LEFT: if (*pxSize != SG_InfiniteWidth) { *pxSize += (c_nHorzSizeOfText + c_nHorzGapAfterText); } break; case BELOW: *pySize += (c_nVertSizeOfText + c_nVertGapAboveText); break; case NO_LABEL: break; default: ERROR3("Unexpected case in LineAttrItem::GetSize"); break; } } /*********************************************************************************************** > virtual void LineAttrItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGFormatInfo* pFormatInfo) Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Inputs: pRedrawInfo - The information on the kernel-rendered redraw area pFormatInfo - The formatting information structure Member variable FormatRect should be set up (before calling this method) to be the rectangle in which to draw this item Purpose: LineAttrItem item redraw method - removed from the main HandleEvent method merely to make the code tidier. Justin here: this version sets default attributes within the render region, such as foreground & background colour, and then calls the Render() function to do the actual drawing. Notes: VERY IMPORTANT: The rendering must be enclosed by calls to StartRendering and StopRendering, to ensure that rendering works properly (in the future we may change the redraw system to use a GRenderRegion for each individual item, rather than one global one for the window, for which these calls will be essential) Scope: protected ***********************************************************************************************/ void LineAttrItem::HandleRedraw(SGRedrawInfo* pRedrawInfo, SGMiscInfo* pMiscInfo) { // Remove the gap between the items, shrink by one pixel to ensure clean clipping, // and fix the bounds coincide with the position of pixels. DocRect drBounds(FormatRect); drBounds.Inflate(-(pMiscInfo->PixelSize + GetHorzGap() / 2), -(pMiscInfo->PixelSize + GetVertGap() / 2)); GridLockRect(pMiscInfo, &drBounds); // Set the foreground and background colours according to whether this item is // selected or not. DocColour dcolForegnd, dcolBackgnd; if (Flags.Selected) { dcolForegnd = pRedrawInfo->SelForeground; dcolBackgnd = pRedrawInfo->SelBackground; } else { dcolForegnd = pRedrawInfo->Foreground; dcolBackgnd = pRedrawInfo->Background; } // Set the attributes for drawing the formatted rectangle. RenderRegion* pRegion = pRedrawInfo->Renderer; pRegion->SetLineWidth(pMiscInfo->PixelSize); // line is one pixel wide pRegion->SetFillColour(dcolBackgnd); // If we are drawing an item that is a "current attribute" then we want to draw it // with a "selected" line around it. Otherwise we draw it with effectively no line. if (m_fIsCurrentAttrib) { pRegion->SetLineColour(pRedrawInfo->SelBackground); } else { // Draw the line the same colour as the fill colour, so it's "invisible". pRegion->SetLineColour(dcolBackgnd); } // Create a closed path that is filled with the fill colour and if necessary has // a visible outline. Path pth; pth.Initialise(); pth.IsFilled = TRUE; pth.IsStroked = m_fIsCurrentAttrib; // draw outline if "current attribute" // "Draw" the bounding rectangle into the path. pth.InsertMoveTo(drBounds.lo); pth.InsertLineTo(DocCoord(drBounds.lo.x, drBounds.hi.y)); pth.InsertLineTo(drBounds.hi); pth.InsertLineTo(DocCoord(drBounds.hi.x, drBounds.lo.y)); pth.InsertLineTo(drBounds.lo); pth.CloseSubPath(); // Draw the path. pRegion->DrawPath(&pth); // Reset the rendering attributes back to the normal: standard gallery foreground // and background colours. pRegion->SetLineColour(dcolForegnd); pRegion->SetFixedSystemTextColours(&dcolForegnd, &dcolBackgnd); // Shrink the rectangle by a pixel, to make sure it nicely fits within the bounds, // lock down, and let the derived class do the rest of the work as it pleases. drBounds.Inflate(-pMiscInfo->PixelSize, -pMiscInfo->PixelSize); GridLockRect(pMiscInfo, &drBounds); Render(pRegion, drBounds, m_eDefaultTextPosition); } /******************************************************************************************** > void LineAttrItem::Render(RenderRegion* pRegion, const DocRect& drBounds, LineAttrItem::TextPosition eTextPos) const Author: Justin_Flude (Xara Group Ltd) Created: 27/3/95 Inputs: pRegion pointer to the RenderRegion to render into drBounds the bounding box to render within eTextPos whether and where to put the text description Outputs: - Returns: - Purpose: Called by the HandleRedraw function. Can be overridden by derived classes. This base class version draws the text describing this item within the text bounding box, and a line within the line bounding box. Errors: - SeeAlso: LineAttrItem::HandleRedraw ********************************************************************************************/ void LineAttrItem::Render(RenderRegion* pRegion, const DocRect& drBounds, LineAttrItem::TextPosition eTextPos) const { // Make a copy of the given bounding box rectangle so that we can adjust it later // if we render some text within it. DocRect drLineBounds(drBounds); // Next, render the text description of this item, if necessary. if (eTextPos != NO_LABEL) { // We must adjust the bounding box of the line to account for the text rendered // into it. Items display their text on the left of the rendered attribute. DocRect drTextBounds(drLineBounds); switch (eTextPos) { case BELOW: { // Divide the bounds horizontally, text below. drTextBounds.hi.y = drTextBounds.lo.y + c_nVertSizeOfText; drLineBounds.lo.y = drTextBounds.hi.y + c_nVertGapAboveText; // Centre the text bounds. As there is no "GetTextExtent" function for // "system text" we have the obligatory bodge . . . // MILLIPOINT nTextLen = (GetDescription().Length() + 1) * c_nAveCharWidth; DocRect TextBounds; String_256 Desc = GetDescription(); pRegion->GetFixedSystemTextSize(&Desc, &TextBounds); MILLIPOINT nTextLen = TextBounds.Width() / 2; MILLIPOINT xMid = (drTextBounds.lo.x + drTextBounds.hi.x) / 2; drTextBounds.lo.x = xMid - nTextLen; drTextBounds.hi.x = xMid + nTextLen; break; } case LEFT: // Divide the bounds vertically, text to the left. drTextBounds.hi.x = drTextBounds.lo.x + c_nHorzSizeOfText; drLineBounds.lo.x = drTextBounds.hi.x + c_nHorzGapAfterText; break; default: ERROR3("Unexpected case in LineAttrItem::Render"); return; } // Draw the text description of this item. Note that the foreground and // background colours have already been set by the caller. pRegion->DrawFixedSystemText((String*) &GetDescription(), drTextBounds); } // Set the default line width for lines rendered within the gallery and let a // derived class set some specialised rendering attributes for its item. Then draw // the line, by default through the centre of the given bounding box. A derived // class may very occasionally need to override this as well (eg. to render join-types). pRegion->SaveContext(); pRegion->SetLineWidth(c_nDefaultLineWidth); SetAttributes(pRegion); DrawItem(pRegion, drLineBounds); pRegion->RestoreContext(); } /******************************************************************************************** > virtual void LineAttrItem::DrawItem(RenderRegion* pRegion, const DocRect& drBounds) const Author: Justin_Flude (Xara Group Ltd) Created: 29/3/95 Inputs: pRegion pointer to the RenderRegion to draw into drBounds reference to the bounding box rectangle to draw within Outputs: - Returns: - Purpose: Draws this item within the bouding box. This default implementation draws a single line through the centre of the box, fine for almost all derived classes. You can override this to do something else (cf. the join-types attribute item, that must draw two lines that meet). Errors: - SeeAlso: LineAttrItem::Render ********************************************************************************************/ void LineAttrItem::DrawItem(RenderRegion* pRegion, const DocRect& drBounds) const { // Calculate the mid-point of the vertical sides of the bounding box. INT32 yMid = (drBounds.lo.y + drBounds.hi.y) / 2; // Draw a line at this height from the left to the right edge. Path pthLinePath; if (pthLinePath.Initialise()) { pthLinePath.InsertMoveTo(DocCoord(drBounds.lo.x, yMid)); pthLinePath.InsertLineTo(DocCoord(drBounds.hi.x, yMid)); pthLinePath.IsFilled = FALSE; pthLinePath.IsStroked = TRUE; pRegion->DrawPath(&pthLinePath); } } /******************************************************************************************** > virtual MILLIPOINT LineAttrItem::GetWidth() const Author: Justin_Flude (Xara Group Ltd) Created: 19/4/95 Inputs: - Outputs: - Returns: The width of this item, in millipoints. Purpose: Called by the formatting code. Errors: - SeeAlso: LineAttrItem::GetSize; LineAttrItem::CalculateMyRect ********************************************************************************************/ MILLIPOINT LineAttrItem::GetWidth() const { return c_nHorzSizeOfItem; } /******************************************************************************************** > virtual MILLIPOINT LineAttrItem::GetHeight() const Author: Justin_Flude (Xara Group Ltd) Created: 19/4/95 Inputs: - Outputs: - Returns: The height of this item, in millipoints. Purpose: Called by the formatting code. Errors: - SeeAlso: LineAttrItem::GetSize; LineAttrItem::CalculateMyRect ********************************************************************************************/ MILLIPOINT LineAttrItem::GetHeight() const { return c_nVertSizeOfItem; } /******************************************************************************************** > virtual MILLIPOINT LineAttrItem::GetHorzGap() const Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: The horizontal gap between this item and another item of the same type, in millipoints. Purpose: Called by the formatting code. This base-class version returns a default value, derived classes may override it to make items closer or further apart. Errors: - SeeAlso: - ********************************************************************************************/ MILLIPOINT LineAttrItem::GetHorzGap() const { return c_nHorzGapBetweenItems; } /******************************************************************************************** > virtual MILLIPOINT LineAttrItem::GetVertGap() const Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: The vertical gap between this item and another item of the same type, in millipoints. Purpose: Called by the formatting code. This base-class version returns a default value, derived classes may override it to make items closer or further apart. Errors: - SeeAlso: - ********************************************************************************************/ MILLIPOINT LineAttrItem::GetVertGap() const { return c_nVertGapBetweenItems; } /*********************************************************************************************** > virtual BOOL LineAttrItem::HandleEvent(SGEventType EventType, void* EventInfo, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) 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 LineAttrItem::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: { // Rely on FormatRect being cached from above SGRedrawInfo* RedrawInfo = GetRedrawInfo(EventType, EventInfo); // only redraw if we intersect the clip rect if (IMustRedraw(RedrawInfo)) { // Now render the item. StartRendering(RedrawInfo, MiscInfo); RedrawInfo->Renderer->SaveContext(); HandleRedraw(RedrawInfo, MiscInfo); RedrawInfo->Renderer->RestoreContext(); StopRendering(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)) { //OK temporary dodge (see, not a bodge) to stop people doing things with brushes in the //line gallery before we get them working! // LineAttrItem* pItem = this; { // If the colour is in the selected document, then it is safe to // do a colour drag - for now, it will only allow drags for the // selected doc. // Otherwise, the normal click action takes place. // If the drag fails (turns into a click) then the normal click action // takes place, passed on by the GalleryColourDragInfo::OnClick handler // SGDisplayGroup *Parent = (SGDisplayGroup *) GetParent(); if (Mouse->DoubleClick) // || Parent->GetParentDocument() != Document::GetSelected()) DefaultClickHandler(Mouse, MiscInfo); else { DefaultPreDragHandler(Mouse, MiscInfo); GalleryLineDragInfo* pInfo; pInfo = new GalleryLineDragInfo(this, Mouse, MiscInfo, Mouse->MenuClick); if (pInfo != NULL) DragManagerOp::StartDrag(pInfo, GetListWindow()); } } return(TRUE); // Claim this event - nobody else can own this click } } break; default: // Pass unknown events on to the base class return(SGDisplayItem::HandleEvent(EventType, EventInfo, MiscInfo)); } // Default return value: We do not claim this event, so it will be passed on to others return FALSE; } /*********************************************************************************************** > virtual void LineAttrItem::DragWasReallyAClick(SGMouseInfo* pMouse, SGMiscInfo* pMiscInfo) Author: Will_Cowling (Xara Group Ltd) Created: 10/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 line attributes from the gallery will call this function back if the drag turns out to just be a click. SeeAlso: LineAttrItem::HandleEvent; GalleryLineDragInfo::OnClick ***********************************************************************************************/ void LineAttrItem::DragWasReallyAClick(SGMouseInfo* pMouse, SGMiscInfo* pMiscInfo) { // Just get default selection action to be applied for this click. DefaultClickHandler(pMouse, pMiscInfo); } /******************************************************************************************** > virtual BOOL LineAttrItem::DefaultClickHandler(SGMouseInfo* pMouse, SGMiscInfo* pMiscInfo) Author: Justin_Flude (Xara Group Ltd) Created: 7/4/95 Inputs: (see base-class implementation in SGDisplayItem) Outputs: - Returns: (see base-class implementation in SGDisplayItem) Purpose: Overrides the default behaviour when items in the line gallery are clicked on, so that it is possible to simple-click and select items in different groups without clearing the selection. Errors: - SeeAlso: SGDisplayItem::DefaultClickHandler ********************************************************************************************/ BOOL LineAttrItem::DefaultClickHandler(SGMouseInfo* pMouse, SGMiscInfo* pMiscInfo) { // Get some objects. SuperGallery* pParent = GetParentGallery(); SGDisplayGroup* pGroup = (SGDisplayGroup*) GetParent(); ERROR3IF(pGroup == NULL, "No parent group in LineAttrItem::DefaultClickHandler?"); // If there is any other item within the group already selected then // deselect it. We start searching from the first child of this group. for (LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); pItem != NULL; pItem = (LineAttrItem*) pItem->GetNext()) { if (pItem != this) pItem->SetSelected(FALSE); } // If Adjust, toggle my selection state // If Select, set myself selected, and ensure all other items deselected // NB. NOTE THAT "ADJUST" IS REALLY WHAT EVERY ONE ELSE CALLS "CONSTRAIN"!! // (Well, actually, it's what Windows uses for altering a selection... it's not my // fault that the rest of Camelot flies in the face of windows conventions... and // as galleries are really "super" windows list boxes, they have to use windows // conventions. Note also that pMouse->Adjust is not necessarily fixed to any key // but happens under Windows to be attached to ctrl or the right button) SetSelected((pMouse->Adjust && !pMouse->DoubleClick) ? !Flags.Selected : TRUE); // OK, now we have guaranteed that an item is selected on a double click we can run // an Apply action. if (pMouse->DoubleClick) { // Apply the attributes. if (pParent->ApplyAction(pMouse->Adjust ? SGACTION_APPLYADJUST : SGACTION_APPLY) && pMouse->Adjust) { // Adjust/Ctrl double click of an item. This applies the item and then // auto closes the gallery (just like RISC OS and Win95) // Auto-close only occurs, however, if the item says it's OK, as arrowheads // use the ctrl-double click to apply in a special way, so shouldn't autoclose. if (ShouldCloseOnDoubleClick()) { pParent->SetVisibility(FALSE); DialogBarOp::SetSystemStateChanged(); // Ensure toolbar button pops out again } } return TRUE; } // Update the pParent to know that we are the new multi-selection anchor // (The anchor only changes when single items are (de)selected) pParent->SetLastSelectedNode((Flags.Selected) ? this : NULL); // Finally, inform the parent gallery that the selection has changed, so it can // shade/unshade buttons as appropriate, etc pParent->SelectionHasChanged(); return TRUE; } /******************************************************************************************** > const String& LineAttrItem::GetDescription() const Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: A reference to a string that describes what this item represents. Purpose: Describes this item, basically. Errors: - SeeAlso: LineAttrItem::LineAttrItem ********************************************************************************************/ const String& LineAttrItem::GetDescription() const { return m_strDescription; } /******************************************************************************************** > void LineAttrItem::SetDescription(StringBase *pNewDescription) Author: Richard_Millican (Xara Group Ltd) Created: 06/03/97 Inputs: pNewDescription - New description of the item Purpose: Changes the item's text in the gallery ********************************************************************************************/ void LineAttrItem::SetDescription(StringBase *pNewDescription) { if(pNewDescription != NULL) { m_strDescription = *pNewDescription; } } /******************************************************************************************** > void LineAttrItem::SetTextPosition(LineAttrItem::TextPosition eNewTextPos) Author: Justin_Flude (Xara Group Ltd) Created: 29/3/95 Inputs: eNewTextPos the new position of the text description Outputs: - Returns: - Purpose: Tells SGDisplayLineAttrItems whether to display themselves with a label describing themselves, or not. Errors: - SeeAlso: - ********************************************************************************************/ void LineAttrItem::SetTextPosition(LineAttrItem::TextPosition eNewTextPos) { m_eDefaultTextPosition = eNewTextPos; } /******************************************************************************************** > virtual BOOL LineAttrItem::GetStatusLineHelp(DocCoord* pMousePos, String_256* pResult) Author: Justin_Flude (Xara Group Ltd) Created: 13/6/95 Inputs: dcMousePos (not used) Outputs: pResult where to put the text Returns: TRUE Purpose: Sets the given string to the text description of this line item. ********************************************************************************************/ BOOL LineAttrItem::GetStatusLineHelp(DocCoord*, String_256* pResult) { // Check for rubbish. ERROR3IF(pResult == NULL, "Null String_256* passed to LineAttrItem::GetStatusLineHelp"); // Build up the status-line text. This is composed of the item's text description, // followed by the text of the item's group title, without the last pluralising 's'. String_256 str; if (IsSelected()) str = String_256(_R(IDS_LINEGAL_SEL_CTRLCLICK)); else str = String_256(_R(IDS_LINEGAL_SEL_CLICK)); str += GetDescription(); str += String_8(_R(IDS_SGLINE_STAT_SPACE_SEP)); // " " str += ((LineAttrGroup*) GetParent())->GetTitle(); str.Left(pResult, str.Length() - 1); String_256 strAttr(_R(IDS_LINEGAL_ATTR)); *pResult += strAttr; // if (IsSelected()) // removing this test fixes bug #4684 (hee hee!!) { String_256 strDbl(_R(IDS_LINEGAL_SEL_DBLCLK)); *pResult += strDbl; } // Success! return TRUE; } /******************************************************************************************** > virtual BOOL LineAttrItem::ShouldCloseOnDoubleClick(void) Author: Jason_Williams (Xara Group Ltd) Created: 12/12/95 Returns: TRUE Purpose: When an item is ctrl-double-clicked, the default action is to apply the item and close the gallery (for convenience). However, arrowheads do a special action for ctrl-double-click (they apply to the other end of the line) so they do not want auto-close to occur. This function returns TRUE (auto-close) by default, and is overridden to return FALSE by derived classes which wish to stop the auto-close action. SeeAlso: LineArrowItem::ShouldCloseOnDoubleClick ********************************************************************************************/ BOOL LineAttrItem::ShouldCloseOnDoubleClick(void) { return(TRUE); } /******************************************************************************************** > virtual void LineAttrItem::ItemSelected() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 20/1/2000 Inputs: pNewAttr - the attribute that we are about to apply Outputs: - Returns: TRUE if we want the line gallery to go ahead and apply the attribute, FALSE if we applied it ourselves. Purpose: utility fn called when the item is selected. If your item needs to do anything just prior to it becoming selected then override this function. Errors: - SeeAlso: BrushAttrItem::ItemSelected ********************************************************************************************/ BOOL LineAttrItem::ItemSelected(NodeAttribute* pNewAttr) { return TRUE; } /******************************************************************************************** > LineAttrGroup::LineAttrGroup(const String_64& strTitle, SuperGallery* pGal) Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: strTitle the title string to display within the group heading pGal pointer to the owning super-gallery object Outputs: - Returns: - Purpose: Contructs a LineAttrGroup, representing a section heading within the line-attributes super-gallery. Errors: - SeeAlso: SGDisplayGroup::SGDisplayGroup ********************************************************************************************/ LineAttrGroup::LineAttrGroup(const String_64& strTitle, SuperGallery* pGal) : SGDisplayGroup(pGal, NULL, NULL) { // Set the title (in the base class). TitleText = strTitle; } /******************************************************************************************** > const String_64& LineAttrGroup::GetTitle() const Author: Justin_Flude (Xara Group Ltd) Created: 13/6/95 Returns: A reference to the string containing this group's title. Purpose: Gets this group's title (the text displayed next to the folder icon). SeeAlso: LineAttrItem::GetStatusLineHelp ********************************************************************************************/ const String_64& LineAttrGroup::GetTitle() const { return TitleText; } /******************************************************************************************** > static BOOL LineGallery::Init() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if gallery initialisation is successful. Purpose: Called when the program starts, loading .INI file settings. Errors: - SeeAlso: - ********************************************************************************************/ BOOL LineGallery::Init() { return Camelot.DeclareSection(TEXT("Displays"), 20) && Camelot.DeclarePref(TEXT("Displays"), TEXT("ArrowScale1"), &m_anArrowScales[0], 0.1, 50.0) && Camelot.DeclarePref(TEXT("Displays"), TEXT("ArrowScale2"), &m_anArrowScales[1], 0.1, 50.0) && Camelot.DeclarePref(TEXT("Displays"), TEXT("ArrowScale3"), &m_anArrowScales[2], 0.1, 50.0) && Camelot.DeclarePref(TEXT("Displays"), TEXT("ArrowScale4"), &m_anArrowScales[3], 0.1, 50.0) && PrepareBrushFolders(); } /******************************************************************************************** > static LineGallery* LineGallery::GetInstance() Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: A pointer to the program's line gallery if it exists, or NULL. Purpose: Public access function to the line gallery. Errors: - SeeAlso: - ********************************************************************************************/ LineGallery* LineGallery::GetInstance() { return m_pTheGallery; } /******************************************************************************************** > static BOOL LineGallery::IsActive() Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: TRUE if the line gallery is currently visible on-screen, FALSE otherwise. Purpose: Used by the message-handlers of gadgets within the line gallery to determine if they should update themselves or not. Errors: - SeeAlso: - ********************************************************************************************/ BOOL LineGallery::IsActive() { return m_pTheGallery != NULL && m_pTheGallery->IsVisible(); } /******************************************************************************************** > LineGallery::LineGallery() Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Purpose: LineGallery default constructor. Sets a global instance pointer to this object. ********************************************************************************************/ LineGallery::LineGallery() { // Remember a pointer to the global instance of this gallery. ERROR3IF(m_pTheGallery != NULL, "Gallery already exists in LineGallery::LineGallery?"); m_pTheGallery = this; DlgResID=_R(IDD_LINESGALLERY); // set to the normal default m_PreviousLineWidth = 500; } /******************************************************************************************** > virtual LineGallery::~LineGallery() Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: - Purpose: Destroys a line gallery, resetting the global instance pointer to NULL. Errors: - SeeAlso: - ********************************************************************************************/ LineGallery::~LineGallery() { // Make sure nothing is seriously screwed-up. ERROR3IF(m_pTheGallery == NULL, "No gallery in LineGallery::~LineGallery?"); m_pTheGallery = NULL; // delete the string array if (m_pFileNameArray != NULL) { for (UINT32 i = 0; i < m_NumDefaultFiles; i++) m_pFileNameArray[i].Empty(); // don't forget that we allocated it with malloc.. free((void*)m_pFileNameArray); m_pFileNameArray = NULL; } } /******************************************************************************************** > virtual BOOL LineGallery::PreCreate() Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Returns: TRUE if the Gallery initialised successfully FALSE if it should not be opened due to a failure to initialise Purpose: The LineGallery PreCreate handler. This overrides the base class PreCreate function. It is called at the very beginning of the SuperGallery::Create method, before the window has been created. ********************************************************************************************/ BOOL LineGallery::PreCreate() { // If there isn't already one, create a DisplayTree if (DisplayTree != NULL) return TRUE; // New root node, with a scrollbar. DisplayTree = new SGDisplayRootScroll(this); ERRORIF(DisplayTree == NULL, _R(IDE_NOMORE_MEMORY), FALSE); // Try to create a title sub-tree for each kind of line attribute. BOOL ok = CreateBrushGroups() && #ifdef VECTOR_STROKING //CreateStrokeTypeGroup() && CreateVarWidthGroup() && #endif // VECTOR_STROKING // CreateWidthGroup() && CreateDashGroup() && CreateArrowGroup(); // CreateCapGroup() && // CreateJoinTypeGroup(); return ok; } /******************************************************************************************** > virtual BOOL LineGallery::PostCreate() Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: - Outputs: - Returns: Whatever the base class SuperGallery returns for this function. Purpose: Called after the LineGallery is created. Forces an update of the "current attribute" status of all items. Errors: - SeeAlso: LineAttrItem::UpdateCurrentAttribStatus ********************************************************************************************/ BOOL LineGallery::PostCreate() { // Prime the current attribute status flags of each item. return SuperGallery::PostCreate() && LineAttrItem::UpdateCurrentAttribStatus(); } /******************************************************************************************** > LineAttrGroup* LineGallery::CreateGroup(const String_256& strTitle, BOOL fOpen) Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: strTitle the title (heading) of the group to create fOpen whether the group "folder" is initially "open" Outputs: - Returns: A pointer to the newly created group, or NULL if it can't be created. Purpose: Creates a new group (heading) within the line-attributes super-gallery. Errors: - SeeAlso: LineAttrGroup::LineAttrGroup ********************************************************************************************/ LineAttrGroup* LineGallery::CreateGroup(const String_256& strTitle, BOOL fOpen) { // Make sure the tree has been initialised. ERROR3IF(DisplayTree == NULL, "Root node not allocated in LineGallery::CreateGroup"); // Try to create and set a new group. LineAttrGroup* pGroup = new LineAttrGroup(strTitle, this); if (pGroup != NULL) { // NB. note that the "folded" flag is inverted. // pGroup->Flags.Folded = (fOpen) ? FALSE : TRUE; pGroup->Flags.Folded = true; pGroup->Flags.Invisible = false; pGroup->Flags.CanSelect = true; DisplayTree->AddItem(pGroup); } // Return a pointer to the new group. return pGroup; } /******************************************************************************************** > BOOL LineGallery::CreateItem(LineAttrGroup* pGroup, LineAttrItem* pItem) Author: Justin_Flude (Xara Group Ltd) Created: 29/3/95 Inputs: pGroup pointer to the group to add the item to pItem pointer to the item to add to the group Outputs: - Returns: TRUE if the item is successfully added, FALSE if either pGroup or pItem is a null pointer. Purpose: Helper function to add items to a line-attribute grouping. Errors: - SeeAlso: LineGallery::CreateGroup ********************************************************************************************/ BOOL LineGallery::CreateItem(LineAttrGroup* pGroup, LineAttrItem* pItem) { // If we were passed a genuine item insert it into the group. if (pGroup != NULL && pItem != NULL) { // Success. pGroup->AddItem(pItem); return TRUE; } // You failed to allocate your item or group! return FALSE; } /******************************************************************************************** > BOOL LineGallery::CreateWidthGroup() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if successful. Purpose: Creates a new "line width" Group with its associated items. Errors: - SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem; LineWidthItem::LineWidthItem ********************************************************************************************/ BOOL LineGallery::CreateWidthGroup() { // Create the group (heading). LineAttrGroup* pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_CREATELINE)), TRUE); if (pGroup != NULL) pGroup->Flags.Folded = TRUE; // Create each item. return CreateItem(pGroup, new LineWidthItem(0.25, String_64(_R(IDS_LINEGAL_025PT)))) && CreateItem(pGroup, new LineWidthItem(0.5, String_64(_R(IDS_LINEGAL_05PT)))) && CreateItem(pGroup, new LineWidthItem(1.0, String_64(_R(IDS_LINEGAL_1PT)))) && CreateItem(pGroup, new LineWidthItem(2.0, String_64(_R(IDS_LINEGAL_2PT)))) && CreateItem(pGroup, new LineWidthItem(4.0, String_64(_R(IDS_LINEGAL_4PT)))) && CreateItem(pGroup, new LineWidthItem(8.0, String_64(_R(IDS_LINEGAL_8PT)))) && CreateItem(pGroup, new LineWidthItem(12.0, String_64(_R(IDS_LINEGAL_12PT)))) && CreateItem(pGroup, new LineWidthItem(16.0, String_64(_R(IDS_LINEGAL_16PT)))); } /******************************************************************************************** > BOOL LineGallery::CreateDashGroup() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if successful. Purpose: Creates a new "dash pattern" Group with all its associated items. Errors: - SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem; LineDashItem::LineDashItem ********************************************************************************************/ BOOL LineGallery::CreateDashGroup() { // Create the group (heading). LineAttrGroup* pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_CREATEDASH)), TRUE); if (pGroup != NULL) pGroup->Flags.Folded = TRUE; // Create each item. INT32 n = (INT32) DashRec::GetNumStockDashes(); for (INT32 i = (INT32) SD_SOLID; i < n; i++) { // If we fail then quit now. String_256 str = DashRec::GetStockDashName((StockDash) i); if (!CreateItem(pGroup, new LineDashItem((StockDash) i, str))) return FALSE; } // Success! return TRUE; } /******************************************************************************************** > BOOL LineGallery::CreateArrowGroup() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if successful. Purpose: Creates a new "arrowhead/tail" Group with its associated items. Errors: - SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem; LineStartArrowItem::LineStartArrowItem ********************************************************************************************/ BOOL LineGallery::CreateArrowGroup() { // Create the group. LineAttrGroup* pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_CREATEARROW)), TRUE); if (pGroup != NULL) pGroup->Flags.Folded = TRUE; // Create each item. First the "no-arrowhead" item. if (!CreateItem(pGroup, new LineNoEndArrowItem(String_64(_R(IDS_LINEGAL_NOHEAD)))) || !CreateItem(pGroup, new LineNoStartArrowItem(String_64(_R(IDS_LINEGAL_NOTAIL))))) { return FALSE; } // Now do the real ones. INT32 nTypes = (INT32) ArrowRec::GetNumStockArrows(); for (INT32 i = (INT32) SA_STRAIGHTARROW; i < nTypes; i++) { for (INT32 j = 0; j < 4; j++) { // Get the text description for this kind of arrowhead. String_256 str = ArrowRec::GetStockArrowName((StockArrow) i); LineArrowItem* pItem = new LineArrowItem((StockArrow) i, m_anArrowScales[j], str); if (!CreateItem(pGroup, pItem)) return FALSE; } } // Success! return TRUE; } /******************************************************************************************** > BOOL LineGallery::CreateCapGroup() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if successful. Purpose: Creates a new "line cap" Group with its associated items. Errors: - SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem; LineCapItem::LineCapItem ********************************************************************************************/ BOOL LineGallery::CreateCapGroup() { // Create the group. LineAttrGroup* pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_CREATECAP)), TRUE); if (pGroup != NULL) pGroup->Flags.Folded = TRUE; // Create each item. return CreateItem(pGroup, new LineCapItem(LineCapButt, String_64(_R(IDS_LINEGAL_BUTT)))) && CreateItem(pGroup, new LineCapItem(LineCapRound, String_64(_R(IDS_LINEGAL_ROUND)))) && CreateItem(pGroup, new LineCapItem(LineCapButt, String_64(_R(IDS_LINEGAL_SQUARE)))); } /******************************************************************************************** > BOOL LineGallery::CreateJoinTypeGroup() Author: Justin_Flude (Xara Group Ltd) Created: 28/3/95 Inputs: - Outputs: - Returns: TRUE if successful. Purpose: Creates a new "join type" Group with its associated items. Errors: - SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem; LineJoinTypeItem::LineJoinTypeItem ********************************************************************************************/ BOOL LineGallery::CreateJoinTypeGroup() { // Create the group. LineAttrGroup* pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_CREATEJOIN)), TRUE); if (pGroup != NULL) pGroup->Flags.Folded = TRUE; // Create each item. return CreateItem(pGroup, new LineJoinTypeItem(MitreJoin, String_64(_R(IDS_LINEGAL_MITRE)))) && CreateItem(pGroup, new LineJoinTypeItem(RoundJoin, String_64(_R(IDS_LINEGAL_ROUND)))) && CreateItem(pGroup, new LineJoinTypeItem(BevelledJoin, String_64(_R(IDS_LINEGAL_BEVEL)))); } /******************************************************************************************** > BOOL LineGallery::CreateVarWidthGroup() Author: Jason_Williams (Xara Group Ltd) Created: 3/3/97 Returns: TRUE if successful. Purpose: Creates a new "variable width" Group with its associated items. SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem ********************************************************************************************/ BOOL LineGallery::CreateVarWidthGroup() { // Removed from non-stroking builds 2/10/97 #ifdef VECTOR_STROKING // Create the group. LineAttrGroup *pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_GROUP_VARWIDTH)), TRUE); if (pGroup == NULL) return(FALSE); // --- Simple constant-width line ------------------------------------------ VariableWidthAttrValue *pAttr; pAttr = new VariableWidthAttrValue(NULL); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONSTANT))))) return(FALSE); // --- SmoothStroke SS_Fallout ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Fallout); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_FALLOUT))))) return(FALSE); // --- SmoothStroke SS_Iron ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Iron); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_IRON))))) return(FALSE); // --- Ellipse ------------------------------------------------------------- pAttr = new VariableWidthAttrValue(new ValueFunctionEllipse); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_ELLIPSE))))) return(FALSE); // --- SmoothStroke SS_SlimBlip ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_SlimBlip); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_SLIMBLIP))))) return(FALSE); // --- Blip ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionBlip); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_BLIP))))) return(FALSE); // --- SmoothStroke SS_Cigar ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Cigar); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CIGAR))))) return(FALSE); // --- SmoothStroke SS_Cigar2 ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Cigar2); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CIGAR_2))))) return(FALSE); // --- SmoothStroke SS_Cigar3 ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Cigar3); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CIGAR_3))))) return(FALSE); // --- SmoothStroke SS_Convex ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Convex); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONVEX))))) return(FALSE); // --- Simple S-shaped ramp with none-zero end width------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionRampS2); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONVEX_2))))) return(FALSE); // --- Simple S-shaped ramp ------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionRampS); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONVEX_3))))) return(FALSE); // --- SmoothStroke SS_Concave ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Concave); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONCAVE))))) return(FALSE); // --- Simple linear ramp with non-zero end width -------------------------------------------------- pAttr = new VariableWidthAttrValue(new ValueFunctionRampL2); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONCAVE_2))))) return(FALSE); // --- Simple linear ramp -------------------------------------------------- pAttr = new VariableWidthAttrValue(new ValueFunctionRampL); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_CONCAVE_3))))) return(FALSE); // --- Teardrop CurvedEnd ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionTeardropCurvedEnd); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_DAB))))) return(FALSE); // --- Teardrop ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionTeardrop); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_RAINDROP))))) return(FALSE); // --- SmoothStroke SS_Comet ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Comet); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_COMET))))) return(FALSE); // --- SmoothStroke SS_Petal ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Petal); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_PETAL))))) return(FALSE); // --- SmoothStroke SS_Reed ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Reed); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_REED))))) return(FALSE); // --- SmoothStroke SS_Meteor ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Meteor); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_METEOR))))) return(FALSE); // --- SmoothStroke SS_Torpedo ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Torpedo); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_TORPEDO))))) return(FALSE); // --- SmoothStroke SS_Missile ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Missile); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_MISSILE))))) return(FALSE); // --- SmoothStroke SS_Goldfish ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Goldfish); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_GOLDFISH))))) return(FALSE); // --- SmoothStroke SS_Yacht ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Yacht); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_YACHT))))) return(FALSE); // --- SmoothStroke SS_Barb ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_Barb); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_BARB))))) return(FALSE); // --- SmoothStroke SS_Ocean Liner ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSS_OceanLiner); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_OCEAN_LINER))))) return(FALSE); // --- Propeller ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionPropeller); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_PROPELLER))))) return(FALSE); // --- DoubleRampS ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionDoubleRampS); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_BOW_TIE))))) return(FALSE); // --- BevelEnds ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionBevelEnds); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_BEVELLED_ENDS))))) return(FALSE); // --- SawTooth ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionSawTooth); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_SAW_TOOTH))))) return(FALSE); // --- Intestine ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionIntestine); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_INTESTINE))))) return(FALSE); // --- Decay ------------------------------------------------------------ pAttr = new VariableWidthAttrValue(new ValueFunctionDecay); if (pAttr == NULL || !CreateItem(pGroup, new VarWidthItem(pAttr, String_64(_R(IDS_LINEGAL_VARWIDTH_DECAY))))) return(FALSE); #endif // VECTOR_STROKING return(TRUE); } /******************************************************************************************** > BOOL LineGallery::CreateStrokeTypeGroup() Author: Jason_Williams (Xara Group Ltd) Created: 3/3/97 Returns: TRUE if successful. Purpose: Creates a new "Stroke type" Group with its associated items. SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem ********************************************************************************************/ BOOL LineGallery::CreateStrokeTypeGroup() { // Removed from non-stroking builds 2/10/97 #ifdef VECTOR_STROKING // Create the group. LineAttrGroup *pGroup = CreateGroup(String_256(_R(IDS_LINEGAL_GROUP_STROKETYPE)), TRUE); if (pGroup == NULL) return(FALSE); // Create each item. StrokeTypeAttrValue *pAttr; // --- Simple old-style line ----------------------------------------------- pAttr = new StrokeTypeAttrValue(NULL); if (pAttr == NULL || !CreateItem(pGroup, new StrokeTypeItem(pAttr, String_64(_R(IDS_LINEGAL_STROKETYPE_LINE))))) return(FALSE); // --- Simple flat-filled stroke -------------------------------------------- pAttr = new StrokeTypeAttrValue(new PathProcessorStroke); if (pAttr == NULL || !CreateItem(pGroup, new StrokeTypeItem(pAttr, String_64(_R(IDS_LINEGAL_STROKETYPE_STROKE))))) return(FALSE); /* // --- Airbrush (L) --------------------------------------------------------- PathProcessorStrokeAirbrush *pAirbrush = new PathProcessorStrokeAirbrush; if (pAirbrush == NULL) return(FALSE); pAirbrush->SetIntensityFunction(new ValueFunctionRampL); pAttr = new StrokeTypeAttrValue(pAirbrush); if (pAttr == NULL || !CreateItem(pGroup, new StrokeTypeItem(pAttr, String_64(TEXT("Thin airbrush"))))) return(FALSE); // --- Airbrush (S) --------------------------------------------------------- pAirbrush = new PathProcessorStrokeAirbrush; if (pAirbrush == NULL) return(FALSE); pAirbrush->SetIntensityFunction(new ValueFunctionRampS); pAttr = new StrokeTypeAttrValue(pAirbrush); if (pAttr == NULL || !CreateItem(pGroup, new StrokeTypeItem(pAttr, String_64(TEXT("Thick airbrush"))))) return(FALSE); */ #endif // VECTOR_STROKING return(TRUE); } /******************************************************************************************** > BOOL LineGallery::CreateBrushGroups() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 9/1/2000 Returns: TRUE if successful. Purpose: Creates groups to hold brushes in the line gallery. Basically we create folders for each of the default files that are loaded during start-up, plus one extra folder where all subsequent brushes will be put. Note that PrepareBrushFolders must have been called at some point prior to this. SeeAlso: LineGallery::CreateGroup; LineGallery::CreateItem ********************************************************************************************/ BOOL LineGallery::CreateBrushGroups() { // Create the default folder, which will contain the default stroke LineAttrGroup *pGroup = CreateGroup(String_256(_R(IDS_BRUSHGROUP_DEFAULT)), TRUE); if (pGroup == NULL) return(FALSE); // Create a default 'no brush' brush BrushAttrValue *pAttr; // --- Simple old-style line ----------------------------------------------- pAttr = new BrushAttrValue; if (pAttr == NULL || !CreateItem(pGroup, new BrushAttrItem(pAttr, String_64(_R(IDS_BRUSHITEM_DEFAULT))))) return(FALSE); //For this release, force the brush group to be invisible and non-selectable // pGroup->Flags.Folded = true; // pGroup->Flags.Invisible = true; // pGroup->Flags.CanSelect = false; // make groups for all the filenames we stored if (m_pFileNameArray != NULL) { UINT32 Counter = 0; String_256 GroupName; pGroup = NULL; while (Counter < m_NumDefaultFiles) { GroupName = m_pFileNameArray[Counter++]; // create the group pGroup = CreateGroup(GroupName, TRUE); if (pGroup == NULL) return(FALSE); //For this release, force the brush group to be invisible and non-selectable // pGroup->Flags.Folded = true; // pGroup->Flags.Invisible = true; // pGroup->Flags.CanSelect = false; } } return TRUE; } /******************************************************************************************** > virtual BOOL LineGallery::ApplyAction(SGActionType Action) Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Inputs: Action - Indicates what action to apply Returns: TRUE to indicate successful handling of the action, or FALSE to indicate failure (NOTE that this is not necessarily an error, but may simply be that we don't support the given action. e.g. if we don't handle APPLYADJUST, we'll be called again with a normal APPLY call) Purpose: Applies certain conventional gallery actions (usually associated with gallery buttons, for new, edit, delete, etc) SeeAlso: SGActionType ********************************************************************************************/ BOOL LineGallery::ApplyAction(SGActionType Action) { // No display tree? Better forget about it then! if (DisplayTree == NULL) return FALSE; // Now, process the action TO DO! - see Colour gallery for examples switch (Action) { case SGACTION_APPLY: return OnApplyButton(FALSE); case SGACTION_APPLYADJUST: return OnApplyButton(TRUE); case SGACTION_SETLINEPROPERTIES: return TRUE; case SGACTION_SETOPTIONS: case SGACTION_CREATE: case SGACTION_REDEFINE: case SGACTION_EDIT: case SGACTION_DELETE: case SGACTION_DISPLAYMODECHANGED: TRACEUSER( "JustinF", _T("Unimplemented feature executed in Line gallery\n")); // Drop through to default handler (return FALSE) default: ERROR3("Unexpected action in LineGallery::ApplyAction"); return FALSE; } // Successful processing. return TRUE; } /******************************************************************************************** > virtual MsgResult LineGallery::Message(Msg* Message) Author: Justin_Flude (Xara Group Ltd) Created: 15/2/95 (base generated in sgbase.cpp) Inputs: Message - The message to handle Purpose: A standard message handler, really. Notes: Any messages that this does not handle must be passed down to the SuperGallery base class message handler. NOTE WELL that the SuperGallery base class handler does some funky things for us - see SuperGallery::Message - such as deleting our display subtree for any document which dies (which, uncannily, would explain why they go away like that when you close documents ;-), and shading the gallery when there are no documents present. [To override this behaviour in these cases, you should respond to the message, and return OK rather than calling the base class message handler] SeeAlso: SuperGallery::Message ********************************************************************************************/ MsgResult LineGallery::Message(Msg* pMessage) { // Do we need to update our display of the current attributes. if (MESSAGE_IS_A(pMessage, CurrentAttrChangedMsg)) { LineAttrItem::UpdateCurrentAttribStatus(); } // A dialogue box message? else if (IS_OUR_DIALOG_MSG(pMessage)) { DialogMsg* pMsg = (DialogMsg*) pMessage; switch (pMsg->DlgMsg) { // Gallery being created. case DIM_CREATE: SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAY_LINE_GALLERY), TRUE); break; // Gallery being closed. case DIM_CANCEL: SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAY_LINE_GALLERY), FALSE); break; case DIM_LFT_BN_CLICKED: if (pMsg->GadgetID == _R(IDC_GALLERY_HELP)) // Show help page { HelpUserTopic(_R(IDS_HELPPATH_Gallery_Line)); } break; default: break; } } // A document state message? else if (MESSAGE_IS_A(pMessage, DocChangingMsg)) { DocChangingMsg* pMsg = (DocChangingMsg*) pMessage; if (pMsg->State == DocChangingMsg::SELCHANGED) { if (pMsg->pNewDoc != NULL) { // A new document is selected, so update our selection state. SuperGallery::ShadeGallery(FALSE); SelectionHasChanged(); } else { // There is no selected doc, so grey the gallery for now. SuperGallery::ShadeGallery(TRUE); } } } else if (MESSAGE_IS_A(pMessage, BrushDefMsg)) { UpdateBrushItem(((BrushDefMsg*)pMessage)->m_BrushEdited); } // Pass on to the base-class for any more handling. return SuperGallery::Message(pMessage); } /******************************************************************************************** > void LineGallery::UpdateBrushItem(BrushHandle Handle) Author: Diccon_Yamanaka (Xara Group Ltd) Created: 3/4/2000 Inputs: Handle - identifier for the brush that needs updating Outputs: - Returns: - Purpose: Searches for a brush item with the same handle as Handle, and asks it to update itself Errors: - SeeAlso: - ********************************************************************************************/ void LineGallery::UpdateBrushItem(BrushHandle Handle) { // we need to make sure the groups have been created if (!MakeSureGroupsHaveBeenCreated()) return; // Iterate over each group. for (LineAttrGroup* pGroup = (LineAttrGroup*) GetDisplayTree()->GetChild(); pGroup != NULL; pGroup = (LineAttrGroup*) pGroup->GetNext()) { // Iterate over each item within the group. LineAttrItem* pNextItem; LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); // if its not a brush we're not interested if (!pItem->IsKindOf(CC_RUNTIME_CLASS(BrushAttrItem))) pItem = NULL; while (pItem != NULL) { // get the next item before we delete anything pNextItem = (LineAttrItem*) pItem->GetNext(); // If the item is selected then remove it from the tree before deleting if (((BrushAttrItem*)pItem)->GetBrushHandle() == Handle) ((BrushAttrItem*)pItem)->UpdateGalleryItem(); pItem = pNextItem; } } } /******************************************************************************************** > virtual BOOL LineGallery::OnSelChangingMsg(SelChangeMsg::SelectionState st) Author: Justin_Flude (Xara Group Ltd) Created: 17/4/95 Inputs: st reason code for what's happing to the selection Outputs: - Returns: TRUE if the message is processed successfully. Purpose: Responds to the selection state changing by updating the "current attribute" status of the gallery's items. Errors: - SeeAlso: - ********************************************************************************************/ /* BOOL LineGallery::OnSelChangingMsg(SelChangingMsg::SelectionState st) { return SuperGallery::OnSelChangingMsg(st) && LineAttrItem::UpdateCurrentAttribStatus(); } */ /******************************************************************************************** > virtual BOOL LineGallery::OnCommonAttrsChangedMsg() Author: Simon_Maneggio (Xara Group Ltd) Created: 09/02/95 Returns: TRUE if the message is processed successfully. Purpose: Responds to the the common attributes changing ********************************************************************************************/ BOOL LineGallery::OnCommonAttrsChangedMsg() { return SuperGallery::OnCommonAttrsChangedMsg() && LineAttrItem::UpdateCurrentAttribStatus(); } /******************************************************************************************** > virtual RenderRegion* LineGallery::CreateRenderRegion(DocRect* pSize, ReDrawInfoType* pInfo) Author: Justin_Flude (Xara Group Ltd) Created: 29/3/95 Inputs: pSize how big the render region should be pInfo some more information about it Outputs: - Returns: A pointer to a newly created GDraw render-region, or NULL if it fails. Purpose: Creates a GDraw render-region for drawing in a super-gallery. Overrides the default behaviour, which creates an OS render-region. Errors: - SeeAlso: DialogOp::CreateGRenderRegion ********************************************************************************************/ RenderRegion* LineGallery::CreateRenderRegion(DocRect* pSize, ReDrawInfoType* pInfo) { // Try to create a GDraw render-region. RenderRegion* pRegion = CreateGRenderRegion(pSize, pInfo); if (pRegion != NULL) { // Try to create a display quality attribute. QualityAttribute* pAttr = new QualityAttribute; if (pAttr != NULL) { // If all that worked then turn on anti-aliasing when drawing in the gallery. pAttr->QualityValue = Quality::QualityMax; pRegion->SetQuality(pAttr, TRUE); } } return pRegion; } /******************************************************************************************** > virtual void LineGallery::DestroyRenderRegion(RenderRegion* pRegion) Author: Justin_Flude (Xara Group Ltd) Created: 29/3/95 Inputs: pRegion pointer to the RenderRegion to destroy Outputs: - Returns: - Purpose: Destroys the given render-region (in this case a GDraw version). Errors: - SeeAlso: DialogOp::DestroyGRenderRegion ********************************************************************************************/ void LineGallery::DestroyRenderRegion(RenderRegion* pRegion) { DestroyGRenderRegion(pRegion); } /******************************************************************************************** > virtual void LineGallery::SelectionHasChanged() Author: Justin_Flude (Xara Group Ltd) Created: 7/4/95 Inputs: - Outputs: - Returns: - Purpose: Called by the base-class SuperGallery whenever the user clicks on an item. This version overrides the default bahaviour so that selecting more than one item does NOT grey the "Apply" button. Errors: - SeeAlso: - ********************************************************************************************/ void LineGallery::SelectionHasChanged() { // Nothing to do if we are unavailable. if (GetDisplayTree() == NULL || AmShaded || !IsVisible()) return; // Only grey the "Apply" button when NO items are selected. EnableGadget(_R(IDC_GALLERY_APPLY), (GetDisplayTree()->GetSelectedItemCount() > 0)); // Update the status text to reflect the new selection. SetStatusText(); } /******************************************************************************************** > virtual BOOL LineGallery::OnApplyButton(BOOL fIsAdjust) Author: Justin_Flude (Xara Group Ltd) Created: 6/4/95 Inputs: fIsAdjust if TRUE then modify action to "adjust" apply Outputs: - Returns: TRUE if the application is successful (i.e. did something) FALSE if we failed to do anything useful (not necessarily an error) Purpose: Called by the line gallery when the user clicks the "Apply" button. Iterates over each group within the gallery trying to apply any selected attributes within the group to the current selection. Errors: Out of memory. SeeAlso: LineGallery::ApplyAction ********************************************************************************************/ BOOL LineGallery::OnApplyButton(BOOL fIsAdjust) { BOOL ActuallyDidSomething = FALSE; // Iterate over each group. for (LineAttrGroup* pGroup = (LineAttrGroup*) GetDisplayTree()->GetChild(); pGroup != NULL; pGroup = (LineAttrGroup*) pGroup->GetNext()) { // Iterate over each item within the group. for (LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); pItem != NULL; pItem = (LineAttrItem*) pItem->GetNext()) { // If the item is selected then try to apply the attribute it represents // to the current selection. if (pItem->IsSelected()) { // Ask the item to create a new attribute of the required kind. NodeAttribute* pNewAttr = pItem->CreateNewAttribute(fIsAdjust); ERRORIF(pNewAttr == NULL, _R(IDE_NOMORE_MEMORY), FALSE); // ask items if they need to do anything before they become selected // Note that if this returns FALSE it means we no longer want to apply // the attribute here if (pItem->ItemSelected(pNewAttr)) AttributeManager::AttributeSelected(pNewAttr); // deselect the item pItem->SetSelected(FALSE); ActuallyDidSomething = TRUE; } } } // Success. return(ActuallyDidSomething); } /******************************************************************************************** > void LineGallery::SetStatusText() Author: Justin_Flude (Xara Group Ltd) Created: 26/4/95 Purpose: Works out what the status text should be from which items are selected in the gallery, and updates it on-screen. SeeAlso: LineGallery::SelectionHasChanged ********************************************************************************************/ void LineGallery::SetStatusText() { /* THIS CODE HAS BEEN COMMENTED OUT BECAUSE, ALTHOUGH IT WORKS, THE GALLERY STATUS-LINE CODE PROVIDES ITS OWN STATUS-LINE HELP TEXT FOR THE APPLY BUTTON. // Update the status line text, according to what is selected in the gallery. String_256 strAttribs; strAttribs.Empty(); // Ask each selected item in each group to provide a description of its attribute. INT32 nSelected = 0; for (LineAttrGroup* pGroup = (LineAttrGroup*) GetDisplayTree()->GetChild(); pGroup != NULL; pGroup = (LineAttrGroup*) pGroup->GetNext()) { for (LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); pItem != NULL; pItem = (LineAttrItem*) pItem->GetNext()) { // Does this item have something to contribute? if (pItem->IsSelected()) { // It does, so if it isn't the first add some punctuation. if (nSelected > 0) strAttribs += TEXT(", "); strAttribs += pItem->GetDescription(); nSelected++; } } } // Did we find any selected attributes? if (nSelected > 0) { // If there's only one attribute then prepend a singular indefinite article and don't // pluralize the "attribute" word. If not then vice versa. String strPlural = TEXT("s"); // Commented out if (nSelected == 1) { String_256 s = TEXT("a "); // Commented out strAttribs = (s += strAttribs); strPlural.Empty(); } // Format the attribute text into a meaningful sentence and if successful set the // status line text with the information. String_256 strStatus; if (strStatus.MakeMsg(_R(IDS_LINEGAL_STATUS_TEXT_MASK), &strAttribs, &strPlural) != 0) { // Write the new text. // GetApplication()->UpdateStatusBarText(&strStatus); TRACEUSER( "JustinF", _T("%s\n"), (LPCTSTR) strStatus); } } */ } /******************************************************************************************** > static void LineGallery::AddNewStrokeItem(AttrStrokeType *pNewStroke); Author: Jason_Williams (Xara Group Ltd) Created: 3/3/97 Purpose: Finds the line gallery, and adds the given stroke type attribute to the end of the stroke type display. ********************************************************************************************/ void LineGallery::AddNewStrokeItem(StrokeTypeAttrValue *pNewStroke) { // Removed from non-stroking builds 2/10/97 #ifdef VECTOR_STROKING ERROR3IF(pNewStroke == NULL, "Illegal NULL param"); LineGallery *pGallery = (LineGallery *) LineGallery::GetInstance(); if (pGallery == NULL) return; // This will create the groups if they're not there yet pGallery->MakeSureGroupsHaveBeenCreated(); SGDisplayRoot *pRoot = pGallery->GetDisplayTree(); if (pRoot == NULL) return; LineAttrGroup *pGroup = (LineAttrGroup *) pRoot->GetChild(); if (pGroup == NULL) return; #if _DEBUG SGDisplayItem *pItem = (SGDisplayItem *) pGroup->GetChild(); ERROR3IF(pItem == NULL || !pItem->IsKindOf(CC_RUNTIME_CLASS(StrokeTypeItem)), "LineGallery::AddNewStrokeItem - I seem to be adding to the wrong group!"); #endif // Find the stroke's name, if it has one String_64 Name(TEXT("Custom brush")); PathProcessorStroke *pProcessor = pNewStroke->GetPathProcessor(); if (pProcessor != NULL && pProcessor->IsKindOf(CC_RUNTIME_CLASS(PathProcessorStrokeVector))) { StrokeHandle Handle = ((PathProcessorStrokeVector *)pProcessor)->GetStrokeDefinition(); StrokeDefinition *pStroke = StrokeComponent::FindStroke(Handle); if (pStroke != NULL) Name = *pStroke->GetStrokeName(); } StrokeTypeItem * pStrokeTypeItem = new StrokeTypeItem(pNewStroke, Name); if (pStrokeTypeItem == NULL) return; pGallery->CreateItem(pGroup, pStrokeTypeItem); pGallery->ReformatAndRedrawIfNecessary(); #endif // VECTOR_STROKING } /******************************************************************************************** > static void LineGallery::AddNewItem(BrushAttrValue *pNewBrush); Author: Diccon_Yamanaka (Xara Group Ltd) Created: 9/1/2000 Purpose: Goes through the line gallery to find out which group to add the new brush to. Basically if the brushes fileID == BRUSHFILE_NONE then it belongs in the default folder, otherwise we find the folder name from our array. ********************************************************************************************/ void LineGallery::AddNewBrushItem(BrushAttrValue *pNewBrush) { if (pNewBrush == NULL) { ERROR3("Illegal NULL param"); return; } // find the string for title of the folder from the definition String_256 GroupString(_R(IDS_BRUSHGROUP_DEFAULT)); // initialise to default string BrushDefinition* pDef = pNewBrush->GetBrushDefinition(); if (pDef == NULL) { ERROR3("No brush definition in LineGallery::AddNewBrushItem"); return; } UINT32 FileID = pDef->GetBrushFileID(); if (FileID != BRUSHFILE_NONE && FileID <= m_NumDefaultFiles) { if (m_pFileNameArray != NULL) GroupString = m_pFileNameArray[FileID]; } // now search through the line gallery to find the group with that title LineGallery *pGallery = (LineGallery *) LineGallery::GetInstance(); if (pGallery == NULL) return; // This will create the groups if they're not there yet pGallery->MakeSureGroupsHaveBeenCreated(); SGDisplayRoot *pRoot = pGallery->GetDisplayTree(); if (pRoot == NULL) return; LineAttrGroup *pGroup = (LineAttrGroup *) pRoot->GetChild(); if (pGroup == NULL) return; LineAttrGroup* pCopyGroup = pGroup; // loop through until we find our group. String_256 NameString; while (pCopyGroup != NULL) { NameString = (String_256)(pCopyGroup->GetTitle()); if (NameString.IsIdentical(GroupString)) { pGroup = pCopyGroup; break; } pCopyGroup = (LineAttrGroup*)pCopyGroup->GetNext(); } // Find the stroke's name, if it has one String_64 Name = TEXT(" "); String_32* pName = pDef->GetLineName(); if (pName != NULL) Name = *pName; BrushAttrItem* pBrushAttrItem = new BrushAttrItem(pNewBrush, Name); if (pBrushAttrItem == NULL) return; /* #ifdef _DEBUG pBrushAttrItem->CheckMemory(TRUE); #endif */ pGallery->CreateItem(pGroup, pBrushAttrItem); // we must invalidate so that brushes are scaled correctly the first // time they are drawn pGallery->InvalidateCachedFormat(); pGallery->ReformatAndRedrawIfNecessary(); } /******************************************************************************************** > virtual BOOL LibClipartSGallery::InitMenuCommands(void) Author: Richard_Millican (Xara Group Ltd) Created: 07/03/97 Returns: TRUE for success Purpose: Initialises any menu commands that this gallery needs. Notes: Will only create the menu commands once - further calls in the future will return TRUE immediately wihtout doing anything. ********************************************************************************************/ BOOL LineGallery::InitMenuCommands(void) { static BOOL MenusInitialised = FALSE; BOOL ok = TRUE; if (!MenusInitialised) { // Initialise menu command Ops //ok = ok && InitMenuCommand((StringBase *) &SGCmd_Properties, _R(IDS_SGMENU_PROPERTIES)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_RenameBrush, _R(IDS_SGMENU_RENAMEBRUSH)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_ExportBrush, _R(IDS_SGMENU_EXPORTBRUSH)); ok = ok && InitMenuCommand((StringBase *) &SGCmd_Delete, _R(IDS_SGMENU_DELETE)); MenusInitialised = TRUE; } return(ok); } /******************************************************************************************** > virtual BOOL LibClipartSGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID) Author: Richard_Millican (Xara Group Ltd) Created: 07/03/97 Inputs: TheMenu - The menu to add commands to MenuID - The type of menu (over-list or from-options-button) to create Returns: TRUE if it succeeded Purpose: To build a menu of commands to be popped up over the gallery. ********************************************************************************************/ BOOL LineGallery::BuildCommandMenu(GalleryContextMenu *TheMenu, SGMenuID MenuID) { BOOL ok = FALSE; SGDisplayNode *pItem = DisplayTree->FindNextSelectedItem(NULL); // Only pop the properties menu up for Custom Brushes if(pItem != NULL && pItem->IsKindOf(CC_RUNTIME_CLASS(StrokeTypeItem))) { StrokeTypeAttrValue *pAttrType = ((StrokeTypeItem *)pItem)->GetStrokeTypeAttrValue(); if(pAttrType != NULL) { PathProcessor *pPP = pAttrType->GetPathProcessor(); if(pPP != NULL && pPP->AllowsPropertiesDialog()) { ok = AddCommand(TheMenu, (StringBase *) &SGCmd_Properties); } } } // we want to launch our new edit dialog for the new style brushes, its all new baby if (pItem != NULL && pItem->IsKindOf(CC_RUNTIME_CLASS(BrushAttrItem))) { // make sure its not the default 'no brush' BrushDefinition* pDef = ((BrushAttrItem*)pItem)->GetBrushDefinition(); if ( pDef != NULL) { ok = AddCommand(TheMenu, (StringBase *) &SGCmd_RenameBrush); if (ok) ok = AddCommand(TheMenu, (StringBase *) &SGCmd_ExportBrush); // check to see that this is not a default brush before adding delete option UINT32 FileID = pDef->GetBrushFileID(); if (FileID == BRUSHFILE_NONE && ok) ok = AddCommand(TheMenu, (StringBase *) &SGCmd_Delete); } } return(ok); } /******************************************************************************************** > virtual OpState LibClipartSGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason) Author: Richard_Millican (Xara Group Ltd) Created: 07/03/97 Inputs: CommandID - TheString ID of the command Outputs: ShadeReason - If you return (OpState.Greyed == TRUE) then this should be filled ion with the reason that the item is shaded/greyed. Returns: An OpState indicating the current menu item state. Purpose: To determine the state of a given menu item. This method is an exact parallel to an Op's GetState method (in fact, it is called by an Op's GetState) ********************************************************************************************/ OpState LineGallery::GetCommandState(StringBase *CommandID, String_256 *ShadeReason) { OpState State; if (*CommandID == SGCmd_Properties) return(State); return(State); } /******************************************************************************************** > virtual void LineGallery::DoCommand(StringBase *CommandID) Author: Richard_Millican (Xara Group Ltd) Created: 07/03/97 Inputs: CommandID - The String ID of the command Purpose: To apply a given command when it is chosen from the menu. ********************************************************************************************/ void LineGallery::DoCommand(StringBase *CommandID) { // Taken out by vector stroking code Neville 2/10/97 #ifdef VECTOR_STROKING // if (*CommandID == SGCmd_Properties) // { // SGalleryLinePropertiesDlg::InvokeDialog(this); // } // else #endif // VECTOR_STROKING // we are now launching the brush edit dialog from here SGDisplayNode *pItem = DisplayTree->FindNextSelectedItem(NULL); // we want to launch our new edit dialog for the new style brushes, its all new baby if (pItem != NULL && pItem->IsKindOf(CC_RUNTIME_CLASS(BrushAttrItem))) { // get the brush component from the document Document* pDoc = Document::GetCurrent(); if (pDoc == NULL) { return; // not necessarily an error, but we don't wish to proceed } BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); if (pBrushComp == NULL) { ERROR3("We've got a document with no brush component"); return; } BrushHandle Handle = ((BrushAttrItem*)pItem)->GetBrushHandle(); if (Handle != BrushHandle_NoBrush) { if (*CommandID == SGCmd_RenameBrush) { // launch the naming dialog OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_NAME_BRUSH_DLG); if (pDesc != NULL) { // provide the new brush handle as a parameter OpParam Param(static_cast(Handle), 0); pDesc->Invoke(&Param); } } else if (*CommandID == SGCmd_ExportBrush) { pBrushComp->CopyInkObjectsToClipboard(Handle); } else if (*CommandID == SGCmd_Delete) { OpDescriptor* pDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_DELETEBRUSH); if (pDesc != NULL) { // provide the new brush handle as a parameter OpParam Param(static_cast(Handle), 0); pDesc->Invoke(&Param); } } } } // SuperGallery::DoCommand(CommandID); // Unknown command- pass to the base class } /******************************************************************************************** > MILLIPOINT LineGallery::SetCurrentLineWidth() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 9/1/2000 Returns: the current default line width Purpose: queries AttributeManager to get the current default,sets it as the member variable and returns it ********************************************************************************************/ MILLIPOINT LineGallery::SetPreviousLineWidth() { Document* pDoc = Document::GetCurrent(); if (pDoc == NULL) { ERROR3("No document"); return -1; } AttributeManager* pAttrMgr = &(pDoc->GetAttributeMgr()); if (pAttrMgr == NULL) { ERROR3("No attribute manager"); return -1; } NodeAttribute* pAttr = pAttrMgr->GetCurrentAttribute(CC_RUNTIME_CLASS(NodeRenderableInk), CC_RUNTIME_CLASS(AttrLineWidth)); if (pAttr == NULL) return -1; LineWidthAttribute* pVal = (LineWidthAttribute*)pAttr->GetAttributeValue(); if (pVal == NULL) return -1; m_PreviousLineWidth = pVal->LineWidth; return m_PreviousLineWidth; } /******************************************************************************************** > BOOL LineGallery::PrepareBrushFolders() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 9/1/2000 Returns: TRUE if successful. Purpose: Prepares tp create folders in which to put brushes that are loaded in as part of the load default brushes process. Basically scans for .xar files in the /Templates/Brushes/ folders and stores each filename found. These filenames are subsequently used to create folders in CreateBrushGroups SeeAlso: ********************************************************************************************/ BOOL LineGallery::PrepareBrushFolders() { // find all .xar files in the /templates/brushes directory and put them in a temp array PORTNOTE("other", "Disabled loading of line gallery templates") #ifndef EXCLUDE_FROM_XARALX // allocate a stupidly large array String_256 TempString[1000]; // surely can't be 1000 files! // set up the path to our .xar files String_256 SearchPath; CResDll::GetExecutablePath((TCHAR*)SearchPath); String_256 Path = TEXT("\\Templates\\Brushes\\"); SearchPath += Path; String_256 FileSpecifier = SearchPath; FileSpecifier += TEXT("*.xar"); UINT32 Counter = 0; // use file util to find the file for us, we need only pass the searchpath BOOL ok = FileUtil::StartFindingFiles(&FileSpecifier); String_256 Filename; INT32 StringLength; String_256 ShortName; while (ok) { // FileUtil will put our filename string into Filename ok = FileUtil::FindNextFile(&Filename); if (ok && Counter < 1000) { // strip the .xar from the string StringLength = Filename.Length(); Filename.Left(&ShortName, StringLength - 4); // //Special case - when Xara default brushes are loaded, change the folder group // //text to something prettier than "defbrush" - bit of a bodge but it works... // if (ShortName == String_256("defbrush")) // { // ShortName = String_256("Default brushes"); // } TempString[Counter++] = ShortName; } } FileUtil::StopFindingFiles(); // Now allocate our member string array, MFC seems to get very upset when // we try to delete an array of String_256's so use malloc m_pFileNameArray = (String_256*)malloc(sizeof(String_256) * Counter); if (m_pFileNameArray == NULL) return FALSE; // copy the strings over INT32 size = sizeof(String_256); memcpy(m_pFileNameArray, &TempString, size * Counter); m_NumDefaultFiles = Counter; // remember how many we got #endif return TRUE; } /******************************************************************************************** > MILLIPOINT LineGallery::GetCurrentLineWidth() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 9/1/2000 Returns: the previous line width member Purpose: as above ********************************************************************************************/ MILLIPOINT LineGallery::GetPreviousLineWidth() { return m_PreviousLineWidth; } /******************************************************************************************** > BOOL LineGallery::DeleteSelection() Author: Diccon_Yamanaka (Xara Group Ltd) Created: 17/7/2000 Inputs: Handle - the handle of the brush to delete Outputs: - Returns: TRUE if all went well, FALSE if not Purpose: Deletes the brush with the given handle Errors: - SeeAlso: - ********************************************************************************************/ BOOL LineGallery::DeleteBrushItem(BrushHandle Handle) { LineGallery *pGallery = (LineGallery *) LineGallery::GetInstance(); if (pGallery == NULL) return FALSE; // Iterate over each group. for (LineAttrGroup* pGroup = (LineAttrGroup*) GetDisplayTree()->GetChild(); pGroup != NULL; pGroup = (LineAttrGroup*) pGroup->GetNext()) { // Iterate over each item within the group. LineAttrItem* pNextItem; LineAttrItem* pItem = (LineAttrItem*) pGroup->GetChild(); // if its not a brush we're not interested if (!pItem->IsKindOf(CC_RUNTIME_CLASS(BrushAttrItem))) pItem = NULL; while (pItem != NULL) { // get the next item before we delete anything pNextItem = (LineAttrItem*) pItem->GetNext(); // If the item is selected then remove it from the tree before deleting if (((BrushAttrItem*)pItem)->GetBrushHandle() == Handle) { pItem->RemoveFromTree(); pItem->DestroySubtree(TRUE); } pItem = pNextItem; } } SelectionHasChanged(); pGallery->ReformatAndRedrawIfNecessary(); return TRUE; } /******************************************************************************************** > static BOOL OpDisplayLineGallery::Init() Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Inputs: - Outputs: - Returns: TRUE if the operation could be successfully initialised FALSE if no more memory could be allocated Purpose: General-purpose line gallery initialiser method Errors: - SeeAlso: - ********************************************************************************************/ BOOL OpDisplayLineGallery::Init() { return LineGallery::Init() && OpChangeLineJoinOpDesc::Init() && OpChangeLineCapOpDesc::Init() && RegisterOpDescriptor(0, _R(IDS_DISPLAY_LINE_GALLERY), CC_RUNTIME_CLASS(OpDisplayLineGallery), OPTOKEN_DISPLAY_LINE_GALLERY, OpDisplayLineGallery::GetState, 0, /* help ID */ _R(IDBBL_DISPLAY_LINE_GALLERY), _R(IDC_BTN_SGLINE), // UINT32 resourceID = 0, // resource ID _R(IDC_BTN_SGLINE), // UINT32 controlID = 0, // control ID SYSTEMBAR_ILLEGAL, // SystemBarType GroupBarID = SYSTEMBAR_ILLEGAL, // group bar ID TRUE, // BOOL ReceiveMessages = TRUE, // BODGE FALSE, // BOOL Smart = FALSE, TRUE, // BOOL Clean = TRUE, NULL, // OpDescriptor *pVertOpDesc = NULL, 0, // UINT32 OneOpenInstID = 0, 0, // UINT32 AutoStateFlags = 0, TRUE // BOOL fCheckable = FALSE ); } /******************************************************************************************** > OpState OpDisplayLineGallery::GetState(String_256*, OpDescriptor*) Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Inputs: - Outputs: - Returns: The state of the OpDisplayLineGallery operation Purpose: For finding the OpDisplayLineGallery's state. Errors: - SeeAlso: - ********************************************************************************************/ OpState OpDisplayLineGallery::GetState(String_256* UIDescription, OpDescriptor*) { // If the gallery is currently open then the menu item should be ticked. OpState OpSt; SuperGallery* pSuperGallery = FindGallery(); if (pSuperGallery != NULL) OpSt.Ticked = pSuperGallery->IsVisible(); // If there are no open documents, you can't toggle the gallery OpSt.Greyed = (Document::GetSelected() == NULL); return OpSt; } /******************************************************************************************** > void OpDisplayLineGallery::Do(OpDescriptor*) Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Inputs: - Outputs: - Returns: - Purpose: Displays the Lines gallery Errors: - SeeAlso: - ********************************************************************************************/ void OpDisplayLineGallery::Do(OpDescriptor*) { SuperGallery *pSuperGallery = FindGallery(); if (!pSuperGallery) pSuperGallery = new LineGallery(); if (pSuperGallery != NULL) { // Toggle the visible state of the gallery window pSuperGallery->SetVisibility(!pSuperGallery->IsVisible()); // And update the gallery button state SGInit::UpdateGalleryButton(_R(OPTOKEN_DISPLAY_LINE_GALLERY), pSuperGallery->IsVisible()); } End(); } /******************************************************************************************** > static SuperGallery* OpDisplayLineGallery::FindGallery() Author: Justin_Flude (Xara Group Ltd) Created: 9/2/95 (base generated in sgbase.cpp) Returns: NULL or a pointer to the Line gallery instance Purpose: Finds the Line gallery class instance Notes: The bars system always keeps one Line gallery alive for us. If one is not found, this usually indicates that it can't be found in bars.ini: Check that the 'Name' string *exactly* matches the title string given in bars.ini. Also check that bars.ini indicates the bar is of the LineGallery class ********************************************************************************************/ SuperGallery* OpDisplayLineGallery::FindGallery() { SuperGallery* pSuperGallery = SuperGallery::FindSuperGallery(_R(IDD_LINESGALLERY)); if (pSuperGallery != NULL) { if (pSuperGallery->GetRuntimeClass() == CC_RUNTIME_CLASS(LineGallery)) return(pSuperGallery); ERROR3("Got the line gallery but it's not of the LineGallery class?"); } return(NULL); }