From: Jeremy O'D. <jer...@gm...> - 2010-11-02 11:10:32
|
Hi James, On 29 October 2010 05:06, James d'Arcy <jam...@wr...> wrote: > Conceptually what I want to do is create items in the ListCtrl and > associate a > unique identifier with each item. This identifier would not be displayed in > the > UI. An Int64 would be ideal but a String would be fine. When a user clicks > on > the item, I want to be able to retrieve this identifier and use it to find > the > associated data, in this case a database record. > > The items are inserted into the ListCtrl ok with the following code: > > showStudy :: ListCtrl l -> (Int,DicomStudy) -> IO () > showStudy wgDbTable (idx,dcmStudy) = do > listCtrlInsertItemWithData wgDbTable idx $ studyUid dcmStudy > set wgDbTable [item idx := [(patientName . studyPatient) dcmStudy, > studyDescription dcmStudy, > studyDate dcmStudy]] > > and the event handler looks like this: > > onDbTableEvent :: HasturContext -> EventList -> IO () > onDbTableEvent HasturCtx {guiDbTable=wgDbTable, guiSeriesList=wgSeriesList} > event = > case event of > ListItemSelected idx -> do > studyUid <- listCtrlGetItemData wgSeriesList idx > infoM "Hastur" $ "DB Table event: " ++ show studyUid > propagateEvent > otherwise -> > propagateEvent > > When the user clicks on the ListCtrl item I get an error dialog pop up > saying: > > "Couldn't retrieve information about list control item X" > > where X is idx. The infoM call produces: > > "DB Table event: 0" > > What am I missing? I've tried listCtrl{Get/Set}Data, listCtrl{Get/Set}Text > all > with the same result. listCtrlDeleteItem in the event handler doesn't > delete the > item but produces the result: False. > > showStudy wgDbTable (idx,dcmStudy) = do listCtrlInsertItemWithData wgDbTable idx $ studyUid dcmStudy set wgDbTable [item idx := [(patientName . studyPatient) dcmStudy, studyDescription dcmStudy, studyDate dcmStudy]] I suspect that the problem comes from mixing WXCore and WX functionality (highlighted in red above if you are using an HTML mailer - otherwise look at the . I doubt that it is safe to do this. Below is an example I have tested. I've tried to make it as simple as possible, so it has a fixed list of (displayed) items, each of which has an Integer key (which is not displayed - it is stored as a data item). I'll write it up more fully in my blog (http://wewantarock.wordpress.com) shortly, but for the moment, just note that I am using the WXCore functions to insert the item data and the displayed contents. module Main () where import Graphics.UI.WXCore import Graphics.UI.WX -- Int data and strings for each column entries = [ (100, ["BouncingBalls.hs" ,"2402" ,"Jul 19 16:50"]) , (101, ["ByeDemo.hs" ,"1414" ,"Jul 13 23:18"]) , (102, ["Camels.hs" ,"7633" ,"Aug 20 11:57"]) , (103, ["Controls.hs" ,"3862" ,"Aug 20 11:57"]) , (104, ["HelloWorld.hs" ,"1028" ,"Aug 15 10:09"]) , (105, ["ImageViewer.hs" ,"3756" ,"Aug 20 11:57"]) , (106, ["Layout.hs" ,"1075" ,"Jul 13 23:18"]) , (107, ["ListCtrl.hs" ,"750" ,"Sep 8 16:22"]) , (108, ["Minimal.hs" ,"147" ,"Jul 13 23:18"]) , (109, ["Paint.hs" ,"1024" ,"Aug 20 11:57"]) , (110, ["Process.hs" ,"2261" ,"Aug 20 11:57"]) , (111, ["TimeFlows.hs" ,"4929" ,"Aug 20 11:57"]) , (112, ["TimeFlowsEx.hs" ,"8648" ,"Aug 20 11:57"]) , (113, ["desert.bmp" ,"61302" ,"Jul 13 23:31"]) ] main :: IO () main = start gui gui :: IO () gui = do -- main gui elements: frame, panel, text control, and the notebook f <- frame [text := "List Sample"] -- panel: just for the nice grey color p <- panel f [] textlog <- textCtrl p [enabled := False, wrap := WrapLine] -- use text control as logger textCtrlMakeLogActiveTarget textlog logMessage "logging enabled" -- list control l <- listCtrl p [columns := [("Name", AlignLeft, 120) ,("Size", AlignRight, -1) ,("Date", AlignRight, -1)]] set l [on listEvent := onListEvent l] mapM_ (setItem l) entries -- specify layout set f [layout := container p $ margin 10 $ column 5 [ fill $ widget l , hfill $ widget textlog ] ,clientSize := sz 400 300 ] return () where onListEvent lc eventList = case eventList of ListItemSelected idx -> do dat <-listCtrlGetItemData lc idx logMessage ("item selected: " ++ show idx ++ " Data: " ++ show dat) ListItemDeselected idx -> logMessage ("item de-selected: " ++ show idx) other -> logMessage ("list control event.") setItem lc (key_val, col_txts) = do count <- listCtrlGetItemCount lc idx <- listCtrlInsertItemWithLabel lc count (show count) (-1) mapM_ (\(column, col_txt) -> listCtrlSetItem lc idx column col_txt (-1)) (zip [0..] col_txts) listCtrlSetItemData lc idx key_val Is what I am trying to achieve possible or would I be better maintaining a > Data.Map with a mapping between idx and the relevant data? If so, how would > that > affect things if the ListCtrl contents are re-ordered (e.g. sort by date)? > Hopefully the example shows how to do what you want... > Sorry if this seems a stupid query, I'm new to Haskell and trying to learn > after > years of using imperative languages. > It's an entirely sensible question if you ask me, but then I'm also a recovering imperative programmer :-) Regards Jeremy |