Paste: Good UI citizen demonstration

Author: dharmatech
Mode: factor
Date: Wed, 26 Nov 2008 17:24:20
Plain Text |
USING: accessors arrays combinators kernel locals math
       math.functions math.geometry math.ranges opengl opengl.gl
       opengl.glu processing.shapes sequences ui.gadgets
       ui.gadgets.worlds ui.render ui ui.gadgets.panes ;

IN: good-ui-citizen

! The Factor user interface toolkit is OpenGL based. The graphical
! building blocks of the toolkit are called 'gadgets' (what other
! toolkits call 'widgets').
!
! One nice thing about OpenGL is it's so easy to change the coordinate
! system to suit your needs (using the glOrtho function for
! example).
!
! However, the situation isn't so easy when you're implementing a new
! gadget which wants it's own coordinate system. When you write a new
! gadget, you have to ensure that it's a "good citizen" of the ui
! toolkit. It should play well with other gadgets.
!
! The litmus test for good behaviour is to call 'gadget.' on your
! gadget in a listener. It should render in the history without
! disturbing the rest of the workspace.
!
! The example below demonstrates how to construct a gadget which
! establishes it's own coordinate system.
!
! Unfortunately, it shouldn't be as difficult as it is.

! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 
! Make a 'setup-viewport' word.
!
! This is an interface to 'gl-viewport' which establishes a viewport
! for a particular gadget in a window.
!
! Such a utility word should probably be offered as a part of the core
! ui library.
! 
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

: screen-y* ( gadget -- loc )
  {
    [ find-world height ]
    [ screen-loc second ]
    [ height ]
  }
  cleave
  + - ;

: screen-loc* ( gadget -- loc )
  {
    [ screen-loc first ]
    [ screen-y* ]
  }
  cleave
  2array ;

: setup-viewport ( gadget -- gadget )
  dup
  {
    [ screen-loc* ]
    [ dim>>       ]
  }
  cleave
  gl-viewport ;

! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! Implement '<sine-gadget>'
!
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! A gadget which draws plots the sine curve from -10 to 10

TUPLE: <sine-gadget> < gadget ;

! Have a default size of 400x400

M: <sine-gadget> pref-dim* ( <sine-gadget> -- dim ) drop { 400 400 } ;

! Where all the magic happens

M:: <sine-gadget> draw-gadget* ( SINE -- )

  ! Switch to GL_PROJECTION mode. Save the matrix. Push identity matrix.

  GL_PROJECTION glMatrixMode glPushMatrix glLoadIdentity

  ! Establish our coordinate system

  -10 10 -10 10 gluOrtho2D

  ! Switch to GL_MODELVIEW mode. Save the matrix. Push identity matrix.

  GL_MODELVIEW glMatrixMode glPushMatrix glLoadIdentity

  ! Specify the viewport for ourself.

  SINE setup-viewport drop

  ! Do what we came here to do!
  
  -10 10 0.5 <range> [ dup sin 2array ] map line-strip

  ! processing.shapes can change this mode.
  ! Make sure we're back in 'fill-mode'

  fill-mode

  ! Restore the GL_PROJECTION and GL_MODELVIEW matrices.

  GL_PROJECTION glMatrixMode glPopMatrix glLoadIdentity
  GL_MODELVIEW  glMatrixMode glPopMatrix glLoadIdentity

  ! Restore the coordinate system that the ui world expects.

  SINE find-world
    { [ drop 0 ] [ width ] [ height ] [ drop 0 ] } cleave -1 1 glOrtho

  ! Restore the viewport for the world.
  
  SINE find-world setup-viewport drop ;

! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! These words demo the gadget. The first will open <sine-gadget> in a
! new window. The second will output a <sine-gadget> to the listener
! history.

: sine-gadget-window ( -- ) <sine-gadget> new-gadget "Sine" open-window ;
: sine-gadget.       ( -- ) <sine-gadget> new-gadget gadget.            ;

! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! Go forth, and write elegant Factor gadgets.

New Annotation

Summary:
Author:
Mode:
Body: