; Show3, a program written by RSInc.
 
 

pro ObjShow3_Event, ev

 WIDGET_CONTROL, ev.top, GET_UVALUE = state
 st = *state
 WIDGET_CONTROL, ev.id, GET_UVALUE = uval

 case uval of

  'TRACK' : begin
            if (ev.type eq 4) then $
                st.oWin->Draw, state.oView $
            else begin

                ; This is a trackball move on the view.
                ;
                moved = st.oTrack->Update(ev, $
                    TRANSFORM = transform)
                oMove = st.oModel
                if (moved)  then begin
                    oMove->GetProperty, TRANSFORM = originalTransform
                    oMove->SetProperty, TRANSFORM = $
                     originalTransform # transform
                    if (ev.press eq 1) then begin
                        st.oWin->SetProperty, QUALITY = 0
                    endif
                    if (ev.release eq 1) then begin
                        st.oWin->SetProperty, QUALITY = 2
                        WIDGET_CONTROL, ev.top, /CLEAR_EVENTS
                    endif
                    WIDGET_CONTROL, /HOURGLASS
                    st.oWin->Draw, st.oView
                endif
            endelse
        end

  'MOVEIMAGE' : begin
   WIDGET_CONTROL, ev.id, GET_VALUE = percent
   st.oFrame->GetProperty, DATA = verts
   verts[2,*] = st.dMin*(100.0-percent)/100.0 + st.dMax*percent/100.0
   st.oFrame->SetProperty, DATA = verts
   st.oWin->Draw, st.oView
  end

  'MOVECONTOUR' : begin
   WIDGET_CONTROL, ev.id, GET_VALUE = percent
   ht = st.dMin*(100.0-percent)/100.0 + st.dMax*percent/100.0
   st.oCont->SetProperty, GEOMZ = ht
   st.oWin->Draw, st.oView
  end

  'NUMLEVELS' : begin
   WIDGET_CONTROL, ev.id, GET_VALUE = numL
   st.oCont->SetProperty, N_LEVELS = numL
   st.oWin->Draw, st.oView
  end

  'SELECTSURF' : begin
   whichOne = WIDGET_INFO(ev.id, /DROPLIST_SELECT)
   PRINT, whichOne
   st.oSurf->SetProperty, STYLE = whichOne
   st.oWin->Draw, st.oView
  end

        else:
    endcase
end

pro ObjShow3_Clean, top

 WIDGET_CONTROL, top, GET_UVALUE = state
 st = *state
 for ii = 0, (N_TAGS(st)-1) do $
  if OBJ_VALID(st.(ii)) then $
   OBJ_DESTROY, st.(ii)

 PTR_FREE, state
 

end

pro ObjShow3, data

 ; If no data input, create some.
 ;
 if (N_ELEMENTS(data) eq 0) then begin
  data = SHIFT(DIST(40), 25, 25)
  data = EXP(-(data/15)^2)
 endif

 ; GUI.
 ;
 wTop = WIDGET_BASE(/COL, TITLE = 'ObjShow3')
 xSize = 400 & ySize = 400
 wDraw = WIDGET_DRAW(wTop, XSIZE = xSize, YSIZE = ySize, $
  GRAPHICS_LEVEL = 2, /MOTION_EVENTS, /BUTTON_EVENTS, $
  UVALUE = 'TRACK', RENDERER = 0)
 dMax = MAX(data, MIN = dMin)
 wSlides = WIDGET_BASE(wTop, /ROW, /ALIGN_CENTER)
 wImageHeight = WIDGET_SLIDER(wSlides, VALUE = 0, MINIMUM = 0, $
  MAXIMUM = 100, TITLE = 'Image Height [%]', UVALUE = 'MOVEIMAGE')
 wContHeight = WIDGET_SLIDER(wSlides, VALUE = 100, MINIMUM = 0, $
  MAXIMUM = 100, TITLE = 'Contour Height [%]', UVALUE = 'MOVECONTOUR')
 wContLevels = WIDGET_SLIDER(wSlides, VALUE = 10, MINIMUM = 5, $
  MAXIMUM = 20, TITLE = 'Contour Levels [#]', UVALUE = 'NUMLEVELS')
 wDrops = WIDGET_BASE(wTop, /ROW, /ALIGN_CENTER)
 dropSurf = ['Points','Mesh','Solid','Ruled XZ','Ruled YZ',$
    'Lego Wires','Lego Solid']
 wSurf = WIDGET_DROPLIST(wDrops, VALUE = dropSurf, UVALUE = 'SELECTSURF')

 ; Objects.
 ;
 ; Size of data.
 ;
 sz = SIZE(data)

 ; Scale data space in z to match width/breadth.
 ;
 zcon = [-dMin*sz[1]/(dMax-dMin),sz[1]/(dMax-dMin)/1.75]

 ; Surface object.
 ;
 oSurf = OBJ_NEW('IDLgrSurface', DATAZ = data, COLOR = [200,40,40], $
  BOTTOM = [40,200,40], SHADING = 1, ZCOORD_CONV = zcon, STYLE = 1)

 ; Contour object.
 ;
 oCont = OBJ_NEW('IDLgrContour', DATA_VALUES = data, $
  COLOR = [40,40,250], /PLANAR, GEOMZ = dMax, $
  ZCOORD_CONV = zcon, N_LEVELS = 10)

 ; Image object w/ fixed color palette.
 ;
 oPal = OBJ_NEW('IDLgrPalette')
 oPal->LoadCt, 20
 oImage = OBJ_NEW('IDLgrImage', DATA = BYTSCL(data), PALETTE = oPal)

 ; Polygon object -- frame for texturemap of image.
 ;
 x0 = 0.0 & x1 = FLOAT(sz[1]) & y0 = 0.0 & y1 = FLOAT(sz[2])
 verts = [[x0,y0,0],[x1,y0,0],[x1,y1,0],[x0,y1,0]]
 oFrame = OBJ_NEW('IDLgrPolygon', DATA = verts, POLYGONS = [4,0,1,2,3], $
  TEXTURE_MAP = oImage, TEXTURE_COORD = [[0,0],[1,0],[1,1],[0,1]], $
  /TEXTURE_INTERP, ZCOORD_CONV = zcon, COLOR = [255,255,255])

 ; Model to contain the 3 entities of the ObjShow3.
 ;
 oModel = OBJ_NEW('IDLgrModel')

 ; Model to offset about center for rotations.
 ;
 oTModel = OBJ_NEW('IDLgrModel')

 ;Model to contain light(s).
 ;
 oLightModel = OBJ_NEW('IDLgrModel')

 ; Light objects.
 ;
 oLight0 = OBJ_NEW('IDLgrLight', TYPE = 1, COLOR = [250,250,250], $
  LOCATION = [sz[1]/2.,sz[2]/2.,4*sz[1]])
 oLight1 = OBJ_NEW('IDLgrLight', TYPE = 1, COLOR = [250,250,250], $
  LOCATION = [0.,sz[2]/2.,2*sz[1]])

 ; View in which to render models.
 ;
 clip = [1.5*MAX(sz[1:2]), -MAX(sz[1:2])-0.5*ABS(MAX(sz[1:2]))]
 vpr = [-sz[1]/2.0-0.3*sz[1],-sz[2]/2.0-0.3*sz[2],sz[1]+0.6*sz[1],sz[2]+0.6*sz[2]]
 oView = OBJ_NEW('IDLgrView', VIEWPLANE_RECT = vpr, $
  COLOR = [0,0,0], ZCLIP = clip, EYE = 4*clip[0])

 ; Trackball to manipulate objects in view.
 ;
 oTrack = OBJ_NEW('Trackball', [xSize/2.0,ySize/2.0], xSize/2.0)

 ; Build object hierarchy.
 ;
 oView->Add, [oLightModel,oModel]
 oLightModel->Add, [oLight0, oLight1]
 oModel->Add, oTModel
 oModel->Add, [oFrame,oSurf,oCont]

 ; Center everything.
 ;
 oModel->Translate, -sz[1]/2.0, -sz[2]/2.0, -(zcon[0]+zcon[1])/2.0

 ; Realize widgets.
 ;
 WIDGET_CONTROL, wTop, /REALIZE

 ; Get object window ID.
 ;
 WIDGET_CONTROL, wDraw, GET_VALUE = oWin
 WIDGET_CONTROL, wSurf, SET_DROPLIST_SELECT = 1

 ; Render original.
 ;
 oModel->Rotate, [-.8,-.4,0], 75
 oWin->Draw, oView

 state = $
 { $
  ;OBJECTS.
  oWin : oWin, $
  oView : oView, $
  oFrame : oFrame, $
  oCont : oCont, $
  oSurf : oSurf, $
  oTrack : oTrack, $
  oImage : oImage, $
  oLight0 : oLight0, $
  oLight1 : oLight1, $
  oModel : oModel, $
  oLightModel : oLightModel, $
  oPal : oPal, $
  ;WIDGETS.
  wDraw : wDraw, $
  wTop : wTop, $
  ;VARIABLES.
  dMax : dMax, $
  dMin : dMin $
 }

 WIDGET_CONTROL, wTop, SET_UVALUE = PTR_NEW(state)
 XMANAGER, 'ObjShow3', wTop, EVENT_HANDLER = 'ObjShow3_Event', $
  CLEANUP = 'ObjShow3_Clean'

end