Skip to content

Instantly share code, notes, and snippets.

@adamczykm
Created September 1, 2018 11:02
Show Gist options
  • Select an option

  • Save adamczykm/2f7958a8feb5077d4f92a0bc21eb0512 to your computer and use it in GitHub Desktop.

Select an option

Save adamczykm/2f7958a8feb5077d4f92a0bc21eb0512 to your computer and use it in GitHub Desktop.
module Svg2PngPrintForm where
import Control.Applicative (pure, when)
import Control.Bind (bind, (=<<), (>>=))
import Control.Category ((<<<))
import Data.BooleanAlgebra ((||))
import Data.Eq ((/=))
import Data.Function (($))
import Data.Int (fromString)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Show (show)
import Data.Unit (unit)
import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import React.Basic (Component, component)
import React.Basic.DOM (button, div, input, text)
import React.Basic.DOM.Events (targetValue)
import React.Basic.Events (handler, handler_)
import SvgBitmapUtils (PngSrcB64, Size, SvgSrcB64, downloadPng, meanReplaceBadPixelsB64, renderSvgToPngBase64)
createPng ∷ SvgSrcB64 → SvgSrcB64 → Size → Aff PngSrcB64
createPng pmSvgSrc sceneSvgSrc size = do
pmPng ← renderSvgToPngBase64 size pmSvgSrc
scenePng ← renderSvgToPngBase64 size sceneSvgSrc
meanReplaceBadPixelsB64 pmPng scenePng
svg2PngPrintForm :: String → SvgSrcB64 → Size → Component { scene ∷ SvgSrcB64 }
svg2PngPrintForm displayName pixelMapSrc initialSize = component
{ displayName
, initialState
, receiveProps
, render
}
where
initialState =
{ outputSize: initialSize
, generateOutput: Nothing
, cached:
{ outputSize: initialSize
, scene: Nothing }}
receiveProps {setState, props, state} =
-- we need to compare against cached values to avoid state update - render loops
when (state.cached.scene /= Just props.scene || state.cached.outputSize /= state.outputSize)
-- update cache and png generating function
let genOutputFun = createPng pixelMapSrc props.scene state.outputSize
in setState (_
{ cached = {outputSize: state.outputSize, scene: Just props.scene}
, generateOutput = Just genOutputFun})
render {state, props, setState} = divc
[ divc [text "width", renderWidthInput]
, divc [text "height" , renderHeightInput]
, downloadButton ]
where
divc children = div {children}
downloadButton = button
{ onClick: handler_ $ case state.generateOutput of
Nothing → pure unit
Just genPng → launchAff_ (genPng >>= liftEffect <<< downloadPng "pattern.png")
, children: [text "Download"]}
renderHeightInput = input
{ type: "number"
, step: "1"
, value: show state.outputSize.height
, onChange: handler targetValue (\v → setState (\s → s{outputSize =
{ height: (fromMaybe s.outputSize.height (fromString =<< v))
, width: s.outputSize.width}}))
}
renderWidthInput = input
{ type: "number"
, step: "1"
, value: show state.outputSize.width
, onChange: handler targetValue (\v → setState (\s → s{outputSize =
{ width: (fromMaybe s.outputSize.width (fromString =<< v))
, height: s.outputSize.height}}))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment