Extending Phooey

From HaskellWiki
Revision as of 07:08, 18 August 2007 by Mark Wassell (talk | contribs) (Created)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

A note on how Phooey is being extended and utilised to develop a non-trivial application HGene. The key problem being addressed is the 'wiring problem' - How to wire up all the buttons, menus and display widgets so that it all works smoothly and is obvious?

First a screen shot:


To achieve this the following was done.

A number of widgets were added:

recordEditor :: Sourceable a => Source (Maybe a)  -> UI (Source (Maybe a))
listDisplay :: Sourceable a => Source [a] -> UI (ListSources a)
treeDisplay :: Sourceable a => Source (Tree a) -> UI (TreeSources a)

All of these are dynamic and take a source which provides updates on the information that they display.

ListSources and TreeSources are a way of grouping sources.

data TreeSources a = TreeSources { treeSelect :: Source (Maybe a), treeCopy :: Source (Maybe a) }
data ListSources a = ListSources { listSelect :: Source (Maybe a), listCopy :: Source (Maybe a) }

The select source is for selections in the widget, and the copy source is hooked into a popup menu action on the widget. This is wired to copy the current item into the clip board.

An additional 'non visible widget was created to provide persistence. The input source is updated 'a' values.

database :: Sourceable a => (Map Int a) -> Source (Maybe a) -> UI (Source (Map Int a))

The following is wired together as follows:

hgene pd = mdo 
            db <- database pd pers
            (pers,clipboard) <- fromLeft $ do 
                aTree  <- title "Family Tree" $ treeDisplay (liftA asTree db)
                fromTop $ do 
                     pers <- title "Person"  $ recordEditor  (aTree!treeSelect) 
                     aList <- title "Children" $ listDisplay ( liftA2 (\d p -> maybe [] (childrenOf d) p) db (aTree!treeSelect) )
                     pasted <- liftIO ( (aTree!treeCopy) `orSource` (aList!listCopy))
                     clipboard <- title "Clipboard" $ showDisplay pasted
                     return (pers,clipboard)
            return clipboard

The above could be neater except that mdo and the fromLeft/fromTop functions don't play together nicely. The '!' construct was borrowed from PropLang. 'orSource' is a function to OR two sources together.

I hope it is clear from the above code what the wiring is. If it isn't let me know about this and other suggestions on the talk page

Next steps are:

  • Add more editing actions - add delete and insert buttons to the recordEditor
  • Add a 'write protect' check box which if checked will prevent changes to the data but also grey out the menu buttons which trigger updates.
  • Add a way of allowing users of listDisplay and treeDisplay to specify additional buttons for the popup menu.
  • How might undo/redo be handled?