Extending Phooey: Difference between revisions
Mark Wassell (talk | contribs) (Created) |
Mark Wassell (talk | contribs) mNo edit summary |
||
Line 1: | Line 1: | ||
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? | 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: | First a screen shot: | ||
Line 15: | Line 15: | ||
</haskell> | </haskell> | ||
All of these are dynamic and take a source which provides updates on the information that they display. | All of these are dynamic and take a source which provides updates on the information that they display. Sourceable is a new class that provides a number of utility functions that are used by recordEditor primarily. | ||
ListSources and TreeSources are a way of grouping sources. | ListSources and TreeSources are a way of grouping sources. | ||
Line 23: | Line 23: | ||
</haskell> | </haskell> | ||
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 | 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 clipboard. | ||
An additional | An additional non-visible 'widget' was created to provide persistence. The input source is updated 'a' values. | ||
<haskell> | <haskell> | ||
database :: Sourceable a => (Map Int a) -> Source (Maybe a) -> UI (Source (Map Int a)) | database :: Sourceable a => (Map Int a) -> Source (Maybe a) -> UI (Source (Map Int a)) | ||
Line 32: | Line 32: | ||
The following is wired together as follows: | The following is wired together as follows: | ||
<haskell> | <haskell> | ||
hgene :: Map Int Person -> UI (Source ()) | |||
hgene pd = mdo | hgene pd = mdo | ||
db <- database pd pers | db <- database pd pers | ||
Line 44: | Line 45: | ||
return clipboard | return clipboard | ||
</haskell> | </haskell> | ||
The input map is a map of Person records read from a file. | |||
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. | 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. | ||
Revision as of 07:27, 18 August 2007
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. Sourceable is a new class that provides a number of utility functions that are used by recordEditor primarily.
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 clipboard.
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 :: Map Int Person -> UI (Source ())
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 input map is a map of Person records read from a file.
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?