wumpus-basic-0.24.0: src/Wumpus/Basic/Kernel/Base/UpdateDC.hs
{-# OPTIONS -Wall #-}
--------------------------------------------------------------------------------
-- |
-- Module : Wumpus.Basic.Kernel.Base.UpdateDC
-- Copyright : (c) Stephen Tetley 2010-2011
-- License : BSD3
--
-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>
-- Stability : highly unstable
-- Portability : GHC
--
-- Customize drawing attributes. The functions here are
-- @DrawingContext@ modifiers to be run within a the scope of a
-- @localize@ block (cf. @local@ of the Reader monad).
--
-- By convention, underscore-separated names are used for
-- DrawingContext modifiers in this module. This is because the
-- modifiers defined here are expected to be used mostly as static
-- \"properties\" resembling constants in drawings.
--
--------------------------------------------------------------------------------
module Wumpus.Basic.Kernel.Base.UpdateDC
(
-- * Globals
snap_grid_factors
-- * Line widths
, set_line_width
, line_default
, line_thin
, line_thick
, line_ultra_thick
, contextual_line_width
, relative_line_width
-- * Line cap
, cap_default
, cap_butt
, cap_round
, cap_square
-- * Line join
, join_default
, join_miter
, join_round
, join_bevel
-- * Dash pattern
, set_dash_pattern
, solid_line
, dotted_line
, packed_dotted
, loose_dotted
, dashed_line
, packed_dashed
, loose_dashed
-- * Font properties
, font_attr
, set_font
, set_font_size
, scale_point_size
, double_point_size
, half_point_size
-- * Text margins
, text_margin
, text_margin_none
, text_margin_tight
, text_margin_default
, text_margin_loose
-- * Colour
, stroke_colour
, fill_colour
, text_colour
, single_colour
, swap_colours
, fill_use_stroke_colour
, stroke_use_fill_colour
, fill_use_text_colour
, stroke_use_text_colour
, text_use_stroke_colour
, text_use_fill_colour
) where
import Wumpus.Basic.Kernel.Base.DrawingContext
import Wumpus.Basic.Kernel.Base.FontSupport
import Wumpus.Basic.Kernel.Base.Units
import Wumpus.Core -- package: wumpus-core
import Control.Applicative
--------------------------------------------------------------------------------
-- helpers
updateStrokeProps :: (StrokeAttr -> StrokeAttr) -> DrawingContextF
updateStrokeProps fn =
(\s i -> s { dc_stroke_props = fn i }) <*> dc_stroke_props
withFontSize :: (FontSize -> DrawingContextF) -> DrawingContextF
withFontSize fn = (\s i -> fn i s) <*> dc_font_size
--------------------------------------------------------------------------------
-- | 'snap_grid_factors' : @ x_unit * y_unit -> DrawingContextF @
--
-- Set the @snap grid factors@ - a snap grid is an alternative
-- coordinate space, it can be convenient for drawing
-- \"box and arrow\" diagrams.
--
snap_grid_factors :: Double -> Double -> DrawingContextF
snap_grid_factors xu yu = \s -> s { dc_snap_grid_factors = (xu, yu) }
--------------------------------------------------------------------------------
-- line widths
-- | set_line_width : @ width_in_points -> DrawingContextF @
--
-- Set the line_width to the supplied point size.
--
-- Initially the line width is 1.0.
--
-- /Constant/ variations of the function maybe be more
-- convenient:
--
-- > line_default, line_thin, line_thick, line_ultra_thick
--
set_line_width :: Double -> DrawingContextF
set_line_width d = updateStrokeProps (\s -> s { line_width = d })
-- | Set the line_width to @default@ - 1.0.
--
line_default :: DrawingContextF
line_default = set_line_width 1.0
-- | Set the line_width to @thin@ - 0.5.
--
line_thin :: DrawingContextF
line_thin = set_line_width 0.5
-- | Set the line_width to @thick@ - 2.0.
--
line_thick :: DrawingContextF
line_thick = set_line_width 2.0
-- | Set the line_width to @ultra_thick@ - 4.0.
--
line_ultra_thick :: DrawingContextF
line_ultra_thick = set_line_width 4.0
-- | Scale the line width respective to its current value.
--
-- The size is calculated with the supplied function.
--
relative_line_width :: (Double -> Double) -> DrawingContextF
relative_line_width fn =
updateStrokeProps (\s -> let lw = line_width s in s { line_width = fn lw })
-- | Set the line width to a size relative to the current font
-- size. The size is calculated with the supplied function.
--
contextual_line_width :: (FontSize -> Double) -> DrawingContextF
contextual_line_width fn =
withFontSize $ \sz s -> set_line_width (fn sz) s
--------------------------------------------------------------------------------
-- Line props
setLineCap :: LineCap -> DrawingContextF
setLineCap d = updateStrokeProps (\s -> s { line_cap = d })
setLineJoin :: LineJoin -> DrawingContextF
setLineJoin d = updateStrokeProps (\s -> s { line_join = d })
-- | Set the line_cap to the default which is @butt@.
--
-- This is a synonym for 'cap_butt'.
--
cap_default :: DrawingContextF
cap_default = cap_butt
-- | Set the line_cap to @butt@.
--
-- Butt chamfers off the stroke, flush to the end point.
--
-- This is the default.
--
-- > .-------.
-- > |=======|
-- > '-------'
--
cap_butt :: DrawingContextF
cap_butt = setLineCap CapButt
-- | Set the line_cap to @round@.
--
-- This rounds the end of the stroke and the visually the
-- rounding slightly extends the length of the line.
--
-- > .-------.
-- > ( ======= )
-- > '-------'
--
cap_round :: DrawingContextF
cap_round = setLineCap CapRound
-- | Set the line_cap to @square@.
--
-- This squares off the end of the stroke, but visual extends the
-- stroke by half the line width.
--
-- > .---------.
-- > | ======= |
-- > '---------'
--
cap_square :: DrawingContextF
cap_square = setLineCap CapSquare
-- | Set the line_join to the default which is @miter@.
--
-- This is a synonym for 'join_miter'.
--
join_default :: DrawingContextF
join_default = join_miter
-- | Set the line_join to @miter@.
--
-- This extends the joining line segments to form a sharp miter.
--
-- This is the default.
--
-- > /\
-- > /..\
-- > /./\.\
-- > /./ \.\
-- > /./ \.\
--
join_miter :: DrawingContextF
join_miter = setLineJoin JoinMiter
-- | Set the line_join to @round@.
--
-- This rounds off the corner of the joined line segments.
--
-- > \.\
-- > \.\
-- > ,.)
-- > /./
-- > /./
--
join_round :: DrawingContextF
join_round = setLineJoin JoinRound
-- | Set the line_join to @round@.
--
-- This bevels off the corner of the joined line segments with a
-- notch.
--
-- > __
-- > /..\
-- > /./\.\
-- > /./ \.\
-- > /./ \.\
--
join_bevel :: DrawingContextF
join_bevel = setLineJoin JoinBevel
--------------------------------------------------------------------------------
-- | Set the dash pattern.
--
-- Initially the dash pattern is 'Solid'.
--
set_dash_pattern :: DashPattern -> DrawingContextF
set_dash_pattern d = updateStrokeProps (\s -> s { dash_pattern = d })
-- | Set the dash_pattern to @solid@ - i.e. no dash pattern.
--
-- This is the default.
--
solid_line :: DrawingContextF
solid_line = set_dash_pattern Solid
-- | Set the dash pattern to draw a dotted line.
--
-- A dot is actually a square - side length is equal to the line
-- width.
--
-- The spacing between dots is 2 times the dot width.
--
dotted_line :: DrawingContextF
dotted_line = set_dash_pattern $ Dash 0 [(1,2)]
-- | Set the dash pattern to draw a tightly packed dotted line.
--
-- A dot is actually a square - side length is equal to the line
-- width.
--
-- The spacing between dots is equal to the dot width.
--
packed_dotted :: DrawingContextF
packed_dotted = set_dash_pattern $ Dash 0 [(1,1)]
-- | Set the dash pattern to draw a loosely dotted line.
--
-- A dot is actually a square - side length is equal to the line
-- width.
--
-- The spacing between dots is 4 times the dot width.
--
loose_dotted :: DrawingContextF
loose_dotted = set_dash_pattern $ Dash 0 [(1,4)]
-- | Set the dash pattern to draw a dashed line.
--
-- The dash length is 3 times the line width, the spacing is 2
-- times the line width.
--
dashed_line :: DrawingContextF
dashed_line = set_dash_pattern $ Dash 0 [(3,2)]
-- | Set the dash pattern to draw a tightly packed, dashed line.
--
-- The dash length is 3 times the line width, the spacing is
-- equal to the line width.
--
packed_dashed :: DrawingContextF
packed_dashed = set_dash_pattern $ Dash 0 [(3,1)]
-- | Set the dash pattern to draw a loosely dashed line.
--
-- The dash length is 3 times the line width, the spacing is 4
-- times the line width.
--
loose_dashed :: DrawingContextF
loose_dashed = set_dash_pattern $ Dash 0 [(3,4)]
--------------------------------------------------------------------------------
-- | Set the font attributes, point size and font face.
--
font_attr :: FontDef -> Int -> DrawingContextF
font_attr ft sz = \s -> s { dc_font_size = sz
, dc_font_face = font_def_face ft }
-- | Set the font face.
--
set_font :: FontDef -> DrawingContextF
set_font ft = \s -> s { dc_font_face = font_def_face ft }
-- | Set the point size.
--
-- This controls the drawing size of both
-- text labels and marks (e.g. dots and arrowheads).
--
set_font_size :: Int -> DrawingContextF
set_font_size sz = \s -> s { dc_font_size = sz }
-- | Scale the current point size by the supplied ratio.
--
-- Note - as fonts can only be drawn at integral sizes this
-- operation is not exact - for instance scaling 15pt by (1%2)
-- results in 7pt.
--
scale_point_size :: Double -> DrawingContextF
scale_point_size a = (\s sz -> set_font_size (floor $ a * fromIntegral sz) s)
<*> dc_font_size
-- | Set the point size (font and mark size) to double the current
-- size.
--
double_point_size :: DrawingContextF
double_point_size = scale_point_size 2
-- | Set the point size to half the current size, note the point
-- size also controls the size of dots, arrowsheads etc.
--
-- Note - as fonts can only be drawn at integral sizes this
-- operation is not exact - half size of 15pt type is 7pt.
--
half_point_size :: DrawingContextF
half_point_size = scale_point_size 0.5
-- | 'text_margin' : @ x_sep * y_sep -> DrawingContextF @
--
-- Note - this is in @Em@ units.
--
text_margin :: Em -> Em -> DrawingContextF
text_margin xsep ysep = \s ->
s { dc_text_margin = TextMargin xsep ysep }
-- | Set the text margin to (0,0).
--
-- This produces a tight box around the text vertically measured
-- to the cap-height and descender. Therefore some characters may
-- extend outside the margin (e.g. accented capitals like
-- A-grave).
--
text_margin_none :: DrawingContextF
text_margin_none = text_margin 0 0
-- | Set the text margin to (0.25 em, 0.25 em).
--
text_margin_tight :: DrawingContextF
text_margin_tight = text_margin 0.25 0.25
-- | Set the text margin to (0.5 em, 0.5 em).
--
text_margin_default :: DrawingContextF
text_margin_default = text_margin 0.5 0.5
-- | Set the text margin to (1.0 em, 1.0 em).
--
text_margin_loose :: DrawingContextF
text_margin_loose = text_margin 1.0 1.0
--------------------------------------------------------------------------------
-- | Set the stroke colour.
--
stroke_colour :: RGBi -> DrawingContextF
stroke_colour rgb = \s -> s { dc_stroke_colour = rgb }
-- | Set the fill colour.
--
fill_colour :: RGBi -> DrawingContextF
fill_colour rgb = \s -> s { dc_fill_colour = rgb }
-- | Set the text colour.
--
text_colour :: RGBi -> DrawingContextF
text_colour rgb = (\s -> s { dc_text_colour = rgb})
-- | Set the stroke, fill and text colours to a single colour.
--
single_colour :: RGBi -> DrawingContextF
single_colour rgb = stroke_colour rgb . fill_colour rgb . text_colour rgb
-- | Swap the stroke colour and fill colours.
--
swap_colours :: DrawingContextF
swap_colours =
(\s a b -> s { dc_stroke_colour = b, dc_fill_colour = a })
<*> dc_stroke_colour <*> dc_fill_colour
-- | Set the fill colour to use the current stroke colour.
--
fill_use_stroke_colour :: DrawingContextF
fill_use_stroke_colour =
(\s a -> s { dc_fill_colour = a }) <*> dc_stroke_colour
-- | Set the stroke colour to use the current fill colour.
--
stroke_use_fill_colour :: DrawingContextF
stroke_use_fill_colour =
(\s a -> s { dc_stroke_colour = a }) <*> dc_fill_colour
-- | Set the fill colour to use the current text colour.
--
fill_use_text_colour :: DrawingContextF
fill_use_text_colour =
(\s a -> s { dc_fill_colour = a }) <*> dc_text_colour
-- | Set the stroke colour to use the current fill colour.
--
stroke_use_text_colour :: DrawingContextF
stroke_use_text_colour =
(\s a -> s { dc_stroke_colour = a }) <*> dc_text_colour
-- | Set the text colour to use the current stroke colour.
--
text_use_stroke_colour :: DrawingContextF
text_use_stroke_colour =
(\s a -> s { dc_text_colour = a }) <*> dc_stroke_colour
-- | Set the text colour to use the current fill colour.
--
text_use_fill_colour :: DrawingContextF
text_use_fill_colour =
(\s a -> s { dc_text_colour = a }) <*> dc_fill_colour