Difference between revisions of "Extending Phooey"
Mark Wassell (talk | contribs) (Created) |
Mark Wassell (talk | contribs) m |
||
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?