wxListCtrl and ClientData

BlitzMax Modules Forums/Brucey's Modules/wxListCtrl and ClientData

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

So i think you mean add this line to the TMainTask.GetListForTypeId function:
' added this line to get the SubTasks associated to each MainTask, and added a list object to the MainTaskList
Local STList:TList = TSubTask.GetListForTypeId(MainTask.MainTaskID)

then when i am adding the ClientData in MyFrame2.MTInsertIntoList() with item.SetData(dataSet) then i should also have my SubTask List, specific for that MainTask entry (MainTaskID).

Next i click on a MainTask and it does a For Eachin loop to get the SubTask Data from the ClientData.

It sounds reasonable to me, but i haven't the faintest idea how to access the second list in the client data. As you can see i have made no attempt to modify the Populate_m_listCtrl2 or STInsertIntoList methods.

Well i did make some attempts but they failed miserably...

I haven't added the list field either yet, to prevent the client data being GC'ed. I can't seem to wrap my head around adding a list with lists inside it, and then accessing that data afterwards... it is the data access i am struggling with the most.

i feel like this is one of the last hurdles to cross. in my main program using menus and popup windows with a right click is working in a seperate sample program, adding/editing/deleting records is easy and updating the GUI just recalls some of these functions.

I think i am close to pulling the disparate functionality together into the main program to finally get the Task List Manager done.

I just need some help with this part again.

Regards
Glenn

'
' Example application stub generated by wxCodeGen v1.02 : 10 Mar 2008 21:41:30
'
SuperStrict

Framework wx.wxApp

Import "ListCtrlClientDataGUI.bmx"
Import BaH.DBSQLite
Import brl.filesystem
Import brl.system

Const cListCtrlDateWidth:Int = 80

New MyApp.run()

Type MyApp Extends wxApp

	Field frame:MyFrame2
	
	Method OnInit:Int()
?macos
		' make the default Mac font for controls not so big
		wxSystemOptions.SetOption(wxWINDOW_DEFAULT_VARIANT, wxWINDOW_VARIANT_SMALL)
?
		' needed so my graphics show up
		wxInitAllImageHandlers()
		' for Mac/Win32 (it is default on Linux)
		wxImage.AddHandler( New wxXPMHandler )
		' create the frame
		Local frame:MyFrame2 = MyFrame2(New MyFrame2.Create(, , "ListCtrl Client Data Test"))
		' frames are created hidden. You need to manually show it.
		frame.show()
		' make sure it is brought to the front
		SetTopWindow(frame)

		Return True
	End Method
	
End Type



Type MyFrame2 Extends MyFrame2Base

	Method OnInit()
		Super.OnInit()
		' There are 2 list controls. Create the Column Headers here
		CreateListCtrlColumnHeaders()
		' populate the Due Date ListCtrl
		PopulateListCtrl(m_listCtrl1)		
		
	End Method

	Method CreateListCtrlColumnHeaders()
		' do the First List Control
		SetColumnHeadings(m_listCtrl1)
		' do the Second List Control
		SetColumnHeadings(m_listCtrl2)
	End Method

	Method SetColumnHeadings(ListControl:wxListCtrl)
		Select ListControl
			Case m_listCtrl1
				ListControl.InsertColumn(0, ("TM"), wxLIST_FORMAT_LEFT, 30)	' Team Member Initials
				ListControl.InsertColumn(1, ("Created"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(2, ("Due Date"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(3, ("Completed"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(4, ("Cancelled"), wxLIST_FORMAT_CENTRE, cListCtrlDateWidth)
				ListControl.InsertColumn(5, ("Main Task Name"), wxLIST_FORMAT_LEFT,200)
			Case m_listCtrl2
				ListControl.InsertColumn(0, ("TM"), wxLIST_FORMAT_LEFT, 30)	' Team Member Initials
				ListControl.InsertColumn(1, ("Created"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(2, ("Due Date"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(3, ("Completed"), wxLIST_FORMAT_LEFT, cListCtrlDateWidth)
				ListControl.InsertColumn(4, ("Cancelled"), wxLIST_FORMAT_CENTRE, cListCtrlDateWidth)
				ListControl.InsertColumn(5, ("Sub Task Name"), wxLIST_FORMAT_LEFT,200)
			Default
				DebugLog "You have passed a ListCtrl that doesn't exist"
		End Select
	End Method

	Method PopulateListCtrl(ListControl:wxListCtrl)
		' delete the Items, so the column headers don't need to be recreated
		ListControl.DeleteAllItems()
		' check the ListCtrl exists
		If ListControl Then
			' Get the data for the MainTask ListCtrl (using the id) from TSelector
			Local list:TList = TMainTask.GetListForTypeId()
			' i is the row number in the ListCtrl
			Local i:Int = 0	
			For Local dataset:TMainTask = EachIn list
				' InsertIntoList(Row Number, the data for this element of the list, the name of the ListCtrl)
				MTInsertIntoList(i, dataset, ListControl)
				' Increment i so you are always adding to the end of the ListCtrl
				' comment this line out if you want your listctrl populated in reverse, ie i = 0
				i:+ 1
			Next
		End If
	End Method

	Method MTInsertIntoList(index:Int, dataSet:TMainTask, list:wxListCtrl)
		' wxListItem - This type stores information about a wxListCtrl item or column.
		' Some comments taken from <a href="http://www.gibbongames.com/content/view/52/50/" target="_blank">http://www.gibbongames.com/content/view/52/50/</a>
		' wxListItem encapsulates the contents of a given listbox cell.
		' So each row/column combination has its own wxListItem structure.
		Local item:wxListItem = New wxListItem.Create()
		' Define all the parameters for the column, then use list.SetItem(item) to bind it
		' Column 0
		item.SetImage(-1)
		item.SetText(dataSet.TMID)
		item.SetId(index)
'******************* set the Client Data???? so it can be used in "Method MainTaskSelected(event:wxListEvent)"
		item.SetData(dataSet)
		' Apparently Column 0 requires InsertItem, but Column n > 0 requires SetItem (assuming that Column 0 has been previously inserted).
		list.InsertItem(item)
		' Column 1
		item.SetText(dataSet.MTCreateDate)
		item.SetColumn(1)
		list.SetItem(item)
		' Column 2
		item.SetText(dataSet.MTDueDate)
		item.SetColumn(2)
		list.SetItem(item)
		' Column 3
		item.SetText(dataSet.MTCompletedDate)
		item.SetColumn(3)
		list.SetItem(item)
		' Column 4
		If dataSet.MTCancelled = 1 Then
			item.SetText("Yes")
		Else
			item.SetText("No")
		End If
		item.SetColumn(4)
		list.SetItem(item)
		' Column 5
		item.SetText(dataSet.MTName)
		item.SetColumn(5)
		list.SetItem(item)
	End Method

	Method ListCtrl1Clicked(event:wxListEvent)
		DebugLog "ListCtrl1Clicked"
		' once the MainTask ListCtrl is clicked we need to populate the SubTask ListCtrl
		' Find the index of the item clicked
		Local index:Int = event.GetIndex()
		DebugLog "index = " + index
'		DebugStop
		
		' Get the value of the item clicked
		' Note: This is the TMainTask object we stored earlier.
		' It gives us access to the Id, for example, which gives us a quicker
		' lookup in the SQL. (ie. no table joins, since the Id is a foreign key!)
' ***************************** GetItemData(index) looks correct but i keep getting a 1 sent to the PopulateSubTask as the id
		Local sMainTask:TMainTask = TMainTask(m_listCtrl1.GetItemData(index))
		' now fill in the SubTask ListCtrl
		Populate_m_listCtrl2(sMainTask.MainTaskID, m_listCtrl2)
	End Method

	Method Populate_m_listCtrl2(id:Int, ListControl:wxListCtrl)
		' delete the Items, so the column headers don't need to be recreated
		ListControl.DeleteAllItems()
		' check the ListCtrl exists
		If ListControl Then
			' Get the data for the MainTask ListCtrl (using the id) from TSelector
			Local list:TList = TSubTask.GetListForTypeId(id)
			' i is the row number in the ListCtrl
			Local i:Int = 0	
			For Local dataset:TSubTask = EachIn list
				' InsertIntoList(Row Number, the data for this element of the list, the name of the ListCtrl)
				STInsertIntoList(i, dataset, ListControl)
				' Increment i so you are always adding to the end of the ListCtrl
				' comment this line out if you want your listctrl populated in reverse, ie i = 0
				i:+ 1
			Next
		End If
	End Method

	Method STInsertIntoList(index:Int, dataSet:TSubTask, list:wxListCtrl)
		' wxListItem - This type stores information about a wxListCtrl item or column.
		' Some comments taken from <a href="http://www.gibbongames.com/content/view/52/50/" target="_blank">http://www.gibbongames.com/content/view/52/50/</a>
		' wxListItem encapsulates the contents of a given listbox cell.
		' So each row/column combination has its own wxListItem structure.
		Local item:wxListItem = New wxListItem.Create()
		' Define all the parameters for the column, then use list.SetItem(item) to bind it
		' Column 0
		item.SetImage(-1)
		item.SetText(dataSet.TMID)
		item.SetId(index)
'******************* set the Client Data???? so it can be used in "Method MainTaskSelected(event:wxListEvent)"
		item.SetData(dataSet)
		' Apparently Column 0 requires InsertItem, but Column n > 0 requires SetItem (assuming that Column 0 has been previously inserted).
		list.InsertItem(item)
		' Column 1
		item.SetText(dataSet.STCreateDate)
		item.SetColumn(1)
		list.SetItem(item)
		' Column 2
		item.SetText(dataSet.STDueDate)
		item.SetColumn(2)
		list.SetItem(item)
		' Column 3
		item.SetText(dataSet.STCompletedDate)
		item.SetColumn(3)
		list.SetItem(item)
		' Column 4
		If dataSet.STCancelled = 1 Then
			item.SetText("Yes")
		Else
			item.SetText("No")
		End If
		item.SetColumn(4)
		list.SetItem(item)
		' Column 5
		item.SetText(dataSet.STName)
		item.SetColumn(5)
		list.SetItem(item)
	End Method
	
End Type





Type TDatabaseTables

	Global db:TDBConnection

	Method Init:TDatabaseTables()
	
		If Not db Then
			DeleteFile("ListCtrlClientData.db")
			DebugLog "Deleted File to start with a fresh one"
			If Not FileType("ListCtrlClientData.db") Then
				CreateDB("ListCtrlClientData.db")
			End If
			db = LoadDatabase("SQLITE", "ListCtrlClientData.db")
		End If
	
		' Check that the DB connection has been made
		If Not db Then
			Notify("Unable to Open the Database ListCtrlClientData.db")
			End
		End If
	
		' Check if the database has an error on opening
		If db.hasError() Then
			errorAndClose(db)
		End If

		Return Self
	End Method
	
	Method CreateDB(filename:String)

		Local dbase:TDBConnection = LoadDatabase("SQLITE", "ListCtrlClientData.db")
		Local s:String
		' Create tblMainTask
		s = "CREATE TABLE tblMainTask (MainTaskID integer primary key AUTOINCREMENT, " + ..
	  		" MTName varchar(100), " + ..
	  		" MTCreateDate varchar(10), " + ..
	  		" MTDueDate varchar(10), " + ..
	  		" MTCompletedDate varchar(10), " + ..
	  		" MTCancelled integer, " + ..
	  		" SelectorID integer, " + ..
			" TMID integer) "
		dbase.executeQuery(s)
		If dbase.hasError() Then
			errorAndClose(dbase)
		End If
		DebugLog "tblMainTask Created"
		' Create tblSubTask
		s = "CREATE TABLE tblSubTask (SubTaskID integer primary key AUTOINCREMENT, " + ..
	  		" STName varchar(100), " + ..
	  		" STOrder integer, " + ..
	  		" STMemo varchar(1000), " + ..
	  		" STCreateDate varchar(10), " + ..
	  		" STDueDate varchar(10), " + ..
	  		" STCompletedDate varchar(10), " + ..
	  		" STLastUpdatedDate varchar(10), " + ..
	  		" STCancelled integer, " + ..
	  		" MainTaskID integer, " + ..
			" TMID integer) "
		dbase.executeQuery(s)
		If dbase.hasError() Then
			errorAndClose(dbase)
		End If
		DebugLog "tblSubTask Created"
		
		' create some data...
		' tblMainTask
		dbase.executeQuery("INSERT INTO tblMainTask values (NULL, 'MainTask One', '01 Jan 2008', '02 Feb 2008', '03 Mar 2008', 0, 1, 1)")
		dbase.executeQuery("INSERT INTO tblMainTask values (NULL, 'MainTask Two', '01 Mar 2008', '02 Feb 2008', '03 Jan 2008', 0, 1, 2)")

		' tblSubTask
		dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask One for MainTask One', 1, 'Memo Field','01 Jan 2008', '02 Feb 2008', '03 Mar 2008', '04 Mar 2008', 0, 1, 1)")
		dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask Two for MainTask One', 1, 'Memo Field','02 Jan 2008', '02 Feb 2008', '03 Mar 2008', '04 Mar 2008', 0, 1, 1)")
		dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask One for MainTask Two', 1, 'Memo Field','01 Jan 2007', '02 Feb 2007', '03 Mar 2007', '04 Mar 2007', 0, 2, 2)")
		dbase.executeQuery("INSERT INTO tblSubTask values (NULL, 'SubTask Two for MainTask Two', 1, 'Memo Field','02 Jan 2007', '03 Feb 2007', '04 Mar 2007', '05 Mar 2007', 0, 2, 2)")

		dbase.close()
		
	End Method

	Function errorAndClose(db:TDBConnection)
		DebugLog(db.error().toString())
		db.close()
		End
	End Function
		
End Type


Type TMainTask Extends TDatabaseTables

	Field MainTaskID:Int
	Field MTName:String
	Field MTCreateDate:String
	Field MTDueDate:String
	Field MTCompletedDate:String
	Field MTCancelled:Int
	Field SelectorID:Int
	Field TMID:Int
	
	Method Init:TMainTask()
		Return TMainTask(Super.init())
	End Method

	Function GetListForTypeId:TList()
		Local list:TList = New TList
	
		Local mt:TMainTask = New TMainTask.Init()
		
		If db.isOpen() Then
		
			Local sql:String = "SELECT MainTaskID, MTName, MTCreateDate, MTDueDate, MTCompletedDate, MTCancelled, SelectorID, TMID "
			sql = sql + "FROM tblMainTask "

			' Get the data from the table
			Local query:TDatabaseQuery = db.executeQuery(sql)
			
			' Loop through each record and add the values to the TList
			For Local record:TQueryRecord = EachIn query
				Local MainTask:TMainTask = New TMainTask 
				MainTask.MainTaskID = record.GetInt(0)
				MainTask.MTName = record.GetString(1)
				MainTask.MTCreateDate = record.GetString(2)
				MainTask.MTDueDate = record.GetString(3)
				MainTask.MTCompletedDate = record.GetString(4)
				MainTask.MTCancelled = record.GetInt(5)
				MainTask.SelectorID = record.GetInt(6)
				MainTask.TMID = record.GetInt(7)
				DebugLog "Start of Data for MainTask record"
				DebugLog "MainTaskID = " + MainTask.MainTaskID
				DebugLog "MTName = " + MainTask.MTName
				DebugLog "MTCreateDate = " + MainTask.MTCreateDate
				DebugLog "MTDueDate = " + MainTask.MTDueDate
				DebugLog "MTCompletedDate = " + MainTask.MTCompletedDate
				DebugLog "MTCancelled = " + MainTask.MTCancelled
				DebugLog "SelectorID = " + MainTask.SelectorID
				DebugLog "TMID = " + MainTask.TMID
				DebugLog "End of Data for MainTask record"
				
				' added this line to get the SubTasks associated to each MainTask, and added a list object to the MainTaskList
				Local STList:TList = TSubTask.GetListForTypeId(MainTask.MainTaskID)
				
				list.AddLast(MainTask)
			Next

		EndIf
		
		Return list
	End Function

End Type

Type TSubTask Extends TDatabaseTables

	Field SubTaskID:Int
	Field STName:String
	Field STOrder:Int
	Field STMemo:String
	Field STCreateDate:String
	Field STDueDate:String
	Field STCompletedDate:String
	Field STLastUpdatedDate:String
	Field STCancelled:Int
	Field MainTaskID:Int
	Field TMID:Int
	
	Method Init:TSubTask()
		Return TSubTask(Super.init())
	End Method

	Function GetListForTypeId:TList(id:Int)
		Local list:TList = New TList
	
		Local st:TSubTask = New TSubTask.Init()
		
		If db.isOpen() Then
		
			Local sql:String = "SELECT SubTaskID, STName, STOrder, STMemo, STCreateDate, STDueDate, STCompletedDate, STLastUpdatedDate, STCancelled, MainTaskID, TMID "
			sql = sql + "FROM tblSubTask "
			sql = sql + "WHERE MainTaskID = " + id

			' Get the data from the table
			Local query:TDatabaseQuery = db.executeQuery(sql)
			
			' Loop through each record and add the values to the TList
			For Local record:TQueryRecord = EachIn query
				Local SubTask:TSubTask = New TSubTask 
				SubTask.SubTaskID = record.GetInt(0)
				SubTask.STName = record.GetString(1)
				SubTask.STOrder = record.GetInt(2)
				SubTask.STMemo = record.GetString(3)
				SubTask.STCreateDate = record.GetString(4)
				SubTask.STDueDate = record.GetString(5)
				SubTask.STCompletedDate = record.GetString(6)
				SubTask.STLastUpdatedDate = record.GetString(7)
				SubTask.STCancelled = record.GetInt(8)
				SubTask.MainTaskID = record.GetInt(9)
				SubTask.TMid = record.GetInt(10)
				DebugLog "Start of Data for SubTask record"
				DebugLog "SubTaskID = " + SubTask.SubTaskID
				DebugLog "STName = " + SubTask.STName
				DebugLog "STOrder = " + SubTask.STOrder
				DebugLog "STMemo = " + SubTask.STMemo
				DebugLog "STCreateDate = " + SubTask.STCreateDate
				DebugLog "STDueDate = " + SubTask.STDueDate
				DebugLog "STCompletedDate = " + SubTask.STCompletedDate
				DebugLog "STLastUpdatedDate = " + SubTask.STLastUpdatedDate
				DebugLog "STCancelled = " + SubTask.STCancelled
				DebugLog "MainTaskID = " + SubTask.MainTaskID
				DebugLog "TMID = " + SubTask.TMid
				DebugLog "End of Data for SubTask record"
				
				list.AddLast(SubTask)
			Next

		EndIf
		
		Return list
	End Function

End Type