00001 // $Id: dropdown.cpp 1412 2006-07-05 19:53:47Z 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 00099 // dropdown.cpp - Drop-down list base class 00100 00101 // >>>> See O:\camelot\docs\howtouse\DropDowns.doc for details of use <<<< 00102 00103 /* 00104 */ 00105 00106 00107 //----------------------------------------------------------------------------------------- 00108 // Include files 00109 00110 #include "camtypes.h" 00111 00112 #include "camelot.h" 00113 #include "griddropdown.h" 00114 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 #include "palman.h" 00116 00117 00118 //----------------------------------------------------------------------------------------- 00119 // Implementation of dynamic classes 00120 00121 00122 //----------------------------------------------------------------------------------------- 00123 // This must be defined AFTER all CC_IMPLEMENT_DYNCREATE calls 00124 #define new CAM_DEBUG_NEW 00125 00126 00127 //----------------------------------------------------------------------------------------- 00128 // Statics 00129 00130 List CGridDropDown::CurrentDropDowns; 00131 00132 wxCamGridPopup::wxCamGridPopup(CGridDropDown* pDropDown, wxGridCombo* pCombo) : 00133 wxGridComboPopup(pCombo) 00134 { 00135 m_pDropDown = pDropDown; 00136 } 00137 00138 wxCamGridPopup::~wxCamGridPopup() 00139 { 00140 } 00141 00142 /****************************************************************************** 00143 Function : wxCamGridPopup::DrawItem 00144 Author : Mikhail Tatarnikov 00145 Purpose : Draws an item. 00146 Returns : void 00147 Exceptions: 00148 Parameters: [in] wxDC& dc - the device context to draw to; 00149 [in] wxRect& rect - the area of the item; 00150 [in] INT32 iItem - item index; 00151 [in] INT32 iFlags - additional flags (selected, highlighted, ...) 00152 Notes : Delegates the call to the control class. 00153 ******************************************************************************/ 00154 void wxCamGridPopup::DrawItem(wxDC& dc, const wxRect& rect, int /* TYPENOTE: Correct */ iItem, INT32 iFlags) 00155 { 00156 if (m_pDropDown) 00157 m_pDropDown->DrawItem(dc, rect, iItem, iFlags); 00158 } 00159 00160 00161 00162 00163 00164 00165 00166 CGridDropDown::CGridDropDown() 00167 { 00168 m_widParentDlg = NULL; 00169 m_pPopup = NULL; 00170 m_gidParentGadget = 0; 00171 m_bInitialised = FALSE; 00172 } 00173 00174 00175 00176 CGridDropDown::~CGridDropDown() 00177 { 00178 if (m_bInitialised) 00179 { 00180 // Do any deinit here 00181 Init(NULL, 0); 00182 } 00183 } 00184 00185 /****************************************************************************** 00186 Function : CGridDropDown::GetBox 00187 Author : Mikhail Tatarnikov 00188 Purpose : Helper function to get the control gadget 00189 Returns : wxGridCombo* - the combo cobtrol the object controls. 00190 Exceptions: 00191 Parameters: None 00192 Notes : 00193 ******************************************************************************/ 00194 wxGridCombo* CGridDropDown::GetBox() 00195 { 00196 wxWindow* pGadget = DialogManager::GetGadget(m_widParentDlg, m_gidParentGadget); 00197 ERROR2IF(!pGadget || !pGadget->IsKindOf(CLASSINFO(wxGridCombo)), NULL, "Bad GridDropdown Gadget"); 00198 return (wxGridCombo*)pGadget; 00199 } 00200 00201 00202 /****************************************************************************** 00203 Function : CGridDropDown::Init 00204 Author : Mikhail Tatarnikov 00205 Purpose : Intialization of the control 00206 Returns : BOOL - 00207 Exceptions: 00208 Parameters: [in] CWindowID Window - window the control resides; 00209 [in] CGadgetID Gadget - control ID. 00210 Notes : 00211 ******************************************************************************/ 00212 BOOL CGridDropDown::Init(CWindowID Window, CGadgetID Gadget) 00213 { 00214 if (Window) 00215 { 00216 wxWindow* pGadget = DialogManager::GetGadget(Window, Gadget); 00217 if (pGadget && pGadget->IsKindOf(CLASSINFO(wxGridCombo))) 00218 { 00219 m_widParentDlg = Window; 00220 m_gidParentGadget = Gadget; 00221 00222 if (!m_bInitialised) // Only ever add myself to the list once 00223 { 00224 m_pPopup = new wxCamGridPopup(this, GetBox()); 00225 ERROR2IF(!m_pPopup, FALSE, "Could not get new list popup"); 00226 ((wxGridCombo*)pGadget)->SetPopupControl(m_pPopup); 00227 CurrentDropDowns.AddHead(this); 00228 } 00229 00230 00231 m_bInitialised = TRUE; 00232 return(TRUE); 00233 } 00234 ERROR3("CGridDropDown::Init failed - illegal Gadget"); 00235 return(FALSE); 00236 } 00237 else 00238 { 00239 // release all memory 00240 KillList(); 00241 Clear(); 00242 m_widParentDlg = NULL; 00243 m_gidParentGadget=0; 00244 m_bInitialised=FALSE; 00245 CurrentDropDowns.RemoveItem(this); 00246 return TRUE; 00247 } 00248 } 00249 00250 /******************************************************************************************** 00251 00252 > static void CGridDropDown::KillDropDownsByWindow(CWindowID Window) 00253 00254 Author: Alex Bligh <alex@alex.org.uk> 00255 Date: 15/05/2005 00256 00257 Purpose: Kills all the dropdowns associated with a particular window 00258 This is called when that window is dying. We can't delete the dropdowns 00259 but we can deinit them so they won't cause anyone eny hassle. 00260 00261 ********************************************************************************************/ 00262 void CGridDropDown::KillDropDownsByWindow(CWindowID Window) 00263 { 00264 // First kill any associated with this window 00265 CGridDropDown* Ptr = (CGridDropDown*) CurrentDropDowns.GetHead(); 00266 while (Ptr != NULL) 00267 { 00268 CGridDropDown* Next = (CGridDropDown*) CurrentDropDowns.GetNext(Ptr); // as we may remove this item from the list 00269 if (Ptr->m_bInitialised && (Ptr->m_widParentDlg == Window)) 00270 Ptr->Init(NULL, 0); 00271 Ptr = Next; 00272 } 00273 00274 // Now process children if any 00275 wxWindowList::Node * pNode = Window->GetChildren().GetFirst(); 00276 while (pNode) 00277 { 00278 KillDropDownsByWindow(pNode->GetData()); 00279 pNode = pNode->GetNext(); 00280 } 00281 return; 00282 } 00283 00284 00285 00286 /****************************************************************************** 00287 Function : CGridDropDown::SetListRedraw 00288 Author : Mikhail Tatarnikov 00289 Purpose : Pause/resume control drawing. 00290 Returns : void 00291 Exceptions: 00292 Parameters: [in] BOOL Enable - TRUE for enabling redraw, FALSE otherwise. 00293 Notes : 00294 ******************************************************************************/ 00295 void CGridDropDown::SetListRedraw(BOOL Enable) 00296 { 00297 wxGridCombo* pGadget = GetBox(); 00298 if (!pGadget) 00299 return; 00300 if (Enable) 00301 pGadget->Thaw(); 00302 else 00303 pGadget->Freeze(); 00304 } 00305 00306 00307 00308 /****************************************************************************** 00309 Function : CGridDropDown::AddItem 00310 Author : Mikhail Tatarnikov 00311 Purpose : Adds a new item 00312 Returns : void 00313 Exceptions: 00314 Parameters: [in] CGridComboUserData* pItemData - new data to associate with the item. 00315 Notes : 00316 ******************************************************************************/ 00317 void CGridDropDown::AddItem(CGridComboUserData* pItemData) 00318 { 00319 wxGridCombo* pGadget = GetBox(); 00320 pGadget->AddItem(pItemData); 00321 } 00322 00323 /****************************************************************************** 00324 Function : CGridDropDown::Clear 00325 Author : Mikhail Tatarnikov 00326 Purpose : Remove all items from the control 00327 Returns : void 00328 Exceptions: 00329 Parameters: 00330 Notes : 00331 ******************************************************************************/ 00332 void CGridDropDown::Clear() 00333 { 00334 wxGridCombo* pGadget = GetBox(); 00335 if (!pGadget) 00336 return; 00337 pGadget->Clear(); 00338 } 00339 00340 00341 /****************************************************************************** 00342 Function : CGridDropDown::DeleteItem 00343 Author : Mikhail Tatarnikov 00344 Purpose : Deletes a specific item. 00345 Returns : void 00346 Exceptions: 00347 Parameters: [in] INT32 index - item to delete. 00348 Notes : 00349 ******************************************************************************/ 00350 void CGridDropDown::DeleteItem(INT32 index) 00351 { 00352 } 00353 00354 00355 /****************************************************************************** 00356 Function : CGridDropDown::SetSelected 00357 Author : Mikhail Tatarnikov 00358 Purpose : Select an item. 00359 Returns : void 00360 Exceptions: 00361 Parameters: [in] INT32 iSelectedIndex - an item to select. 00362 Notes : 00363 ******************************************************************************/ 00364 void CGridDropDown::SetSelected(INT32 iSelectedIndex) 00365 { 00366 wxGridCombo* pGadget = GetBox(); 00367 pGadget->SetSelected(iSelectedIndex); 00368 } 00369 00370 /****************************************************************************** 00371 Function : CGridDropDown::GetSelected 00372 Author : Mikhail Tatarnikov 00373 Purpose : Gets the selected item. 00374 Returns : INT32 - the item selected, -1 if none. 00375 Exceptions: 00376 Parameters: None 00377 Notes : 00378 ******************************************************************************/ 00379 INT32 CGridDropDown::GetSelected() 00380 { 00381 wxGridCombo* pGadget = GetBox(); 00382 return pGadget->GetSelected(); 00383 } 00384 00385 00386 /****************************************************************************** 00387 Function : CGridDropDown::GetItemData 00388 Author : Mikhail Tatarnikov 00389 Purpose : Obtains the user data associated with the item. 00390 Returns : CGridComboUserData* - the user data for the item. 00391 Exceptions: 00392 Parameters: [in] INT32 iItem - item to obtain the user data for. 00393 Notes : 00394 ******************************************************************************/ 00395 CGridComboUserData* CGridDropDown::GetItemData(INT32 iItem) 00396 { 00397 wxGridCombo* pGadget = GetBox(); 00398 return pGadget->GetUserData(iItem); 00399 } 00400 00401 00402 /****************************************************************************** 00403 Function : CGridDropDown::GetItemsNum 00404 Author : Mikhail Tatarnikov 00405 Purpose : Gets the number of items 00406 Returns : INT32 - the number of items in the control. 00407 Exceptions: 00408 Parameters: None 00409 Notes : 00410 ******************************************************************************/ 00411 INT32 CGridDropDown::GetItemsNum() 00412 { 00413 wxGridCombo* pGadget = GetBox(); 00414 return pGadget->GetItemsNum(); 00415 } 00416 00417 00418 /****************************************************************************** 00419 Function : CGridDropDown::SetColumns 00420 Author : Mikhail Tatarnikov 00421 Purpose : Sets the number of column to display in the popup 00422 Returns : void 00423 Exceptions: 00424 Parameters: [in] INT32 iColumns - column number to display. 00425 Notes : 00426 ******************************************************************************/ 00427 void CGridDropDown::SetColumns(INT32 iColumns) 00428 { 00429 wxGridCombo* pGadget = GetBox(); 00430 pGadget->SetColumns(iColumns); 00431 } 00432 00433 00434 /****************************************************************************** 00435 Function : CGridDropDown::DrawShadedRect 00436 Author : Mikhail Tatarnikov 00437 Purpose : A helper function to draw a shaded box 00438 Returns : void 00439 Exceptions: 00440 Parameters: [in] wxDC& dc - device context to draw to; 00441 [in] const wxRect& rect - box to draw; 00442 [in] const wxPen& pen1 - pen to draw top-left sides; 00443 [in] const wxPen& pen2 - pen to draw bottom-right sides; 00444 Notes : 00445 ******************************************************************************/ 00446 void CGridDropDown::DrawShadedRect(wxDC& dc, const wxRect& rect, const wxPen& pen1, const wxPen& pen2) 00447 { 00448 // draw the rectangle 00449 dc.SetPen(pen1); 00450 dc.DrawLine(rect.GetLeft(), rect.GetTop(), 00451 rect.GetLeft(), rect.GetBottom()); 00452 dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), 00453 rect.GetRight(), rect.GetTop()); 00454 dc.SetPen(pen2); 00455 dc.DrawLine(rect.GetRight(), rect.GetTop(), 00456 rect.GetRight(), rect.GetBottom()); 00457 dc.DrawLine(rect.GetLeft(), rect.GetBottom(), 00458 rect.GetRight() + 1, rect.GetBottom()); 00459 00460 } 00461 00462 /****************************************************************************** 00463 Function : CGridDropDown::SetItemSize 00464 Author : Mikhail Tatarnikov 00465 Purpose : Sets the size of items 00466 Returns : void 00467 Exceptions: 00468 Parameters: [in] wxSize szItem - items size. 00469 Notes : 00470 ******************************************************************************/ 00471 void CGridDropDown::SetItemSize(wxSize szItem) 00472 { 00473 wxGridCombo* pGadget = GetBox(); 00474 pGadget->SetItemSize(szItem); 00475 } 00476 00477 00478 /****************************************************************************** 00479 Function : CGridDropDown::GetItemSize 00480 Author : Mikhail Tatarnikov 00481 Purpose : Obtains items size. 00482 Returns : wxSize - the items size. 00483 Exceptions: 00484 Parameters: None 00485 Notes : 00486 ******************************************************************************/ 00487 wxSize CGridDropDown::GetItemSize() 00488 { 00489 wxGridCombo* pGadget = GetBox(); 00490 return pGadget->GetItemSize(); 00491 } 00492 00493 00494 /****************************************************************************** 00495 Function : CGridDropDown::DrawItem 00496 Author : Mikhail Tatarnikov 00497 Purpose : Draws an item 00498 Returns : void 00499 Exceptions: 00500 Parameters: [in] wxDC& dc - the device context to draw to; 00501 [in] wxRect& rect - the area of the item; 00502 [in] int iItem - item index; TYPENOTE: Correct 00503 [in] int iFlags - additional flags (selected, highlighted, ...) TYPENOTE: Correct 00504 Notes : 00505 ******************************************************************************/ 00506 void CGridDropDown::DrawItem(wxDC& dc, const wxRect& rect, INT32 iItem, INT32 iFlags) 00507 { 00508 // Erase the background first. 00509 static wxPen penBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); 00510 static wxBrush brBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); 00511 00512 dc.SetPen(penBackground); 00513 dc.SetBrush(brBackground); 00514 00515 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); 00516 00517 dc.SetBrush(wxNullBrush); 00518 dc.SetPen(wxNullPen); 00519 00520 // Check if we have a valid item and should to continue 00521 // drawing. 00522 if (iItem >= GetItemsNum()) 00523 return; 00524 00525 wxRect rcCore = PreDrawItem(dc, rect, iItem, iFlags); 00526 00527 DrawItemCore(dc, rcCore, iItem, iFlags); 00528 00529 // Post-draw the item. 00530 PostDrawItem(dc, rect, iItem, iFlags); 00531 } 00532 00533 00534 /****************************************************************************** 00535 Function : CGridDropDown::PreDrawItem 00536 Author : Mikhail Tatarnikov 00537 Purpose : Predraws an item (e.g. erases background) 00538 Returns : wxRect - the area where the item should be drawn. 00539 Exceptions: 00540 Parameters: [in] wxDC& dc - the device context to draw to; 00541 [in] wxRect& rect - the area of the item; 00542 [in] INT32 iItem - item index; 00543 [in] INT32 iFlags - additional flags (selected, highlighted, ...) 00544 Notes : The return rect specifies where the item should be drawn. It can be smaller 00545 if we draw a frame and want the item itself to be drawn inside this frame. 00546 ******************************************************************************/ 00547 wxRect CGridDropDown::PreDrawItem(wxDC& dc, const wxRect& rect, INT32 iItem, INT32 iFlags) 00548 { 00549 // Shouldn't do anything if the combobox itself is drawn. 00550 if (iFlags & wxGridComboPopup::keComboControl) 00551 return rect; 00552 00553 wxRect rcRect = rect; 00554 00555 static wxPen penDarkGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW)); 00556 static wxPen penHighlight(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT)); 00557 00558 // Depending on whether the 00559 if (iFlags & wxGridComboPopup::keHighlight) 00560 DrawShadedRect(dc, rect, penDarkGrey, penHighlight); 00561 else 00562 DrawShadedRect(dc, rect, penHighlight, penDarkGrey); 00563 00564 00565 // Adjust the drawing rectangle - we want the other painting to be 00566 // done inside our 3d rectangle. 00567 rcRect.Deflate(1); 00568 00569 return rcRect; 00570 } 00571 00572 /****************************************************************************** 00573 Function : CGridDropDown::PostDrawItem 00574 Author : Mikhail Tatarnikov 00575 Purpose : Post-draws item 00576 Returns : void 00577 Exceptions: 00578 Parameters: [in] wxDC& dc - the device context to draw to; 00579 [in] wxRect& rect - the area of the item; 00580 [in] INT32 iItem - item index; 00581 [in] INT32 iFlags - additional flags (selected, highlighted, ...) 00582 Notes : Here we highlight the selected item. 00583 ******************************************************************************/ 00584 void CGridDropDown::PostDrawItem(wxDC& dc, const wxRect& rect, INT32 iItem, INT32 iFlags) 00585 { 00586 // Shouldn't do anything if the combobox itself is drawn - no reason 00587 // to draw selection in the combobox itslef. 00588 if (iFlags & wxGridComboPopup::keComboControl) 00589 return; 00590 00591 // Check whether we have to highligt the selected item or not. 00592 if ((iFlags & wxGridComboPopup::keSelected) == 0) 00593 return; 00594 00595 dc.SetPen(*wxRED_PEN); 00596 dc.SetBrush(*wxTRANSPARENT_BRUSH); 00597 00598 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); 00599 00600 dc.SetBrush(wxNullBrush); 00601 dc.SetPen(wxNullPen); 00602 } 00603 00604