Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- This module is a starting point for implementing the Graph Drawing
- -- Calculator as described in Part II of the Standard Lab. You can use this
- -- directly, or just study it as an example of how to use threepenny-gui.
- import ThreepennyPages
- import Graphics.UI.Threepenny.Core as UI
- import qualified Graphics.UI.Threepenny as UI
- import Expr
- import Data.Maybe
- canWidth,canHeight :: Num a => a
- canWidth = 300
- canHeight = 300
- main :: IO ()
- main = startGUI defaultConfig setup
- setup :: Window -> UI ()
- setup window =
- do -- Create them user interface elements
- canvas <- mkCanvas canWidth canHeight -- The drawing area
- fx <- mkHTML "<i>f</i>(<i>x</i>)=" -- The text "f(x)="
- input <- mkInput 20 "x" -- The formula input
- draw <- mkButton "Draw graph" -- The draw button
- diffe <- mkButton "Differentiate function" -- The differentiate button
- zoom <- mkSlider (1, 20) 1
- -- The markup "<i>...</i>" means that the text inside should be rendered
- -- in italics.
- -- Add the user interface elements to the page, creating a specific layout
- formula <- row [pure fx,pure input]
- getBody window #+ [column [pure canvas,pure formula,pure draw,pure diffe,pure zoom]]
- -- Styling
- getBody window # set style [("backgroundColor","lightblue"),
- ("textAlign","center")]
- pure input # set style [("fontSize","14pt")]
- -- Interaction (install event handlers)
- on UI.click draw $ \ _ -> readAndDraw input zoom canvas
- on UI.click diffe $ \ _ -> differentiateAndDraw input zoom canvas
- on valueChange' input $ \ _ -> readAndDraw input zoom canvas
- on valueChange' zoom $ \ _ -> readAndDraw input zoom canvas
- differentiateAndDraw :: Element -> Element -> Canvas -> UI ()
- differentiateAndDraw input zoom canvas =
- do
- formula <- get value input
- set' value (showExpr (differentiate (fromJust (readExpr formula)))) input
- readAndDraw input zoom canvas
- readAndDraw :: Element -> Element -> Canvas -> UI ()
- readAndDraw input zoom canvas =
- do -- Get the current formula (a String) from the input element
- formula <- get value input
- zoomV <- get value zoom
- let zoomRead = read zoomV :: Double
- case readExpr formula of
- Nothing -> return ()
- (Just expr) -> drawGraph expr zoomRead canvas
- drawGraph :: Expr -> Double -> Canvas -> UI ()
- drawGraph expr zoom canvas =
- do
- clearCanvas canvas
- set UI.fillStyle (UI.solidColor (UI.RGB 0 0 0)) (pure canvas)
- UI.fillText (showExpr expr) (10,canHeight/2) canvas
- path "blue" (points expr (0.1 / zoom) (canWidth, canHeight)) canvas
- points :: Expr -> Double -> (Int,Int) -> [Point]
- points expr scale (width, height) = zip [0.. (fromIntegral width)] [realToPix y | y <- realY]
- where
- realY = [eval expr $ pixToReal $ fromIntegral x | x <- [0..width]]
- -- converts a pixel x-coordinate to a real x-coordinate
- pixToReal :: Double -> Double
- pixToReal x = (x - fromIntegral (div width 2)) * scale
- -- converts a real y-coordinate to a pixel y-coordinate
- realToPix :: Double -> Double
- realToPix y = fromIntegral ((div height 2) - round (y / scale))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement