00001 // $Id: sgallery.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // SGallery.h - the SuperGallery class 00099 00100 #include "camtypes.h" 00101 00102 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00103 #include "camelot.h" 00104 #include "dragmsg.h" 00105 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 //#include "galstr.h" 00107 //#include "galres.h" 00108 //#include "jason.h" 00109 #include "keypress.h" 00110 #include "camframe.h" 00111 #include "progress.h" 00112 //#include "resource.h" // For _R(IDS_OK) (dammit!) 00113 //#include "sgallery.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 #include "sgdrag.h" 00115 #include "sgmenu.h" 00116 //#include "sgtree.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00117 #include "thumbmsg.h" 00118 //#include "sglinepr.h" 00119 00120 #include "ccdc.h" // For render-into-dialogue support 00121 #include "dlgcol.h" 00122 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00123 #include "grnddib.h" 00124 00125 #include "sgindgen.h" // For ReplaceCharacters function (which should be in stringbase) 00126 #include "sglib.h" // For Searching stuff, which will be removed shortly 00127 //#include "sglbase.h" // For searching stuff 00128 //#include "sglcart.h" // For searching stuff 00129 //#include "sglfills.h" // For searching stuff 00130 00131 //#include "richard3.h" // Few extra text resources 00132 00133 #include "brushmsg.h" // for the screen change message 00134 00135 // Implement the dynamic class bits... 00136 CC_IMPLEMENT_DYNCREATE(SuperGallery, DialogOp) 00137 CC_IMPLEMENT_DYNCREATE(SGalleryOptionsDlg, DialogOp) 00138 CC_IMPLEMENT_DYNCREATE(SGallerySortDlg, DialogOp) 00139 CC_IMPLEMENT_DYNCREATE(SGallerySearchDlg, DialogOp) 00140 00141 // OpParam class for opening the options and search dlgs - local to this .cpp file 00142 class GalDlgParam : public OpParam 00143 { 00144 CC_DECLARE_MEMDUMP(GalDlgParam) 00145 public: 00146 GalDlgParam(SuperGallery *Parent) : OpParam(0, 0) { ParentGal = Parent; }; 00147 SuperGallery *ParentGal; 00148 }; 00149 00150 CC_IMPLEMENT_MEMDUMP(GalDlgParam, OpParam) 00151 00152 00153 00154 00155 // This line mustn't go before any CC_IMPLEMENT_... macros 00156 #define new CAM_DEBUG_NEW 00157 00158 00159 // Static variables 00160 SuperGallery *SuperGallery::CurrentSortGallery = NULL; // Points at the gallery doing the current sort 00161 // Used inside the qsort comparator function 00162 00163 00164 // Preferences 00165 INT32 SuperGallery::UseFixedColourSet = FALSE; // Use Fixed colour set (or read 00166 // redraw colours from Windows settings) 00167 00168 00169 #define MyIdlePriority (IDLEPRIORITY_LOW) 00170 00171 00172 /******************************************************************************************** 00173 00174 > void SuperGallery::InitData(void) 00175 00176 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00177 Created: 10/4/95 00178 00179 Purpose: Internal method to initialise data mambers. Shared code for constructors. 00180 00181 ********************************************************************************************/ 00182 00183 void SuperGallery::InitData(void) 00184 { 00185 GallerySize = wxSize(0,0); 00186 00187 DisplayTree = NULL; 00188 DisplayMode = 0; 00189 00190 FormatIsCached = FALSE; 00191 00192 LastWindowDX = LastWindowDY = 0; 00193 00194 AmShaded = FALSE; 00195 AmRedrawing = FALSE; 00196 00197 LastSelectedNode = NULL; 00198 00199 CurrentOptionsDlg = NULL; 00200 CurrentSortDlg = NULL; 00201 CurrentSearchDlg = NULL; 00202 CurrentLinePropertiesDlg = NULL; 00203 00204 DblClickPending = FALSE; // We aren't in the middle of a double click 00205 00206 PendingRedraws = 0; 00207 LastBGNode = NULL; 00208 00209 for (INT32 i = 0; i < MaxSGSortKeys; i++) 00210 { 00211 SortKeys[i].SortKey = 0; 00212 SortKeys[i].Reversed = FALSE; 00213 } 00214 } 00215 00216 00217 00218 /******************************************************************************************** 00219 00220 > SuperGallery::SuperGallery(CCRuntimeClass *Class = CC_RUNTIME_CLASS(DialogOp)): DialogOp(_R(IDD_BLANKBAR), MODELESS,0,GSAFECLASS(Class)) 00221 00222 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00223 Created: 21/10/94 00224 Purpose: SuperGallery constructor (Identical to DialogOp) 00225 00226 ********************************************************************************************/ 00227 00228 SuperGallery::SuperGallery(CCRuntimeClass *Class): DialogOp(_R(IDD_BLANKBAR), MODELESS,0,GSAFECLASS(Class)) 00229 { 00230 String_32 str = String_32(_R(IDS_K_BARS_NONAME)); 00231 Name=str; 00232 InitData(); 00233 } 00234 00235 00236 00237 /******************************************************************************************** 00238 00239 > SuperGallery::SuperGallery(String_32 &NewName,CCRuntimeClass *Class = CC_RUNTIME_CLASS(DialogOp): 00240 DialogOp(NewName, Class) 00241 00242 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00243 Created: 21/10/94 00244 Purpose: SuperGallery constructor (Identical to DialogOp) 00245 00246 ********************************************************************************************/ 00247 00248 SuperGallery::SuperGallery(String_32 &NewName,CCRuntimeClass *Class) 00249 : DialogOp(_R(IDD_BLANKBAR), MODELESS,0,GSAFECLASS(Class)) 00250 { 00251 String_32 str = String_32(_R(IDS_K_BARS_NONAME)); 00252 Name=str; 00253 InitData(); 00254 } 00255 00256 00257 00258 /******************************************************************************************** 00259 00260 > SuperGallery::~SuperGallery() 00261 00262 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00263 Created: 21/10/94 00264 Purpose: SuperGallery destructor. 00265 00266 ********************************************************************************************/ 00267 00268 SuperGallery::~SuperGallery() 00269 { 00270 if (DisplayTree != NULL) 00271 { 00272 DisplayTree->DestroySubtree(); // Destroy the tree, destructing all nodes except root 00273 delete DisplayTree; // And delete the root as well 00274 DisplayTree = NULL; 00275 } 00276 00277 CloseOwnedDialogs(); 00278 00279 // Remove any idle event processor we had registered for BG redraws 00280 GetApplication()->RemoveIdleProcessor(MyIdlePriority, this); 00281 } 00282 00283 00284 00285 /******************************************************************************************** 00286 00287 > void SuperGallery::FillInMiscInfo(SGMiscInfo *MiscInfo, 00288 ReDrawInfoType *DlgRedrawInfo = NULL) 00289 00290 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00291 Created: 19/1/95 00292 00293 Inputs: DlgRedrawInfo - If you happen to have one of these lying around, pass 00294 it in to save me having to find this out again. 00295 00296 Outputs: MiscInfo - will be filled in, ready to be passed to SG event handlers 00297 00298 Purpose: Sets up a MiscInfo structure, ready for use. 00299 00300 Scope: private (Internal shared code for SuperGallery) 00301 00302 ********************************************************************************************/ 00303 00304 void SuperGallery::FillInMiscInfo(SGMiscInfo *MiscInfo, ReDrawInfoType *DlgRedrawInfo) 00305 { 00306 // If the RedrawInfo was not passed in for us, go and get it for ourselves 00307 ReDrawInfoType TempDlgRedrawInfo; 00308 if (DlgRedrawInfo == NULL) 00309 { 00310 DlgRedrawInfo = &TempDlgRedrawInfo; 00311 GetKernelRenderedGadgetInfo(GetListGadgetID(), DlgRedrawInfo); 00312 } 00313 00314 // Fill in the MiscInfo 00315 MiscInfo->DisplayMode = DisplayMode; 00316 MiscInfo->PixelSize = 72000 / DlgRedrawInfo->Dpi; 00317 MiscInfo->MaxWidth = DlgRedrawInfo->dx; // Window/virtualsize width 00318 MiscInfo->WindowHeight = DlgRedrawInfo->dy; // Window height 00319 } 00320 00321 00322 00323 /******************************************************************************************** 00324 00325 > void SuperGallery::BroadcastEvent(SGEventType EventType, void *EventInfo, 00326 SGMiscInfo *MiscInfo = NULL) 00327 00328 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00329 Created: 19/1/95 00330 00331 Inputs: EventType - the type of the event to broadcast 00332 EventInfo - the information to pass in 'EventInfo' to all event handlers 00333 (FormatInfo/RedrawInfo/MouseInfo, etc, depending upon EventType) 00334 MiscInfo - the MiscInfo to pass to the event handlers. If this is passed in 00335 as NULL, a MiscInfo structure will be set up automatically and 00336 passed in (as MiscInfo must *always* be supplied) 00337 00338 Purpose: Passes the given event through the DisplayTree. 00339 00340 SeeAlso: SGDisplayNode::HandleEvent 00341 00342 ********************************************************************************************/ 00343 00344 void SuperGallery::BroadcastEvent(SGEventType EventType, void *EventInfo, 00345 SGMiscInfo *MiscInfo) 00346 { 00347 if (DisplayTree == NULL) 00348 return; 00349 00350 SGMiscInfo TheMiscInfo; 00351 00352 if (MiscInfo == NULL && IsVisible()) 00353 { 00354 FillInMiscInfo(&TheMiscInfo); 00355 MiscInfo = &TheMiscInfo; 00356 } 00357 00358 ERROR3IF(MiscInfo == NULL && (EventType != SGEVENT_THUMBMSG && EventType != SGEVENT_BGFLUSH), 00359 "Attempt to broadcast an event when the gallery is closed could be dangerous. Tell Jason"); 00360 00361 DisplayTree->HandleEvent(EventType, EventInfo, MiscInfo); 00362 } 00363 00364 00365 00366 /******************************************************************************************** 00367 00368 > virtual MsgResult SuperGallery::Message(Msg* Message) 00369 00370 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00371 Created: 21/10/94 00372 Inputs: Message - The message to handle 00373 00374 Purpose: A standard message handler, really. If you override this in a derived 00375 class, you must pass any unhandled event on to this base class method 00376 after handling the messages you are interested in. 00377 00378 SeeAlso: DialogOp::Message 00379 00380 ********************************************************************************************/ 00381 00382 MsgResult SuperGallery::Message(Msg* Message) 00383 { 00384 if (MESSAGE_IS_A(Message,DeathMsg)) // We must destroy the dialog if the application is dying 00385 { 00386 // Destroy the entire DisplayList (which should be empty by now), 00387 // just to be on the safe side, in case a derived gallery forgot to do it 00388 if (DisplayTree != NULL) 00389 { 00390 DisplayTree->DestroySubtree(); // Destroy the display tree, destructing all nodes 00391 delete DisplayTree; 00392 DisplayTree = NULL; 00393 } 00394 00395 // Ensure that all doc/view pointers for this Op are NULL to stop 00396 // 'FlushRedraw' access violations occurring. 00397 pOurDoc = NULL; 00398 pOurView = NULL; 00399 00400 End(); 00401 return(OK); 00402 } 00403 00404 00405 if ( Message->IsKindOf(CC_RUNTIME_CLASS(DialogMsg)) && 00406 ((DialogMsg*)Message)->DlgMsg == DIM_BAR_DEATH ) 00407 { 00408 DialogOp::Message(Message); 00409 return(OK); 00410 } 00411 00412 if (IS_OUR_DIALOG_MSG(Message)) 00413 { 00414 DialogMsg* Msg = (DialogMsg*)Message; 00415 00416 BOOL WasRightButton = FALSE; // What type of click was it (if any) 00417 // (allows code-sharing in the case statement) 00418 00419 switch (Msg->DlgMsg) 00420 { 00421 case DIM_CREATE: 00422 { 00423 String_32 name(CamResource::GetObjectName(DlgResID)); 00424 SetGalName(name); 00425 } 00426 break; 00427 00428 case DIM_CANCEL: // We're closing - close our owned dlgs 00429 CloseOwnedDialogs(); 00430 00431 // Ensure all items pending background redraws are flushed 00432 FlushBackgroundRedraws(); 00433 00434 // tell everyone the screen will be changing 00435 TRACEUSER( "Diccon", _T("Gallery closing\n")); 00436 BROADCAST_TO_ALL(ScreenChangeMsg()); 00437 break; 00438 00439 case DIM_MOUSEWHEEL_UP: 00440 { 00441 //MouseWheel Scrolled Upwards... 00442 TRACEUSER( "Matt", _T("SuperGallery::Message() Received MouseWheel UPWARDS Message!\n")); 00443 00444 ReDrawInfoType DlgRedrawInfo; 00445 GetKernelRenderedGadgetInfo(GetListGadgetID(), &DlgRedrawInfo); 00446 00447 // Make a SGMiscInfo with, well, MiscInfo in it... 00448 SGMiscInfo MiscInfo; 00449 FillInMiscInfo(&MiscInfo, &DlgRedrawInfo); 00450 00451 //Get the old scroll offset, adjust it accordingly and set it to be the current one... 00452 INT32 newScrollOffset = DisplayTree->GetScrollOffset() - (750 * 30); 00453 DisplayTree->SetScrollOffset(newScrollOffset, &MiscInfo); 00454 } 00455 break; 00456 00457 case DIM_MOUSEWHEEL_DOWN: 00458 { 00459 //MouseWheel Scrolled Downwards... 00460 TRACEUSER( "Matt", _T("SuperGallery::Message() Received MouseWheel DOWNWARDS Message!\n")); 00461 00462 ReDrawInfoType DlgRedrawInfo; 00463 GetKernelRenderedGadgetInfo(GetListGadgetID(), &DlgRedrawInfo); 00464 00465 // Make a SGMiscInfo with, well, MiscInfo in it... 00466 SGMiscInfo MiscInfo; 00467 FillInMiscInfo(&MiscInfo, &DlgRedrawInfo); 00468 00469 //Get the old scroll offset, adjust it accordingly and set it to be the current one... 00470 INT32 newScrollOffset = DisplayTree->GetScrollOffset() + (750 * 30); 00471 DisplayTree->SetScrollOffset(newScrollOffset, &MiscInfo); 00472 } 00473 break; 00474 00475 case DIM_RGT_BN_DOWN: 00476 WasRightButton = TRUE; 00477 // (Note: We treat a right click like a left click now. DIM_RGT_BN_UP is used 00478 // to pop up the menu when the button is released) 00479 00480 // Drop through to LFT_BN_DOWN handler... 00481 00482 case DIM_LFT_BN_DOWN: 00483 if ((Msg->GadgetID == GetListGadgetID()) && Msg->DlgMsgParam) 00484 { 00485 // Get our kernel-rendered-dlg info, and calculate our virtual coord space 00486 ReDrawInfoType *DlgRedrawInfo = (ReDrawInfoType*) Msg->DlgMsgParam; 00487 00488 // Determine where the mouse was clicked, within the virtual coord space 00489 SGMouseInfo ClickInfo; 00490 00491 // Was it a ctrl-click? (Adjust/right clicks now pop up the menu) 00492 ClickInfo.Adjust = KeyPress::IsGalleryCtrlPressed(); 00493 00494 // Was it a click to extend the selection? (shift-click) 00495 ClickInfo.Extend = KeyPress::IsGalleryShiftPressed(); 00496 00497 // Was it a pop-up-menu (right button) click? 00498 ClickInfo.MenuClick = WasRightButton; 00499 00500 // Is it the second installment in a double-click? 00501 ClickInfo.DoubleClick = FALSE; 00502 if (DblClickPending && !WasRightButton) 00503 { 00504 // Double-click Distance (millipoints). If the second click is more than this 00505 // distance away from the forst click point, it is not regarded as a dble click. 00506 const INT32 DblClickDist = 12000; // **** !!!! Read dbl-click-dist preference 00507 INT32 ClickDistX = ABS(LastClickPos.x - DlgRedrawInfo->pMousePos->x); 00508 INT32 ClickDistY = ABS(LastClickPos.y - DlgRedrawInfo->pMousePos->y); 00509 00510 if (ClickDistX <= DblClickDist && ClickDistY <= DblClickDist) 00511 { 00512 const INT32 DblClickTime = 400; // **** !!!! Read OS dbl-click time! 00513 00514 if (!LastClickTime.Elapsed(DblClickTime)) 00515 ClickInfo.DoubleClick= TRUE; 00516 } 00517 } 00518 LastClickPos = *(DlgRedrawInfo->pMousePos); // Remember last click position 00519 00520 if (ClickInfo.DoubleClick) 00521 DblClickPending = FALSE; // No longer pending double click 00522 else 00523 { 00524 DblClickPending = TRUE; // Double click is now pending 00525 LastClickTime.Sample(); // Start the "double-click timeout" timer 00526 } 00527 00528 ClickInfo.Position = *(DlgRedrawInfo->pMousePos); 00529 ConvertToVirtualCoords(DlgRedrawInfo, &ClickInfo.Position); 00530 00531 // And request that the tree decides what to do with the event 00532 BroadcastEvent(SGEVENT_MOUSECLICK, &ClickInfo); 00533 } 00534 break; 00535 00536 00537 case DIM_RGT_BN_UP: 00538 { 00539 // Give the gallery a chance to do something before popping up the context menu 00540 // At present, used by the bitmap gallery to ensure that the plug-ins have all 00541 // been parsed. 00542 PreContextMenu(); 00543 // Right button has been released - pop up a context-sensitive menu 00544 GalleryContextMenu *TheMenu = new GalleryContextMenu(SGMENU_OVERITEM, this); 00545 if (TheMenu != NULL) 00546 TheMenu->Show(); 00547 } 00548 break; 00549 00550 00551 case DIM_LFT_BN_CLICKED: 00552 { 00553 if (Msg->GadgetID == _R(IDC_GALLERY_NEW)) 00554 { 00555 ApplyAction(SGACTION_CREATE); 00556 } 00557 else if (Msg->GadgetID == _R(IDC_GALLERY_APPLY)) 00558 { 00559 // NB. changed to use Control key here, to be consistent with the 00560 // way Adjust works when clicking on items. 00561 if (KeyPress::IsGalleryCtrlPressed()) 00562 { 00563 // If the gallery doesn't respond to Adjust-click then try a plain 00564 // click instead. 00565 if (!ApplyAction(SGACTION_APPLYADJUST)) ApplyAction(SGACTION_APPLY); 00566 } 00567 else 00568 { 00569 ApplyAction(SGACTION_APPLY); 00570 } 00571 } 00572 else if (Msg->GadgetID == _R(IDC_GALLERY_REDEFINE)) 00573 { 00574 ApplyAction(SGACTION_REDEFINE); 00575 } 00576 else if (Msg->GadgetID == _R(IDC_GALLERY_EDIT)) 00577 { 00578 ApplyAction(SGACTION_EDIT); 00579 } 00580 else if (Msg->GadgetID == _R(IDC_GALLERY_DELETE)) 00581 { 00582 ApplyAction(SGACTION_DELETE); 00583 } 00584 else if (Msg->GadgetID == _R(IDC_GALLERY_MENU)) 00585 { 00586 // Pop up the options menu/dialogue 00587 // SGalleryOptionsDlg::InvokeDialog(this); 00588 GalleryContextMenu *TheMenu = new GalleryContextMenu(SGMENU_OPTIONS, this); 00589 if (TheMenu != NULL) 00590 TheMenu->Show(); 00591 } 00592 break; 00593 } 00594 case DIM_RGT_BN_CLICKED: 00595 if (Msg->GadgetID == _R(IDC_GALLERY_APPLY)) 00596 { 00597 if (!ApplyAction(SGACTION_APPLYADJUST)) 00598 ApplyAction(SGACTION_APPLY); 00599 } 00600 break; 00601 00602 00603 case DIM_REDRAW: 00604 if (Msg->GadgetID == _R(IDC_GALLERY_LISTBOX)) // Render the list box 00605 { 00606 RenderListBox((ReDrawInfoType*) Msg->DlgMsgParam); 00607 } 00608 break; 00609 00610 default: 00611 break; 00612 } 00613 } 00614 else if (MESSAGE_IS_A(Message, DocChangingMsg)) 00615 { 00616 DocChangingMsg *Msg = (DocChangingMsg *) Message; 00617 switch (Msg->State) 00618 { 00619 case DocChangingMsg::TITLECHANGED: 00620 if (DisplayTree != NULL && IsVisible()) 00621 { 00622 // If we have any 'categories' which represent this document, 00623 // ask them to redraw themselves to update their titles. 00624 SGDisplayNode *Category = 00625 DisplayTree->FindSubtree(this, Msg->pChangingDoc, NULL); 00626 00627 if (Category != NULL) 00628 Category->ForceRedrawOfMyself(); 00629 } 00630 break; 00631 00632 00633 case DocChangingMsg::ABOUTTODIE: // Document dying - remove from tree 00634 if (DisplayTree != NULL) 00635 { 00636 // If the gallery has a subtree for this document, we'll scrap it for 'em 00637 SGDisplayNode *Ptr = DisplayTree->FindSubtree(this, Msg->pChangingDoc, NULL); 00638 if (Ptr != NULL) 00639 { 00640 Ptr->DestroySubtree(); 00641 ForceRedrawOfList(); 00642 } 00643 } 00644 break; 00645 00646 00647 case DocChangingMsg::SELCHANGED: 00648 if (Msg->pNewDoc == NULL) 00649 { 00650 // There is no selected doc - this can only mean there are no docs 00651 // at all, so we had better shade the gallery 00652 ShadeGallery(TRUE); 00653 } 00654 break; 00655 00656 default: 00657 break; 00658 } 00659 } 00660 00661 else if (MESSAGE_IS_A(Message, DragMessage) && IsVisible() && DisplayTree != NULL) 00662 { 00663 // If a drag starting message comes around, pass it on to the tree 00664 DragMessage *Msg = (DragMessage *) Message; 00665 if (Msg->State == DragMessage::DRAGSTARTED) 00666 { 00667 BroadcastEvent(SGEVENT_DRAGSTARTED, (SGEventInfo *) Msg); 00668 00669 // And then call our virtual function to add a drag target (if appropriate) 00670 // for the entire gallery listbox. 00671 HandleDragStart(Msg); 00672 } 00673 } 00674 00675 else if (MESSAGE_IS_A(Message, ThumbMessage) && DisplayTree != NULL) 00676 { 00677 // If a library Thumb message comes around, pass it on to the tree 00678 // (do this even if the gallery is closed, as libraries may cache stuff even when closed) 00679 BroadcastEvent(SGEVENT_THUMBMSG, (SGEventInfo *) Message); 00680 } 00681 00682 // Pass the call down to the base class 00683 return(DialogOp::Message(Message)); 00684 00685 return OK; 00686 } 00687 00688 00689 00690 /******************************************************************************************** 00691 00692 > BOOL SuperGallery::Create(void) 00693 00694 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00695 Created: 21/10/94 00696 Returns: TRUE if the window was successfully created 00697 FALSE => ERROR2 00698 Purpose: The SuperGallery Create method 00699 This method has been overridden to de-specialize the DialogOp. 00700 00701 Notes: Before doing anything else, the PreCreate handler is called. 00702 Secondly, the InitMenuCommands() method is called to init any 00703 required gallery menu items. 00704 Then, the gallery window is created and initialised 00705 The last thing done is to invoke the PostCreate method 00706 (these upcalls should be overridden by derived classes to do stuff) 00707 00708 This finally calls SelectionHasChanged() to ensure the buttons etc 00709 are updated appropriately to the selection state. 00710 00711 ********************************************************************************************/ 00712 00713 BOOL SuperGallery::Create(void) 00714 { 00715 if (!DialogOp::Create()) 00716 return(FALSE); 00717 00718 // Call derived class PreCreate handler (to create display tree, usually) 00719 if (!PreCreate()) 00720 return(FALSE); 00721 00722 // Call the derived class Menu creation handler, to create any needed menu items 00723 if (!InitMenuCommands()) 00724 return(FALSE); 00725 00726 // Ensure any items pending background-redraws are 'flushed' 00727 FlushBackgroundRedraws(); 00728 00729 #ifndef EXCLUDE_FROM_XARALX 00730 PORTNOTE("galleries", "Removed docking stuff") 00731 // Bar initialisation and creation 00732 SetDockBarType(Dock); 00733 SetSlot(Slot); 00734 SetOffset(Offset); 00735 SetFloatingCPoint(FloatPos); 00736 #endif 00737 00738 // if (!DialogOp::Create()) 00739 // return(FALSE); 00740 00741 AmShaded = FALSE; 00742 00743 // Call derived class PostCreate handler 00744 if (!PostCreate()) 00745 return(FALSE); 00746 00747 SelectionHasChanged(); // Ensure we update appropriately for the selection state 00748 00749 return(TRUE); 00750 } 00751 00752 00753 00754 /******************************************************************************************** 00755 00756 > virtual void SuperGallery::SetVisibility(BOOL Open) 00757 00758 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00759 Created: 22/1/96 00760 Inputs: Open - if TRUE then open SuperGallery in its last pos if it is 00761 currently closed. 00762 if FALSE, it is closed 00763 00764 Purpose: Used by the tool bar customize system to open and close a tool bar. 00765 00766 SuperGallery overrides this virtual function so that it can be aware 00767 of when its window is closed/hidden, so that it may remove its owned 00768 dialogues (sort/search/properties). 00769 00770 It always calls the base class in order to show/hide the gallery 00771 00772 NOTE THAT THIS CAN DELETE THE OBJECT CONCERNED! 00773 00774 ********************************************************************************************/ 00775 00776 void SuperGallery::SetVisibility(BOOL Open) 00777 { 00778 if (!Open) 00779 { 00780 // If we're being hidden, make sure that any owned dialogues are closed 00781 CloseOwnedDialogs(); 00782 } 00783 00784 // Now call the base class to show/hide ourselves 00785 DialogOp::SetVisibility(Open); 00786 if (!Open) 00787 End(); // Return quick, this deletes the super gallery 00788 } 00789 00790 00791 /******************************************************************************************** 00792 00793 > virtual void SuperGallery::CloseOwnedDialogs(void) 00794 00795 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> 00796 Created: 05/03/97 00797 00798 Purpose: Checks and closes the various dialogs which can be owned by galleries. 00799 00800 SeeAlso: SuperGallery::SetVisibility, SuperGallery::~SuperGallery() 00801 SuperGallery::Message(Msg* Message) 00802 00803 ********************************************************************************************/ 00804 00805 void SuperGallery::CloseOwnedDialogs(void) 00806 { 00807 if (CurrentOptionsDlg != NULL) 00808 { 00809 CurrentOptionsDlg->Close(); 00810 CurrentOptionsDlg->End(); 00811 } 00812 00813 if (CurrentSortDlg != NULL) 00814 { 00815 CurrentSortDlg->Close(); 00816 CurrentSortDlg->End(); 00817 } 00818 00819 if (CurrentSearchDlg != NULL) 00820 { 00821 CurrentSearchDlg->Close(); 00822 CurrentSearchDlg->End(); 00823 } 00824 00825 PORTNOTE("dialogs", "Removed CurrentLinePropertiesDlg from SuperGallery::CloseOwnedDialogs(void)") 00826 #ifndef EXCLUDE_FROM_XARALX 00827 if (CurrentLinePropertiesDlg != NULL) 00828 { 00829 CurrentLinePropertiesDlg->Close(); 00830 CurrentLinePropertiesDlg->End(); 00831 } 00832 #endif 00833 } 00834 00835 /******************************************************************************************** 00836 00837 > virtual BOOL SuperGallery::PreCreate(void) 00838 00839 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00840 Created: 24/10/94 00841 Returns: TRUE if the gallery was successfully initialised 00842 00843 Purpose: A call to be overridden by the derived class. 00844 This is called BEFORE the SuperGallery::Create function tries to create 00845 the gallery window. 00846 Derived galleries then initialise any unintialised data, and return 00847 TRUE if it is safe to continue creating the gallery window. 00848 00849 Notes: Generally speaking, most initialisation code should go into the post create 00850 handler method. Override this method with care. 00851 00852 SeeAlso: SuperGallery::PostCreate 00853 00854 ********************************************************************************************/ 00855 00856 BOOL SuperGallery::PreCreate(void) 00857 { 00858 return(TRUE); 00859 } 00860 00861 00862 00863 /******************************************************************************************** 00864 00865 > virtual BOOL SuperGallery::PostCreate(void) 00866 00867 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00868 Created: 24/10/94 00869 Returns: TRUE if the gallery was successfully initialised 00870 Purpose: A call to be overridden by the derived class. 00871 This is called AFTER the SuperGallery::Create function has succeeded. 00872 Derived galleries can then initialise any unintialised data, and return 00873 TRUE if it is safe to open the gallery window. 00874 00875 SeeAlso: SuperGallery::PreCreate 00876 00877 ********************************************************************************************/ 00878 00879 BOOL SuperGallery::PostCreate(void) 00880 { 00881 return(TRUE); 00882 } 00883 00884 00885 00886 /******************************************************************************************** 00887 00888 > void SuperGallery::ShadeGallery(BOOL ShadeIt) 00889 00890 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00891 Created: 18/1/95 00892 00893 Inputs: ShadeIt - TRUE to shade, FALSE to un-shade, the gallery 00894 00895 Purpose: Shades (disables) the SuperGallery window. 00896 This calls the DoShadeGallery upcall to allow derived classes to take 00897 special action for any extra controls they may own, etc. 00898 00899 If un-shading the gallery, it also calls SelectionHasChanged method to 00900 ensure that the buttons are in an appropriate state for the selection. 00901 00902 Notes: If the gallery is already in the requested state, or if it is closed 00903 (not visible on screen) then nothing happens (other than that the shaded 00904 flag is updated to reflect the desired state) 00905 00906 SeeAlso: SuperGallery::DoShadeGallery; SuperGallery::SelectionHasChanged 00907 00908 ********************************************************************************************/ 00909 00910 void SuperGallery::ShadeGallery(BOOL ShadeIt) 00911 { 00912 if (AmShaded != ShadeIt && IsVisible()) 00913 { 00914 EnableGadget(_R(IDC_GALLERY_APPLY), !ShadeIt); 00915 EnableGadget(_R(IDC_GALLERY_NEW), !ShadeIt); 00916 EnableGadget(_R(IDC_GALLERY_DELETE), !ShadeIt); 00917 EnableGadget(_R(IDC_GALLERY_REDEFINE), !ShadeIt); 00918 EnableGadget(_R(IDC_GALLERY_EDIT), !ShadeIt); 00919 // EnableGadget(_R(IDC_GALLERY_UNDO), !ShadeIt); 00920 EnableGadget(_R(IDC_GALLERY_MENU), !ShadeIt); 00921 EnableGadget(_R(IDC_GALLERY_NAME), !ShadeIt); 00922 00923 DoShadeGallery(ShadeIt); 00924 } 00925 00926 AmShaded = ShadeIt; 00927 00928 if (!AmShaded) // If unshading, ensure the buttons are updated 00929 SelectionHasChanged(); // to reflect the new selection state 00930 } 00931 00932 00933 00934 /******************************************************************************************** 00935 00936 > virtual void SuperGallery::DoShadeGallery(BOOL ShadeIt); 00937 00938 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00939 Created: 18/1/95 00940 00941 Inputs: ShadeIt - TRUE to shade, FALSE to un-shade, the gallery 00942 00943 Purpose: Shades (disables) the SuperGallery window. 00944 This calls the DoShadeGallery upcall to allow derived classes to take 00945 special action for any extra controls they may own, etc. 00946 00947 Notes: This base class method does nothing - it is expected to be overridden if 00948 derived classes need to do anything when shading state changes 00949 00950 SeeAlso: SuperGallery::DoShadeGallery 00951 00952 ********************************************************************************************/ 00953 00954 void SuperGallery::DoShadeGallery(BOOL ShadeIt) 00955 { 00956 // The base class does nothing 00957 } 00958 00959 00960 00961 /******************************************************************************************** 00962 00963 > virtual void SuperGallery::HandleDragStart(DragMessage *DragMsg) 00964 00965 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00966 Created: 14/3/95 00967 00968 Inputs: DragMsg - The DRAGSTARTED message that we've just recieved, indicating 00969 the type of drag which is just starting. 00970 00971 Purpose: Checks a DragMessage to see if it is a gallery list-drag. If so, it 00972 adds a new drag target to handle drops on the gallery list box. 00973 00974 Notes: This method should be overridden by derived galleries to: 00975 a) Stop the gallery from allowing recieving of these drags, or 00976 b) Add handlers for specific drag types you're interested in - e.g. 00977 the colour gallery will use less generic colour drags to handle 00978 gallery reorganisation, so that you can also drag colours out of the 00979 gallery. 00980 00981 ********************************************************************************************/ 00982 00983 void SuperGallery::HandleDragStart(DragMessage *DragMsg) 00984 { 00985 // If this is a gallery list-reorganising drag which originated from this gallery, 00986 // then create a target for the gallery listbox. 00987 if (DragMsg->pInfo->IsKindOf(CC_RUNTIME_CLASS(SGListDragInfo)) && 00988 ((SGListDragInfo *)DragMsg->pInfo)->GetParentGallery() == this) 00989 { 00990 // Note this sort of auto-attaches it seems - AMB 00991 /*SGListDragTarget *NewTarget = */new SGListDragTarget(this, GetListGadgetID()); 00992 } 00993 } 00994 00995 00996 00997 /******************************************************************************************** 00998 00999 > virtual BOOL SuperGallery::ApplyAction(SGActionType Action) 01000 01001 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01002 Created: 18/1/95 01003 01004 Inputs: Action - Indicates what action to apply 01005 01006 Returns FALSE (Derived classes will return TRUE to indicate successful handling 01007 of the action, or FALSE to indicate failure) 01008 01009 Purpose: Applies certain conventional gallery actions (usually associated with 01010 gallery buttons, for new, edit, delete, etc) 01011 01012 Notes: This base-class method should be overridden by derived classes. It 01013 does nothing by default, and returns FALSE. 01014 01015 SeeAlso: SGActionType 01016 01017 ********************************************************************************************/ 01018 01019 BOOL SuperGallery::ApplyAction(SGActionType Action) 01020 { 01021 return(FALSE); 01022 } 01023 01024 01025 01026 /******************************************************************************************** 01027 01028 > static INT32 __cdecl SuperGallery::SortComparator(const void *Item1, const void *Item2) 01029 01030 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01031 Created: 10/4/95 01032 01033 Inputs: Item1, Item2 - the display nodes to be compared 01034 01035 Returns: a negative, zero, or positive result of comparing the items with the 01036 current gallery multi-key sort mode. 01037 01038 Purpose: 'qsort' comparator function, used when quicksorting the display list 01039 01040 Notes: Relies on the static var. 'CurrentSortGallery' to contain a pointer to 01041 the gallery which requested this sort. 01042 01043 SeeAlso: SuperGallery::ApplySortNow 01044 01045 ********************************************************************************************/ 01046 01047 INT32 __cdecl SuperGallery::SortComparator(const void *Item1, const void *Item2) 01048 { 01049 SGDisplayNode *Node1 = *((SGDisplayNode **)Item1); 01050 SGDisplayNode *Node2 = *((SGDisplayNode **)Item2); 01051 01052 INT32 Result = Node1->CompareTo(Node2, CurrentSortGallery->SortKeys[0].SortKey); 01053 if (CurrentSortGallery->SortKeys[0].Reversed) 01054 Result = -Result; 01055 01056 if (Result == 0) 01057 { 01058 Result = Node1->CompareTo(Node2, CurrentSortGallery->SortKeys[1].SortKey); 01059 if (CurrentSortGallery->SortKeys[1].Reversed) 01060 Result = -Result; 01061 } 01062 01063 return(Result); 01064 } 01065 01066 01067 01068 /******************************************************************************************** 01069 01070 > virtual void SuperGallery::ApplySortNow(BOOL ApplyToEntireList) 01071 01072 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01073 Created: 10/4/95 01074 01075 Inputs: ApplyToEntireList - TRUE to sort the entire DisplayList, 01076 FALSE to sort only groups which contain a selection 01077 01078 Purpose: Applies the current gallery sort mode (member array SortKeys) to the 01079 display list. 01080 01081 SeeAlso: SuperGallery::SortComparator; ::qsort 01082 01083 ********************************************************************************************/ 01084 01085 void SuperGallery::ApplySortNow(BOOL ApplyToEntireList) 01086 { 01087 if (SortKeys[0].SortKey == 0 || DisplayTree == NULL) 01088 return; 01089 01090 CurrentSortGallery = this; 01091 01092 SGDisplayNode *CurrentGroup = DisplayTree->GetChild(); 01093 if (CurrentGroup == NULL) // Nothing to sort 01094 return; 01095 01096 SGDisplayNode *Ptr = CurrentGroup; 01097 01098 // Pre-run progress indicator 01099 String_64 ProgMsg(_R(IDS_GALLERY_PREPARE_FOR_SORT)); 01100 BeginSlowJob(-1, FALSE, &ProgMsg); 01101 01102 // For library galleries we need to set the Quiet button status ready to un-supress errors 01103 SetQuietStatus(FALSE); 01104 01105 // Count the number of available items to sort 01106 BOOL HasSelection = FALSE; 01107 INT32 NumItemsToSort = 0; 01108 while (Ptr != NULL) 01109 { 01110 if(ApplyToEntireList || ((SGDisplayGroup *)Ptr)->IsSelected()) 01111 if(((SGDisplayGroup *)Ptr)->IsVirtualised()) 01112 ((SGDisplayGroup *)Ptr)->DeVirtualise(); 01113 01114 if (ApplyToEntireList || ((SGDisplayGroup *)Ptr)->FindNextSelectedItem(NULL) != NULL) 01115 { 01116 SGDisplayNode *Item = Ptr->GetChild(); // Count number of items to sort in this group 01117 INT32 ItemsInThisGroup = 0; 01118 while (Item != NULL) 01119 { 01120 ItemsInThisGroup++; 01121 if (Item->Flags.Selected) 01122 HasSelection = TRUE; 01123 Item = Item->GetNext(); 01124 } 01125 01126 if (ItemsInThisGroup > 1 && (ApplyToEntireList || HasSelection)) 01127 NumItemsToSort += ItemsInThisGroup; 01128 } 01129 Ptr = Ptr->GetNext(); 01130 } 01131 01132 EndSlowJob(); 01133 01134 // If there is no point in trying to sort, abort now 01135 if (NumItemsToSort < 2) 01136 return; 01137 01138 // Start progress indicators, with a percentage based upon the number of items. 01139 // We will update twice for each group (after qsort and shuffle-items stages) 01140 String_64 Description(_R(IDS_SGOPTS_SORTING)); 01141 BeginSlowJob(NumItemsToSort * 2, FALSE, &Description); 01142 NumItemsToSort = 0; 01143 01144 INT32 NumItems; 01145 INT32 i; 01146 BOOL GroupHasChanged = FALSE; 01147 01148 while (CurrentGroup != NULL) 01149 { 01150 // Don't sort virtualised-out groups ! (they should have all been devirtualised before) 01151 if(!((SGDisplayGroup *)CurrentGroup)->IsVirtualised()) 01152 { 01153 HasSelection = FALSE; 01154 Ptr = CurrentGroup->GetChild(); 01155 ERROR3IF(Ptr != NULL && !Ptr->IsKindOf(CC_RUNTIME_CLASS(SGDisplayItem)), 01156 "Sort hasn't found items! Heinous failure imminent!" ); 01157 // Count the number of items we have to sort 01158 NumItems = 0; 01159 while (Ptr != NULL) 01160 { 01161 NumItems++; 01162 if (Ptr->Flags.Selected) 01163 HasSelection = TRUE; 01164 Ptr = Ptr->GetNext(); 01165 } 01166 01167 // If there are 2 or more items, and we are either applying to all groups, or this 01168 // group contains selected item(s), then we will sort it.. 01169 if (NumItems > 1 && (ApplyToEntireList || HasSelection)) 01170 { 01171 // Get memory for an array of pointers to these items 01172 SGDisplayNode **SortArray = (SGDisplayNode **)CCMalloc(NumItems * sizeof(SGDisplayNode *)); 01173 if (SortArray == NULL) 01174 { 01175 CurrentSortGallery = NULL; 01176 InvalidateCachedFormat(); 01177 EndSlowJob(); 01178 InformError(); 01179 return; 01180 } 01181 01182 // Fill in the array with pointers to display items to sort 01183 i = 0; 01184 Ptr = CurrentGroup->GetChild(); 01185 while (Ptr != NULL) 01186 { 01187 SortArray[i++] = Ptr; 01188 Ptr = Ptr->GetNext(); 01189 } 01190 01191 // Sort the array of pointers 01192 qsort(SortArray, NumItems, sizeof(SGDisplayNode *), SuperGallery::SortComparator); 01193 01194 NumItemsToSort += NumItems; 01195 if (!ContinueSlowJob(NumItemsToSort)) // Update percentage complete for the number of items processed 01196 { 01197 // User has cancelled by pressing escape 01198 CCFree(SortArray); 01199 break; 01200 } 01201 01202 01203 GroupHasChanged = FALSE; 01204 01205 // Now, take the sorted array, and rearrange the display items to be in that order 01206 // Special case the first item 01207 if (SortArray[0]->GetPrevious() != NULL) 01208 { 01209 SortArray[1]->MoveBefore(SortArray[0]); 01210 GroupHasChanged =