[Date Prev][Date Next][Thread Prev][Thread Next][Thread Index]

[XaraXtreme-commits] Commit Complete



Commit by  : alex
Repository : xara
Revision   : 1703
Date       : Thu Aug 17 10:22:54 BST 2006

Changed paths:
   A /Trunk/XaraLX/wxXtra/gridcombo.cpp
   A /Trunk/XaraLX/wxXtra/gridcombo.h
   A /Trunk/XaraLX/wxXtra/xh_gridcombo.cpp
   A /Trunk/XaraLX/wxXtra/xh_gridcombo.h

Add files I forgot


Diff:
Index: Trunk/XaraLX/wxXtra/gridcombo.cpp
===================================================================
--- Trunk/XaraLX/wxXtra/gridcombo.cpp	(revision 0)
+++ Trunk/XaraLX/wxXtra/gridcombo.cpp	(revision 1703)
@@ -0,0 +1,914 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        gridcombo.cpp
+// Purpose:     A grid grid combo
+// Author:      Mikhail Tatarnikov
+// Modified by:
+// Created:     2006-08-16
+// RCS-ID:      $Id: $
+// Copyright:   (c) 2006 Xara Ltd
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#include "gridcombo.h"
+#include <wx/utils.h>
+
+
+#define HIGHLITED_TIMERID		777
+#define HIGHLITED_TIMERINTERVAL	250
+
+
+
+BEGIN_EVENT_TABLE(wxGridComboPopup, wxScrolledWindow)
+	EVT_TIMER(HIGHLITED_TIMERID, wxGridComboPopup::OnTimer)
+    EVT_SIZE(wxGridComboPopup::OnSize)
+    EVT_MOTION(wxGridComboPopup::OnMouseMove)
+    EVT_KEY_DOWN(wxGridComboPopup::OnKey)
+    EVT_LEFT_UP(wxGridComboPopup::OnLeftClick)
+END_EVENT_TABLE()
+
+
+
+wxGridComboPopup::wxGridComboPopup(wxGridCombo* pCombo)
+	: m_tmrHighlited(this, HIGHLITED_TIMERID)
+{
+	m_pCombo	  = pCombo;
+	m_iHighlighed = -1;
+
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::GetColumns
+Author    : Mikhail Tatarnikov
+Purpose   : A helper function to obtain the number of columns specified by the user
+Returns   : int - the number of columns to display in the popup.
+Exceptions: 
+Parameters: None
+Notes     : All the information is stored in one place - the combobox control itself.
+******************************************************************************/
+int wxGridComboPopup::GetColumns() const
+{
+	return m_pCombo->GetColumns();
+}
+
+/******************************************************************************
+Function  : intwxGridComboPopup::GetRows
+Author    : Mikhail Tatarnikov
+Purpose   : A helper function to obtain the number of rows that should be
+			displayd. Not all rows will be visible at once.
+Returns   : int - the number of all rows (visible and invisible).
+Exceptions: 
+Parameters: None
+Notes     : All the required to calculate the rows coun is stored in one
+			place - the combobox control itself.
+******************************************************************************/
+int	wxGridComboPopup::GetRows() const
+{
+	return m_pCombo->GetRows();
+}
+
+/******************************************************************************
+Function  : intwxGridComboPopup::GetItemsNum
+Author    : Mikhail Tatarnikov
+Purpose   : A helper function to obtain the number of items in the combobx.
+Returns   : int - the number of items to display.
+Exceptions: 
+Parameters: None
+Notes     : All the information is stored in one place - the combobox control itself.
+******************************************************************************/
+int	wxGridComboPopup::GetItemsNum() const
+{
+	return m_pCombo->GetItemsNum();
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::GetItemSize
+Author    : Mikhail Tatarnikov
+Purpose   : A helper function to obtain the size of items - e.g. the popup cell
+			size.
+Returns   : wxSize - the items size.
+Exceptions: 
+Parameters: None
+Notes     : All the information is stored in one place - the combobox control itself.
+			All items have the same size.
+******************************************************************************/
+wxSize wxGridComboPopup::GetItemSize() const
+{
+	return m_pCombo->GetItemSize();
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::GetSelected
+Author    : Mikhail Tatarnikov
+Purpose   : Get the currentrly selected element.
+Returns   : int - the index of currently selected element, -1 if none.
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+int wxGridComboPopup::GetSelected() const
+{
+	return m_pCombo->GetSelected();
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::SetSelected
+Author    : Mikhail Tatarnikov
+Purpose   : Selects an element
+Returns   : void
+Exceptions: 
+Parameters: [in] int iItem - an element index to select.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::SetSelected(int iItem)
+{
+	m_pCombo->SetSelected(iItem);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::Init
+Author    : Mikhail Tatarnikov
+Purpose   : Performs any initialization required.
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::Init()
+{
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::Create
+Author    : Mikhail Tatarnikov
+Purpose   : Creates the popup window
+Returns   : bool - true if successfull, false otherwise.
+Exceptions: 
+Parameters: [in] wxWindow* pwndParent - the parent window (combobox control).
+Notes     : 
+******************************************************************************/
+bool wxGridComboPopup::Create(wxWindow* pwndParent)
+{
+	if (!wxScrolledWindow::Create(pwndParent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
+		wxBORDER_SIMPLE | wxLB_INT_HEIGHT | wxWANTS_CHARS | wxVSCROLL | wxHSCROLL))
+		return false;
+
+	SetAutoLayout(true);
+
+	return true;
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::ChangeSelection
+Author    : Mikhail Tatarnikov
+Purpose   : Notification that the selection has been changed.
+Returns   : void
+Exceptions: 
+Parameters: [in] int iOldSelected - the prevoiusly selected item;
+            [in] int iNewSelected - the newly selected item.
+Notes     : Control has to repqint both items.
+******************************************************************************/
+void wxGridComboPopup::ChangeSelection(int iOldSelected, int iNewSelected)
+{
+	InvalidateItem(iOldSelected);
+	InvalidateItem(iNewSelected);
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::UpdateScrollers
+Author    : Mikhail Tatarnikov
+Purpose   : Update the scroll bars with the current information
+			(items number, columns, sizes, etc).
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::UpdateScrollers()
+{
+	wxSize szItem = GetItemSize();
+
+	wxPoint ptGrid(0, 0);
+	int iSelected = GetSelected();
+	if (iSelected != -1)
+		ptGrid = ItemToGrid(iSelected);
+
+	SetScrollbars(szItem.x, szItem.y, GetColumns(), GetRows(),
+		ptGrid.x, ptGrid.y);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::ItemToGrid
+Author    : Mikhail Tatarnikov
+Purpose   : Calculates position of an item based on its index
+Returns   : wxPoint - the item position (row/column).
+Exceptions: 
+Parameters: [in] int iItem - item index to calculate positio for.
+Notes     : 
+******************************************************************************/
+wxPoint wxGridComboPopup::ItemToGrid(int iItem)
+{
+	wxPoint ptGrid;
+	int iCols = GetColumns();
+	ptGrid.x = iItem % iCols;
+	ptGrid.y = iItem / iCols;
+
+	return ptGrid;
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::ItemFromPoint
+Author    : Mikhail Tatarnikov
+Purpose   : Finds item based on point (in client virtual coordinates)
+Returns   : int - the item index which the point belong.
+Exceptions: 
+Parameters: [in] wxPoint ptClient - the point to find item from.
+Notes     : 
+******************************************************************************/
+int wxGridComboPopup::ItemFromPoint(wxPoint ptClient)
+{
+	// TODO: Optimise - calculate instead of brute force iterate.
+
+	int iItemsNum = GetItemsNum();
+	for (int i = 0; i < iItemsNum; ++i)
+	{
+		// Calculate the area of the current item.
+		wxRect rcItem = GetItemRect(i);
+
+		// Check if the item should be updated.
+		if (rcItem.Inside(ptClient))
+			return i;
+	}
+
+	return -1;
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::GetItemRect
+Author    : Mikhail Tatarnikov
+Purpose   : Calculates the item area (in client virtual coordinates)
+Returns   : wxRect - the area occupied by the item.
+Exceptions: 
+Parameters: [in] int iItem - item to calculate the area for.
+Notes     : 
+******************************************************************************/
+wxRect wxGridComboPopup::GetItemRect(int iItem)
+{
+	wxPoint ptGrid = ItemToGrid(iItem);
+	wxSize  szItem = GetItemSize();
+
+	ptGrid.x *= szItem.x;
+	ptGrid.y *= szItem.y;
+
+	wxRect rcItem(ptGrid, szItem);
+
+	return rcItem;
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::ClientToScrolledVirtual
+Author    : Mikhail Tatarnikov
+Purpose   : Transfers a point from client to virtual (scrolled) coordinates
+Returns   : void
+Exceptions: 
+Parameters: [in/out] int* pX - the absciss value to convert;
+            [in/out] int* pY - the ordinate value to convert.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::ClientToScrolledVirtual(int* pX, int* pY)
+{
+	wxSize szItem	 = GetItemSize();
+	int iXOrigin = 0;
+	int iYOrigin = 0;
+	GetViewStart(&iXOrigin, &iYOrigin);
+	
+	if (pX)
+		*pX += iXOrigin * szItem.x;
+		
+	if (pY)
+		*pY += iYOrigin * szItem.y;
+
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnShow
+Author    : Mikhail Tatarnikov
+Purpose   : Notification that the popup is about to be shown
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::OnShow()
+{
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnSize
+Author    : Mikhail Tatarnikov
+Purpose   : Resize notification handler.
+Returns   : void
+Exceptions: 
+Parameters: [in] wxSizeEvent& event - size event information.
+Notes     : We need to update our scroll bars.
+******************************************************************************/
+void wxGridComboPopup::OnSize(wxSizeEvent& event)
+{
+	wxScrolledWindow::OnSize(event);
+	
+	UpdateScrollers();
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnMouseMove
+Author    : Mikhail Tatarnikov
+Purpose   : mouse movement notification handler
+Returns   : void
+Exceptions: 
+Parameters: [in] wxMouseEvent& event - mouse event information.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::OnMouseMove(wxMouseEvent& event)
+{
+	// Convert the poin to the logical coordinates.
+	wxPoint ptMouse(event.GetX(), event.GetY());
+	ClientToScrolledVirtual(&ptMouse.x, &ptMouse.y);	
+
+	// Find out what item the mouse hover over.
+	int iItem = ItemFromPoint(ptMouse);
+
+	// Check if mouse is hovered withing the same item.
+	if (iItem == m_iHighlighed)
+		return;
+
+	// If an item is hightlighted we need to start "dishighlight" timer
+	// since this message can be the last one before leaving the control.
+	if (iItem != -1)
+		m_tmrHighlited.Start(HIGHLITED_TIMERINTERVAL);
+
+	// Repaint the old and new items.
+	InvalidateItem(m_iHighlighed);
+	InvalidateItem(iItem);
+
+	m_iHighlighed = iItem;
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnTimer
+Author    : Mikhail Tatarnikov
+Purpose   : Timer notification handler
+Returns   : void
+Exceptions: 
+Parameters: [in] wxTimerEvent& event - time event information.
+Notes     : We need it to trace situations when the mouse highlight an item and
+			then leave the control leaving the item highlighted.
+******************************************************************************/
+void wxGridComboPopup::OnTimer(wxTimerEvent& event)
+{
+	if (m_iHighlighed == -1)
+	{
+		m_tmrHighlited.Stop();
+		return;
+	}
+
+	wxMouseState oMouseState = wxGetMouseState();
+	wxPoint ptMouse(oMouseState.GetX(), oMouseState.GetY());
+
+	ScreenToClient(&(ptMouse.x), &(ptMouse.y));
+
+	int iItem = ItemFromPoint(ptMouse);
+
+	if (iItem == -1)
+	{
+		m_tmrHighlited.Stop();
+		
+		int iCurHighlighted = m_iHighlighed;
+		m_iHighlighed		 = -1;
+		InvalidateItem(iCurHighlighted);
+	}
+
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnKey
+Author    : Mikhail Tatarnikov
+Purpose   : Keyboard notification handler.
+Returns   : void
+Exceptions: 
+Parameters: [in] wxKeyEvent& event - keyboard event information.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::OnKey(wxKeyEvent& event)
+{
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnLeftClick
+Author    : Mikhail Tatarnikov
+Purpose   : Left mouse button click handler
+Returns   : void
+Exceptions: 
+Parameters: [in] wxMouseEvent& event - mouse event information.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::OnLeftClick(wxMouseEvent& event)
+{
+	// Convert the poin to the logical coordinates.
+	wxPoint ptMouse(event.GetX(), event.GetY());
+	ClientToScrolledVirtual(&ptMouse.x, &ptMouse.y);	
+	
+	// Select a new item, if any was clicked.
+	int iItem = ItemFromPoint(ptMouse);
+	if (iItem != -1)
+		SetSelected(iItem);
+
+	DismissWithEvent();
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::DismissWithEvent
+Author    : Mikhail Tatarnikov
+Purpose   : Helper  function to setup a new selection, close the popup and send
+			a notification message.
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::DismissWithEvent()
+{
+    Dismiss();
+
+	int iSelected = GetSelected();
+    SendComboBoxEvent(iSelected);
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::SendComboBoxEvent
+Author    : Mikhail Tatarnikov
+Purpose   : Sends a combobox selection event
+Returns   : void
+Exceptions: 
+Parameters: [in] int iSelection - a new selection to notify clients about.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::SendComboBoxEvent(int iSelection)
+{
+	wxCommandEvent evt(wxEVT_COMMAND_COMBOBOX_SELECTED, m_combo->GetId());
+
+	evt.SetEventObject(m_pCombo);
+
+	evt.SetInt(iSelection);
+
+	// Set client data, if any
+	if (iSelection >= 0 && GetItemsNum() > iSelection)
+	{
+		CGridComboUserData* pClientData = m_pCombo->GetUserData(iSelection);
+		evt.SetClientData(pClientData);
+	}
+
+	m_combo->GetEventHandler()->AddPendingEvent(evt);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::GetAdjustedSize
+Author    : Mikhail Tatarnikov
+Purpose   : Calculates preferable size.
+Returns   : wxSize - the final size requested.
+Exceptions: 
+Parameters: [in] int iMinWidth	 - minimum width for the control. In some circumstances
+								   can be ignored;
+            [in] int iPrefHeight - preferable height;
+            [in] int iMaxHeight	 - maximum of height allowed.
+Notes     : 
+******************************************************************************/
+wxSize wxGridComboPopup::GetAdjustedSize(int iMinWidth, int iPrefHeight, int iMaxHeight)
+{
+	wxSize szAdjusted(0, 0);
+	wxSize szItem	= GetItemSize();
+	int	   iColumns = GetColumns();
+	int	   iRows	= GetRows();
+	
+	szAdjusted.x = szItem.x * iColumns;
+
+	int iRowsFit = iPrefHeight / szItem.y + 1;
+
+	// Check if we fit the maximum height.
+	int iHeight = iRowsFit * szItem.y;
+	if (iHeight > iMaxHeight)
+		iHeight = --iRowsFit * szItem.y;
+
+	// We must show at least one row.
+	iRowsFit = std::max(iRowsFit, 1);
+	
+	// No point in showing more rows than we have.
+	iRowsFit = std::min(iRowsFit, iRows);
+
+	szAdjusted.y = iRowsFit * szItem.y;
+
+	// Check if a slider is required.
+	if (iRowsFit < iRows)
+		szAdjusted.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
+
+	// Take into account the border.
+	szAdjusted.x += 2;
+	szAdjusted.y += 2;
+	
+	
+	return szAdjusted;
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::InvalidateItem
+Author    : Mikhail Tatarnikov
+Purpose   : Requests repaint of an item.
+Returns   : void
+Exceptions: 
+Parameters: [in] int iItem - an item to repaint.
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::InvalidateItem(int iItem)
+{
+	if (iItem == -1)
+		return;
+
+	int iX = 0;
+	int iY = 0;
+	
+	wxRect rcItem = GetItemRect(iItem);
+	
+	ClientToScrolledVirtual(&iX, &iY);
+	rcItem.x -= iX;
+	rcItem.y -= iY;
+	
+	Refresh(false, &rcItem);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::OnDraw
+Author    : Mikhail Tatarnikov
+Purpose   : The default implementation of drawing.
+Returns   : void
+Exceptions: 
+Parameters: [in] wxDC& dc - device context of the control to paint to.
+Notes     : Breaks the control to separate items and sends a request for painting
+			each item via DrawItem pure virtual function.
+******************************************************************************/
+void wxGridComboPopup::OnDraw(wxDC& dc)
+{
+	wxRect rcInvalid = GetUpdateClientRect();
+	ClientToScrolledVirtual(&(rcInvalid.x), &(rcInvalid.y));
+
+	// Iterate over all items, simply figing out whether we
+	// need to update it or not.
+	// TODO: optimize - iterate over visible items only.
+	int iItemsNum = GetColumns() * GetRows();
+	for (int i = 0; i < iItemsNum; ++i)
+	{
+		// Calculate the area of the current item.
+		wxRect rcItem = GetItemRect(i);
+
+		// Check if the item should be updated.
+		if (!rcItem.Intersects(rcInvalid))
+			continue;
+
+		// Check if the item is selected or highlighted.
+		int iFlags = 0;
+		if (i == GetSelected())
+			iFlags |= keSelected;
+
+		if (i == m_iHighlighed)
+			iFlags |= keHighlight;
+
+		DrawItem(dc, rcItem, i, iFlags);
+
+	}
+}
+
+/******************************************************************************
+Function  : wxGridComboPopup::PaintComboControl
+Author    : Mikhail Tatarnikov
+Purpose   : Paints an item in the combo control itself.
+Returns   : void
+Exceptions: 
+Parameters: [in] wxDC&		   dc	- dc to paint to;
+            [in] const wxRect& rect - area for painting.
+Notes     : Uses DrawItem pure virtual function.
+******************************************************************************/
+void wxGridComboPopup::PaintComboControl(wxDC& dc, const wxRect& rect)
+{
+	int iSelected = GetSelected();
+	if (iSelected == -1)
+	{
+	    wxComboPopup::PaintComboControl(dc, rect);
+		return;
+	}
+
+	int iFlags = keComboControl;
+	if (!m_pCombo->IsEnabled())
+		iFlags |= keDisabled;
+
+	DrawItem(dc, rect, iSelected, iFlags);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::DrawItem
+Author    : Mikhail Tatarnikov
+Purpose   : Draws item based on row and column
+Returns   : void
+Exceptions: 
+Parameters: [in] wxDC&	 dc		   - device context to paint to;
+            [in] wxRect& rcRect	   - the item position;
+            [in] int	 iRow	   - element's row;
+            [in] int	 iCol	   - element's column;
+            [in] bool	 bSelected - indicate whether the item is selected or not.
+Notes     : Calculates the item index and dispatch the call to descendants via
+			DrawItem pure virtual function.
+******************************************************************************/
+void wxGridComboPopup::DrawItem(wxDC& dc, const wxRect& rcRect, int iRow, int iCol, bool bSelected)
+{
+	int iItem = iRow * GetColumns() + iCol;
+
+	int iFlags = 0;
+	if (bSelected)
+		iFlags |= keSelected;
+
+	DrawItem(dc, rcRect, iItem, iFlags);
+}
+
+
+/******************************************************************************
+Function  : wxGridComboPopup::UpdateColumnsNum
+Author    : Mikhail Tatarnikov
+Purpose   : Updates the coumn number.
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridComboPopup::UpdateColumnsNum()
+{
+	UpdateScrollers();
+}
+
+
+
+
+
+
+
+
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxGridCombo, wxComboCtrl)
+
+/******************************************************************************
+Function  : wxGridCombo::Init
+Author    : Mikhail Tatarnikov
+Purpose   : Initialization routine
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridCombo::Init()
+{
+	m_iColumns	= 1;	// A standard list box with one column by default.
+	m_iSelected = -1;
+}
+
+wxGridCombo::wxGridCombo(wxWindow* pwndParent,
+						 wxWindowID wiID,
+						 const wxPoint& crptPos,
+						 const wxSize& crszSize,
+						 long lStyle,
+						 const wxString& crstrName)
+{
+    Init();
+    Create(pwndParent, wiID, crptPos, crszSize, lStyle, crstrName);
+}
+
+/******************************************************************************
+Function  : wxGridCombo::Create
+Author    : Mikhail Tatarnikov
+Purpose   : Creates the control
+Returns   : bool - see wxWindow::Create
+Exceptions: 
+Parameters: see wxWindow::Create.
+Notes     : 
+******************************************************************************/
+bool wxGridCombo::Create(wxWindow* pwndParent,
+						   wxWindowID wiID,
+						   const wxPoint& crptPos,
+						   const wxSize& crszSize,
+						   long lStyle,
+						   const wxString& crstrName)
+{
+	if (!wxComboCtrl::Create(pwndParent, wiID, wxEmptyString, crptPos, crszSize, lStyle, wxDefaultValidator, crstrName))
+		return false;
+
+	return true;
+}
+
+/******************************************************************************
+Function  : wxGridCombo::~wxGridCombo
+Author    : Mikhail Tatarnikov
+Purpose   : Destroys the object
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     :
+******************************************************************************/
+wxGridCombo::~wxGridCombo()
+{
+	DeleteUserData();
+}
+
+/******************************************************************************
+Function  : wxGridCombo::DeleteUserData
+Author    : Mikhail Tatarnikov
+Purpose   : Deletes all user data for itmes.
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridCombo::DeleteUserData()
+{
+	std::vector<CGridComboUserData*>::const_iterator citCur = m_vecUserData.begin();
+	for (; citCur != m_vecUserData.end(); ++citCur)
+		delete *citCur;
+
+	m_vecUserData.clear();
+}
+
+/******************************************************************************
+Function  : wxGridCombo::AddItem
+Author    : Mikhail Tatarnikov
+Purpose   : Adds a new item (appended to the end)
+Returns   : void
+Exceptions: 
+Parameters: [in] CGridComboUserData* pUserData - a new item to add.
+Notes     : 
+******************************************************************************/
+void wxGridCombo::AddItem(CGridComboUserData* pUserData)
+{
+	m_vecUserData.push_back(pUserData);
+	
+	wxGridComboPopup* pPopup = dynamic_cast<wxGridComboPopup*>(GetPopupControl());
+	if (pPopup)
+		pPopup->UpdateScrollers();
+}
+
+/******************************************************************************
+Function  : wxGridCombo::Clear
+Author    : Mikhail Tatarnikov
+Purpose   : Removes all elements from the combobox
+Returns   : void
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+void wxGridCombo::Clear()
+{
+	DeleteUserData();
+	
+	wxGridComboPopup* pPopup = dynamic_cast<wxGridComboPopup*>(GetPopupControl());
+	if (pPopup)
+		pPopup->UpdateScrollers();
+}
+
+
+/******************************************************************************
+Function  : wxGridCombo::GetUserData
+Author    : Mikhail Tatarnikov
+Purpose   : Retrieves user data associated with an item.
+Returns   : CGridComboUserData* - the user data for the item, if any.
+Exceptions: 
+Parameters: [in] int iIndex - index of the item to retrieve associated user data for.
+Notes     : 
+******************************************************************************/
+CGridComboUserData* wxGridCombo::GetUserData(int iIndex)
+{
+	if (iIndex < GetItemsNum())
+		return m_vecUserData[iIndex];
+
+	return NULL;
+}
+
+/******************************************************************************
+Function  : wxGridCombo::GetRows
+Author    : Mikhail Tatarnikov
+Purpose   : Calculates the number of rows.
+Returns   : int - the number of rows.
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+int wxGridCombo::GetRows()
+{
+	// Calculate the full rows based on the item number and the columns requested.
+	// Then add a partial row if required.
+	int iRows = GetItemsNum() / GetColumns();
+	if (GetItemsNum() % GetColumns() != 0)
+		iRows++;
+
+	return iRows;
+}
+
+
+/******************************************************************************
+Function  : wxGridCombo::SetItemSize
+Author    : Mikhail Tatarnikov
+Purpose   : Sets the item size
+Returns   : void
+Exceptions: 
+Parameters: [in] wxSize szItem - a new size for items.
+Notes     : All items have the same size.
+******************************************************************************/
+void wxGridCombo::SetItemSize(wxSize szItem)
+{
+	m_szItem = szItem;
+
+	wxGridComboPopup* pPopup = dynamic_cast<wxGridComboPopup*>(GetPopupControl());
+	if (!pPopup)
+		return;
+
+	pPopup->UpdateScrollers();
+}
+
+
+/******************************************************************************
+Function  : wxGridCombo::SetColumns
+Author    : Mikhail Tatarnikov
+Purpose   : Sets the number of columns
+Returns   : void
+Exceptions: 
+Parameters: [in] int iCols - new column number.
+Notes     : 
+******************************************************************************/
+void wxGridCombo::SetColumns(int iCols)
+{
+	m_iColumns = iCols;
+	
+	wxGridComboPopup* pPopup = dynamic_cast<wxGridComboPopup*>(GetPopupControl());
+	if (!pPopup)
+		return;
+
+	pPopup->UpdateColumnsNum();
+}
+
+
+/******************************************************************************
+Function  : wxGridCombo::SetSelected
+Author    : Mikhail Tatarnikov
+Purpose   : Selects an item.
+Returns   : void
+Exceptions: 
+Parameters: [in] int iItem - an item to select, -1 for unselecting.
+Notes     : 
+******************************************************************************/
+void wxGridCombo::SetSelected(int iItem)
+{
+	// Check if we actually changed anything.
+	if (GetSelected() == iItem)
+		return;
+
+	wxGridComboPopup* pPopup = dynamic_cast<wxGridComboPopup*>(GetPopupControl());
+	if (!pPopup)
+		return;
+
+	pPopup->ChangeSelection(GetSelected(), iItem);
+
+	m_iSelected = iItem;
+
+	// Invalidate the combo control.
+	Refresh(false);
+}
+
+/******************************************************************************
+Function  : wxGridCombo::GetSelected
+Author    : Mikhail Tatarnikov
+Purpose   : Gets the selected item
+Returns   : int - the index of the selected item, -1 otherwise.
+Exceptions: 
+Parameters: None
+Notes     : 
+******************************************************************************/
+int wxGridCombo::GetSelected() const
+{
+	return m_iSelected;
+}
Index: Trunk/XaraLX/wxXtra/xh_gridcombo.h
===================================================================
--- Trunk/XaraLX/wxXtra/xh_gridcombo.h	(revision 0)
+++ Trunk/XaraLX/wxXtra/xh_gridcombo.h	(revision 1703)
@@ -0,0 +1,38 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/xrc/xh_odcombo.h
+// Purpose:     XML resource handler for wxOwnerDrawnComboBox
+// Author:      Alex Bligh - based on wx/xrc/xh_combo.h
+// Created:     2006/06/19
+// RCS-ID:      $Id: xh_odcombo.h,v 1.1 2006/06/20 12:26:05 ABX Exp $
+// Copyright:   (c) 2006 Alex Bligh
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_XH_GRIDCOMBO_H_
+#define _WX_XH_GRIDCOMBO_H_
+
+
+#include <wx/xrc/xmlres.h>
+
+
+/*************************************************************************
+Class         : wxGridComboXmlHandler
+Base Class    : public wxXmlResourceHandler
+Author        : Mikhail Tatarnikov
+Description   : Creator class for wxGridCombo based on XML resources.
+Pure Virtual  : None
+Known Issues  : None
+Usage Notes   : None
+Override Notes: None
+**************************************************************************/
+class WXDLLIMPEXP_XRC wxGridComboXmlHandler : public wxXmlResourceHandler
+{
+DECLARE_DYNAMIC_CLASS(wxGridComboXmlHandler)
+public:
+    wxGridComboXmlHandler();
+    virtual wxObject *DoCreateResource();
+    virtual bool CanHandle(wxXmlNode *node);
+};
+
+
+#endif // _WX_XH_GRIDCOMBO_H_
Index: Trunk/XaraLX/wxXtra/xh_gridcombo.cpp
===================================================================
--- Trunk/XaraLX/wxXtra/xh_gridcombo.cpp	(revision 0)
+++ Trunk/XaraLX/wxXtra/xh_gridcombo.cpp	(revision 1703)
@@ -0,0 +1,98 @@
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+#if wxUSE_XRC
+
+#include "xh_gridcombo.h"
+
+#include "gridcombo.h"
+
+IMPLEMENT_DYNAMIC_CLASS(wxGridComboXmlHandler, wxXmlResourceHandler)
+
+wxGridComboXmlHandler::wxGridComboXmlHandler()
+                        :wxXmlResourceHandler()
+{
+    XRC_ADD_STYLE(wxCB_SIMPLE);
+    XRC_ADD_STYLE(wxCB_READONLY);
+    XRC_ADD_STYLE(wxCB_DROPDOWN);
+
+    AddWindowStyles();
+}
+
+/******************************************************************************
+Function  : *wxGridComboXmlHandler::DoCreateResource
+Author    : Mikhail Tatarnikov
+Purpose   : Creates new wxGridCombo and initializes it with values from the
+			resources.
+Returns   : wxObject* - the brand new initialized object.
+Exceptions: None
+Parameters: None
+Notes     : 
+******************************************************************************/
+wxObject* wxGridComboXmlHandler::DoCreateResource()
+{
+    XRC_MAKE_INSTANCE(pControl, wxGridCombo)
+
+    // Grid like stuff
+    if(HasParam(wxT("columns")))
+    {
+        pControl->SetColumns(GetLong(wxT("columns")));
+    }
+
+    if(HasParam(wxT("itemsize")))
+	{
+		wxSize sizItemSize = GetSize(wxT("itemsize"));
+		pControl->SetItemSize(sizItemSize);
+	}
+
+    pControl->Create(m_parentAsWindow,
+                    GetID(),
+                    GetPosition(), GetSize(),
+                    GetStyle(),
+                    GetName());
+
+
+    // ComboCtrl like stuff
+    wxSize ButtonSize=GetSize(wxT("buttonsize"));
+    if (ButtonSize != wxDefaultSize)
+	    pControl->SetButtonPosition(ButtonSize.GetWidth(), ButtonSize.GetHeight());
+
+    SetupWindow(pControl);
+
+    return pControl;
+}
+
+/******************************************************************************
+Function  : wxGridComboXmlHandler::CanHandle
+Author    : Mikhail Tatarnikov
+Purpose   : Checks if an XML node corresponds to our wxGridCombo control.
+Returns   : bool - true if wxGridCombo can be created from the node, false otherwise.
+Exceptions: 
+Parameters: [in] wxXmlNode* node - resource XML node to test.
+Notes     : 
+******************************************************************************/
+bool wxGridComboXmlHandler::CanHandle(wxXmlNode* node)
+{
+#if wxCHECK_VERSION(2,7,0)
+
+    return (IsOfClass(node, wxT("wxGridCombo")));
+
+#else
+
+//  Avoid GCC bug - this fails on certain GCC 3.3 and 3.4 builds for an unknown reason
+//  it is believed to be related to the fact IsOfClass is inline, and node->GetPropVal
+//  gets passed an invalid "this" pointer. On 2.7, the function is out of line, so the
+//  above should work fine. This code is left in here so this file can easily be used
+//  in a version backported to 2.6. All we are doing here is expanding the macro
+
+    bool bOurClass = node->GetPropVal(wxT("class"), wxEmptyString) == wxT("wxGridCombo");
+    return bOurClass;
+#endif
+}
+
+#endif // wxUSE_XRC
Index: Trunk/XaraLX/wxXtra/gridcombo.h
===================================================================
--- Trunk/XaraLX/wxXtra/gridcombo.h	(revision 0)
+++ Trunk/XaraLX/wxXtra/gridcombo.h	(revision 1703)
@@ -0,0 +1,213 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        gridcombo.h
+// Purpose:     A grid grid combo
+// Author:      Mikhail Tatarnikov
+// Modified by:
+// Created:     2006-08-16
+// RCS-ID:      $Id: $
+// Copyright:   (c) 2006 Xara Ltd
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WXXTRA_GRIDCOMBO_H_
+#define _WXXTRA_GRIDCOMBO_H_
+
+#include <wx/defs.h>
+//#include <wx/grid.h>
+#include <vector>
+
+#if wxUSE_COMBOCTRL
+#include <wx/combo.h>
+#else
+#include "combog.h"
+#endif
+
+
+class wxGridCombo;
+
+
+
+/*************************************************************************
+Class         : wxGridComboPopup
+Base Class    : public wxScrolledWindow
+				public wxComboPopup
+Author        : Mikhail Tatarnikov
+Description   : A base class for wxComboPopup implementation implementing
+				a grid-like popup (multicolmn as opposint to a standard one-column
+				list box popup).
+Pure Virtual  : DrawItem - you have to override it and do the actuall cell paint in it.
+Known Issues  : None
+Usage Notes   : All the information that pertain to the control as a whole (a combobox and popup)
+				is stored in the combobox itself. A number of access functions (e.g. GetColumns)
+				are provided.
+				An item can be in selected or highlighted (when the mouse is hovered over the item)
+				state.
+Override Notes: None
+**************************************************************************/
+class wxGridComboPopup : public wxScrolledWindow,
+						 public wxComboPopup
+{
+	friend class wxGridCombo;
+public:
+	enum EDrawFlags
+	{
+		keSelected	   = 0x0001,	// The item is selected.
+		keHighlight	   = 0x0002,	// The item is hovered.
+		keComboControl = 0x0004,	// The paint the item in the combo control itself.
+		keDisabled	   = 0x0008		// The item is disabled. For now can be applied for the combo
+									// control itself only.
+	};
+	
+public:
+
+	wxGridComboPopup(wxGridCombo* pCombo);
+
+    virtual void Init();
+    virtual bool Create(wxWindow* pwndParent);
+
+    virtual void	  OnShow();
+    virtual wxSize	  GetAdjustedSize(int iMinWidth, int iPrefHeight, int iMaxHeight);
+    virtual wxWindow* GetControl() {return this;}
+
+	// Drawing functions.
+	virtual void DrawItem(wxDC& dc, const wxRect& rect, int iItem, int iFlags) = 0;
+    virtual void PaintComboControl(wxDC& dc, const wxRect& rect);
+
+	virtual void SetSelected(int iItem);
+	virtual int	 GetSelected() const;
+
+
+	// Helper function
+	inline int	  GetColumns() const;
+	inline int	  GetRows() const;
+	inline int	  GetItemsNum() const;
+	inline wxSize GetItemSize() const;
+
+
+    // Gets displayed string representation of the value.
+    // Since we are owner-drawn control, the string doen't matter much.
+    virtual wxString GetStringValue() const {return wxString();}
+
+protected:
+	virtual void DrawItem(wxDC& dc, const wxRect& rect, int iCol, int iRow, bool bSelected);
+	virtual void UpdateScrollers();
+	virtual void UpdateColumnsNum();
+	virtual void ChangeSelection(int iOldSelected, int iNewSelected);
+	virtual void SendComboBoxEvent(int iSelection);
+
+	wxRect  GetItemRect(int iItem);
+	wxPoint ItemToGrid(int iItem);
+	int		ItemFromPoint(wxPoint ptClient);
+	void	InvalidateItem(int iItem);
+	void 	ClientToScrolledVirtual(int* pX, int* pY);
+
+	// Closes the popup and sends notig
+    void DismissWithEvent();
+
+	// Message handlers.
+	virtual void OnDraw(wxDC& dc);
+	void OnSize(wxSizeEvent& event);
+    void OnMouseMove(wxMouseEvent& event);
+    void OnKey(wxKeyEvent& event);
+    void OnLeftClick(wxMouseEvent& event);
+	void OnTimer(wxTimerEvent& event);
+
+protected:
+	wxGridCombo* m_pCombo;
+	int			 m_iHighlighed;
+	wxTimer		 m_tmrHighlited;	// Need a timer to spot the moment the mouse leaves popup (to dehighlight an item).
+private:
+    DECLARE_EVENT_TABLE()
+};
+
+
+
+
+
+
+
+
+
+
+
+
+struct CGridComboUserData
+{
+	virtual ~CGridComboUserData(){};
+};
+
+
+
+/*************************************************************************
+Class         : wxGridCombo
+Base Class    : public wxComboCtrl
+Author        : Mikhail Tatarnikov
+Description   : wxWidgit control extension that implements grid-like behaivor. Uses wxGridComboPopup
+				or its derivitives.
+Pure Virtual  : None
+Known Issues  : None
+Usage Notes   : None
+Override Notes: 
+**************************************************************************/
+class WXDLLIMPEXP_ADV wxGridCombo : public wxComboCtrl
+{
+//	friend class wxGridComboPopup;
+public:
+
+	wxGridCombo(){Init();}
+
+	wxGridCombo(wxWindow* pwndParent,
+				wxWindowID wiID = wxID_ANY,
+				const wxPoint& crptPos = wxDefaultPosition,
+				const wxSize& crszSize = wxDefaultSize,
+				long lStyle = 0,
+				const wxString& crstrName = wxT("wxSliderComboBox"));
+
+	bool Create(wxWindow* pwndParent,
+				wxWindowID wiID = wxID_ANY,
+				const wxPoint& crptPos = wxDefaultPosition,
+				const wxSize& crszSize = wxDefaultSize,
+				long lStyle = 0,
+				const wxString& crstrName = wxT("wxSliderComboBox"));
+
+	virtual ~wxGridCombo();
+
+
+	virtual void AddItem(CGridComboUserData* pUserData);
+	virtual CGridComboUserData* GetUserData(int iIndex);
+
+	virtual void Clear();
+	virtual void DeleteUserData();
+
+
+	void SetColumns(int iCols);
+	int	GetColumns() const {return m_iColumns;}
+	int	GetRows();
+
+	void SetSelected(int iSelected);
+	int  GetSelected() const;
+
+	int	GetItemsNum() const {return m_vecUserData.size();}
+
+	void   SetItemSize(wxSize szItem);
+	wxSize GetItemSize() const {return m_szItem;}
+
+
+protected:
+	void Init();
+
+protected:
+
+	std::vector<CGridComboUserData*> m_vecUserData;
+
+private:
+	int m_iColumns;
+
+	int m_iSelected;
+
+	wxSize m_szItem;	// The item size. In grid we can have items with the same size only. TODO: allow rows/columns with different sizes?
+
+	DECLARE_DYNAMIC_CLASS(wxGridCombo)
+};
+
+#endif //_WXXTRA_GRIDCOMBO_H_


Xara