packages feed

fudgets-0.18.3: Demos/graph/ZoomF.hs

module ZoomF(ZoomOutput(..),zoomF) where
import AllFudgets

data ZoomOutput
  = ZoomIn Size Point
  | ZoomOut Size Point
  | ZoomRect Size Rect
  | ZoomPick Size Point 
  | ZoomResize Size
  deriving (Eq,Show)

zoomF fud = groupF startcmds zoomK0 fud
  where
    startcmds = map XCmd $ 
                 [ConfigureWindow [CWBorderWidth 0],
                 ChangeWindowAttributes [CWEventMask eventmask],
		 clickGrab 1,
		 clickGrab 3,
		 GrabButton False (Button 2) []
				 [ButtonPressMask,
				 PointerMotionMask,
				 ButtonReleaseMask]]
    clickGrab n = GrabButton False (Button n) [] []
    eventmask = [ButtonPressMask]

    zoomK0 =
	setFontCursor 130 $
        allocNamedColorPixel defaultColormap bgColor $ \ bg ->
        allocNamedColorPixel defaultColormap fgColor $ \ fg ->
        wCreateGC rootGC (GCSubwindowMode IncludeInferiors:
	                  GCFunction GXxor:
			  invertColorGCattrs fg bg) $ \ gcinv ->
        waitForMsg layoutsize $ \ size ->
        zoomK gcinv size
      where
        layoutsize (Low (LEvt (LayoutSize size))) = Just size
	layoutsize _ = Nothing

    zoomK gcinv size =
        getK $ message low high
      where
        same = zoomK gcinv size
	high _ = same
	low event =
	  case event of
	    XEvt ButtonEvent {pos=p,state=mods} | Shift `elem` mods ->
		  put (ZoomPick size p) same
	    XEvt ButtonEvent {pos=p,button=Button 1} -> put (ZoomIn size p) same
	    XEvt ButtonEvent {pos=p,button=Button 3} -> put (ZoomOut size p) same
	    XEvt ButtonEvent {pos=p,button=Button 2,type'=Pressed} ->
	      putLow (wDrawRectangle gcinv (Rect p (Point 1 1))) $
	      rubberBandK gcinv size p p $ \ size' ->
	      zoomK gcinv size'
	    --XEvt MotionNotify {} ->
	    LEvt (LayoutSize size') ->
	      put (ZoomResize size') $
	      zoomK gcinv size'
	    _ -> same

rubberBandK gcinv size p0 p1 return =
     getK $ message low high
  where
    cont p = rubberBandK gcinv size p0 p return
    resize size' = rubberBandK gcinv size' p0 p1 return
    same = cont p1
    toggle p0 p1 = putLow $ wDrawRectangle gcinv (rect' p0 p1)
    high _ = same
    low event =
      case event of
        XEvt MotionNotify {pos=p} ->
	  toggle p0 p1 $
	  toggle p0 p $
	  cont p
	XEvt ButtonEvent {pos=p,type'=Released,button=Button 2} ->
	  toggle p0 p1 $
	  put (ZoomRect size (rect' p0 p1)) $
	  return size
        LEvt (LayoutSize size') -> resize size'
	_ -> same

rect' p1 p2 =
  let p0 = pmin p1 p2
      p = pmax p1 p2
  in Rect p0 (p-p0+1)