ColorListBox Topic is solved

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
Post Reply
galapaegos
In need of some credit
In need of some credit
Posts: 9
Joined: Mon Oct 16, 2006 7:13 pm

ColorListBox

Post by galapaegos » Fri Mar 23, 2012 9:22 pm

Hi all,

I'm developing a simple segmenting application for MRI data using wxWidgets 2.8.12 on both Windows & Linux. For displaying the segments that are created, I am currently using a wxCheckListBox. What I would like to do is something as follows:
[checkbox] [color of the segment as an image box] Segment name

Essentially I want a Listbox to maintain a list checkboxes with an image (it will be a flat color, so not quite an image). Ordering isn't too much of a concern in terms of drawing, as long as it looks and feels like a normal widget. Or possibly a listbox that draws a checkimagebox component (IE override to draw an image before the text of a checkbox).

I have seen related questions asked, but I didn't find any solutions that work for me and what I am after (wxSheet was one, wxTreeMultiCtrl had a broken link, etc). The answers usually boil down to using a wxGrid/wxTree type control, but after modifying an implementation of a Grid control to handle more like a listbox, I feel this is the wrong way to approach this particular widget. Browsing through the wxCode repository I didn't find anything similar to what I was looking for except wxtreelistctrl, but unable to get this code to compile. Even then, I don't think it is quite what I am looking for since it has switch statements to control which widgets are created, and I didn't see image support.

I greatly appreciate the help, thanks!

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Re: ColorListBox

Post by Auria » Sat Mar 24, 2012 12:40 am

I would have recommended using wx 2.9 with wxDataViewCtrl, where you can create a list with a check column, an icon column and a text column. If you can't update to wx 2.9... I think CodeLite contains a control that can fake that, simply by faking the checkbox using an icon and detecting clicks on an icon.

And also, a very simple but efficient way : make your own control! :) Create a wxFlexGridSizer, add checkboxes in the first column, static bitmaps in the second column, static texts in the 3rd column. This wouldn't be very hard
"Keyboard not detected. Press F1 to continue"
-- Windows

galapaegos
In need of some credit
In need of some credit
Posts: 9
Joined: Mon Oct 16, 2006 7:13 pm

Re: ColorListBox

Post by galapaegos » Sat Mar 24, 2012 1:01 pm

I didn't think of a wxFlexGridSizer, but this wouldn't give me a listbox feel would it? I tried to inherit off a wxCheckListBox but had some crazy flickering issues I couldn't resolve. I think this would work from just a wxControl, and send the appropriate wxCheckListBox events to the parent.

I will take a look at the widget in 2.9 (compiling now), and also look into CodeLite thanks!

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Re: ColorListBox

Post by Auria » Sat Mar 24, 2012 10:13 pm

Indeed using a sizer would not give a very list-like feeling per se, though what I do in a project (that is still stuck with wx 2.8, no use in doing that for a project that can require wx 2.9) is to use wxRendererNative ( http://docs.wxwidgets.org/trunk/classwx ... ative.html ) to render the headers, which makes them looks like native list headers. Not toooo much work and overall is a nice replacement until I can require 2.9
"Keyboard not detected. Press F1 to continue"
-- Windows

galapaegos
In need of some credit
In need of some credit
Posts: 9
Joined: Mon Oct 16, 2006 7:13 pm

Re: ColorListBox

Post by galapaegos » Mon Mar 26, 2012 10:07 pm

Thanks again Auria, wxRendererNative seems to be my answer.

For anyone else that is looking to do something like this or similar, here is what I did. I subclassed a wxControl, and overloaded the two functions (onPaint, onLeftDown) to perform the modifications that I wanted. I added an event object, along with macros to add these to the event table (select, toggle, double click).

Here is the relevant code:

Code: Select all

void CheckColorList::onPaint (wxPaintEvent &event)
{
	wxPaintDC dc (this);

	dc.SetBrush (*wxWHITE_BRUSH);
	dc.SetPen (*wxWHITE_PEN);
	dc.Clear ();

	int size = 16;

	for (unsigned int x = 0; x < getCount (); x++)
	{
		if (isSelected (x))
		{
			dc.SetBrush (*wxBLUE_BRUSH);
			dc.SetPen (*wxBLACK_DASHED_PEN);
			dc.DrawRectangle (0, x*size, GetSize ().GetWidth (), size);
		}

		//draw checkbox widget
		if (isChecked (x))
			wxRendererNative::Get ().DrawCheckBox (this, dc, wxRect (2, x*size, size, size), wxCONTROL_CHECKED);
		else
			wxRendererNative::Get ().DrawCheckBox (this, dc, wxRect (2, x*size, size, size), 0);

		dc.SetFont (*wxNORMAL_FONT);
		dc.SetBrush (wxBrush (list[x].m_Color));
		dc.SetPen (wxPen (list[x].m_Color));

		dc.DrawRectangle (size + 2, x*size, size, size);

		dc.DrawText (getString (x), (size + 2)*2, x*size);
	}
}

Code: Select all

void CheckColorList::onLeftDown (wxMouseEvent &event)
{
	int w, h;
	GetSize (&w, &h);

	int size = 16;

	int index = event.GetY ()/size;

	if (index < 0)
		index = 0;

	if (index > (int)list.size ())
		index = wxNOT_FOUND;

	if (event.GetX () > 1 && event.GetX () < size + 2)
	{
		//toggle the checkbox
		check (index, !isChecked (index));

		wxCommandEvent e (checkColorList_toggle, GetId ());
		e.SetInt (index);
		e.SetEventObject (this);

		ProcessCommand (e);
	}
	else
	{
		//not toggling, select
		select (index);

		wxCommandEvent e (checkColorList_select, GetId ());
		e.SetInt (getSelection ());
		e.SetEventObject (this);
		e.SetString (getStringSelection ());

		ProcessCommand (e);
	}

	Refresh (false);
}

Post Reply