Skip to content

Commit

Permalink
Merge branch 'origin/develop'
Browse files Browse the repository at this point in the history
Conflicts:
	threepenny-gui.cabal
  • Loading branch information
HeinrichApfelmus committed Sep 7, 2013
2 parents d1f7391 + e975ff6 commit 925c08a
Show file tree
Hide file tree
Showing 33 changed files with 1,675 additions and 758 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ TAGS
log
*.DS_Store
/Material/
/haddocks.html
39 changes: 30 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Use the web browser as a GUI, controllable from Haskell.
Threepenny-gui is a GUI framework that uses the web browser as a display.

* [Project homepage](http://www.haskell.org/haskellwiki/Threepenny-gui)

## Introduction

Expand All @@ -12,8 +14,8 @@ What is more, Threepenny is controlled entirely from within Haskell code,
relieving the user of writing client-side Javascript by hand.

Threepenny comes with a simple web server that is preconfigured to host a
client-side JS file called threepenny-gui.js. The Threepenny API communicates
with this JS to create new elements, respond to events, and more. This frequent
client-side JS file called `threepenny-gui.js`. The Threepenny API communicates
with this JS to create new elements, respond to events, and more. This frequent
communication precludes Threepenny from use in high-latency environments.

Users can, however, write their own Javascript if they wish, and invoke that
Expand All @@ -24,12 +26,15 @@ This project was originally called Ji in its earliest iterations.

## Examples

* [Simple buttons](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Buttons.hs)
* [Missing dollars question](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/MissingDollars.hs)
* [Multi-user chat](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Chat.hs)
* [Replace words in a text](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/UseWords.hs) (Apologies for the male-centric story)
* [BarTab - dynamic creation of widgets](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/BarTab.hs)
* [Drag'N'Drop example](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/DragNDropExample.hs)
* [BarTab.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/BarTab.hs) - Dynamic creation of widgets.
* [Buttons.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Buttons.hs) - Simple buttons to click on.
* [Chat.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/Chat.hs) - Multi-user chat.
* [CurrencyConverter.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/CurrencyConverter.hs) - Simple demonstration of two reactive input elements.
* [DragNDropExample.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/DragNDropExample.hs) - Simple drag'N'drop demo.
* [DrumMachine.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/DrumMachine.hs) - Specify rhythm by activating and deactivating checkboxes.
* [MissingDollars.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/MissingDollars.hs) - Text with configurable values.
* [UseWords.hs](https://github.com/HeinrichApfelmus/threepenny-gui/blob/master/src/UseWords.hs) - Text with configurable words. (Apologies for the male-centric story.)



## Challenges
Expand All @@ -39,6 +44,8 @@ This project was originally called Ji in its earliest iterations.
As indicated, the frequent communication between browser and server
means that Threepenny is best used as a GUI server running on localhost.

The communication is done over a persistent connection using WebSockets.

If you want to reduce latency, the best option is to generate JavaScript
code and run it on the client. Consider this approach similar to [a
shading language.](http://en.wikipedia.org/wiki/Shading_language)
Expand Down Expand Up @@ -82,3 +89,17 @@ can read the pages.

There are plenty more like this, but this is the first that springs to
mind that is good.

## Contributors

Many thanks to everyone who contributed, provided feedback or simply wrote an application using Threepenny!

* *Heinrich Apfelmus*
* *Daniel Austin*
* Daniel Díaz
* *Daniel Mlot*
* Luke Palmer
* Jens Petersen
* rnons

Special thanks to *Chris Done* for starting the precursor project Ji.
5 changes: 2 additions & 3 deletions src/BarTab.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import Graphics.UI.Threepenny.Core
main :: IO ()
main = do
static <- getStaticDir
startGUI Config
startGUI defaultConfig
{ tpPort = 10000
, tpCustomHTML = Nothing
, tpStatic = static
, tpStatic = Just static
} setup

setup :: Window -> IO ()
Expand Down
5 changes: 2 additions & 3 deletions src/Buttons.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import Paths
main :: IO ()
main = do
static <- getStaticDir
startGUI Config
startGUI defaultConfig
{ tpPort = 10000
, tpCustomHTML = Nothing
, tpStatic = static
, tpStatic = Just static
} setup

setup :: Window -> IO ()
Expand Down
50 changes: 29 additions & 21 deletions src/Chat.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Control.Monad
import Data.Functor
import Data.List.Extra
import Data.Time
import Data.IORef
import Prelude hiding (catch)

import Control.Monad.Trans.Reader as Reader
Expand All @@ -30,36 +31,40 @@ main :: IO ()
main = do
static <- getStaticDir
messages <- Chan.newChan
startGUI Config
startGUI defaultConfig
{ tpPort = 10000
, tpCustomHTML = Just "chat.html"
, tpStatic = static
, tpStatic = Just static
} $ setup messages

type Message = (UTCTime, String, String)

setup :: Chan Message -> Window -> IO ()
setup globalMsgs w = do
setup globalMsgs window = do
msgs <- Chan.dupChan globalMsgs

return w # set title "Chat"
return window # set title "Chat"

(nick, nickname) <- mkNickname
messageArea <- mkMessageArea msgs nick
(nickRef, nickname) <- mkNickname
messageArea <- mkMessageArea msgs nickRef

getBody w #+
getBody window #+
[ UI.div #. "header" #+ [string "Threepenny Chat"]
, UI.div #. "gradient"
, viewSource
, element nickname
, element messageArea
]

void $ forkIO $ receiveMessages w msgs messageArea
messageReceiver <- forkIO $ receiveMessages window msgs messageArea

on UI.disconnect window $ const $ do
putStrLn "Disconnected!"
killThread messageReceiver
now <- getCurrentTime
nick <- readIORef nickRef
Chan.writeChan msgs (now,nick,"( left the conversation )")

-- io $ catch (runTP session handleEvents)
-- (\e -> do killThread messageReceiver
-- throw (e :: SomeException))

receiveMessages w msgs messageArea = do
messages <- Chan.getChanContents msgs
Expand All @@ -68,30 +73,33 @@ receiveMessages w msgs messageArea = do
element messageArea #+ [mkMessage msg]
UI.scrollToBottom messageArea

mkMessageArea :: Chan Message -> Element -> IO Element
mkMessageArea :: Chan Message -> IORef String -> IO Element
mkMessageArea msgs nickname = do
input <- UI.textarea #. "send-textarea"

on UI.sendValue input $ (. trim) $ \content -> do
when (not (null content)) $ do
now <- getCurrentTime
nick <- trim <$> get value nickname
nick <- readIORef nickname
element input # set value ""
when (not (null nick)) $
Chan.writeChan msgs (now,nick,content)

UI.div #. "message-area" #+ [UI.div #. "send-area" #+ [element input]]


mkNickname :: IO (Element, Element)
mkNickname :: IO (IORef String, Element)
mkNickname = do
i <- UI.input #. "name-input"
el <- UI.div #. "name-area" #+
[ UI.span #. "name-label" #+ [string "Your name "]
, element i
]
UI.setFocus i
return (i,el)
input <- UI.input #. "name-input"
el <- UI.div #. "name-area" #+
[ UI.span #. "name-label" #+ [string "Your name "]
, element input
]
UI.setFocus input

nick <- newIORef ""
on UI.keyup input $ \_ -> writeIORef nick . trim =<< get value input
return (nick,el)

mkMessage :: Message -> IO Element
mkMessage (timestamp, nick, content) =
Expand Down
111 changes: 0 additions & 111 deletions src/Control/Event.hs

This file was deleted.

30 changes: 0 additions & 30 deletions src/Control/Monad/Extra.hs

This file was deleted.

8 changes: 0 additions & 8 deletions src/Control/Monad/IO.hs

This file was deleted.

Loading

0 comments on commit 925c08a

Please sign in to comment.