; docformat = 'rst' ;+ ; Demonstrates changing attributes of axis' text so they are always facing the ; viewer. ;- ;+ ; Handle all events. ; ; :Params: ; event : in, required, type=structure ; any event generated by widget program ;- pro mg_show_axes_event, event compile_opt strictarr widget_control, event.top, get_uvalue=pstate uname = widget_info(event.id, /uname) case uname of 'draw' : begin update = (*pstate).track->update(event, transform=rotation) if (update) then begin ; normal trackball rotation stuff here model = (*pstate).view->getByName('model') model->getProperty, transform=transform newTransform = transform # rotation model->setProperty, transform=newTransform ; instead of storing each axis object in state structure, find by name xaxis = model->getByName('x') yaxis = model->getByName('y') zaxis = model->getByName('z') ; set textbaseline so text faces viewer if (~(*pstate).noSwitch) then begin xaxis->setProperty, textbaseline=[(newTransform[2, 2] gt 0 ? 1 : -1), 0, 0] yaxis->setProperty, textbaseline=[0, (newTransform[2, 2] gt 0 ? 1 : -1), 0] zaxis->setProperty, textbaseline=[0, 0, (newTransform[1, 2] gt 0 ? -1 : 1)] endif ; remember to redraw or you won't see any changes (*pstate).window->draw, (*pstate).view endif end endcase end ;+ ; Cleanup resources. ; ; :Params: ; tlb : in, required, type=long ; widget identifier of the top-level base ;- pro mg_show_axes_cleanup, tlb compile_opt strictarr widget_control, tlb, get_uvalue=pstate ; trackball not part of hierarchy, so must be destroyed separately obj_destroy, [(*pstate).view, (*pstate).track] ptr_free, pstate end ;+ ; Demonstrates changing attributes of axis' text so they are always facing the ; viewer. ; ; :Keywords: ; no_switch : in, optional, type=boolean ; set to not switch the text baseline to face the viewer ; renderer : in, optional, type=long ; set to 0 for hardware rendering, 1 for software rendering ;- pro mg_show_axes, no_switch=noSwitch, renderer=renderer compile_opt strictarr ; create simple widget hierarchy tlb = widget_base(title='Axes demo', /column) draw = widget_draw(tlb, xsize=400, ysize=400, $ graphics_level=2, renderer=renderer, $ /button_events, /motion_events, uname='draw') widget_control, tlb, /realize widget_control, draw, get_value=window view = obj_new('IDLgrView', color=background) model = obj_new('IDLgrModel', name='model') view->add, model cr = [0, 1] cc = norm_coord(cr) cc[0] -= 0.5 xaxis = obj_new('IDLgrAxis', 0, range=cr, /exact, $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='x') model->add, xaxis yaxis = obj_new('IDLgrAxis', 1, range=cr, /exact, $ textbaseline=[0, 1, 0], textupdir=[-1, 0, 0], $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='y') model->add, yaxis zaxis = obj_new('IDLgrAxis', 2, range=cr, /exact, $ textbaseline=[0, 0, -1], textupdir=[-1, 0, 0], $ location=[cr[0], cr[0], cr[0]], $ xcoord_conv=cc, ycoord_conv=cc, zcoord_conv=cc, $ ticklen=0.025, name='z') model->add, zaxis ; rotate to get a nicer original orientation model->rotate, [1, 0, 0], 5 model->rotate, [0, 1, 0], -30 ; initial rendering window->draw, view ; trackball handles converting mouse motions to transformations track = obj_new('Trackball', [200, 200], 200) ; "pstate" data passing strategy for a widget program state = { view: view, $ window: window, $ track: track, $ noSwitch: keyword_set(noSwitch) $ } pstate = ptr_new(state, /no_copy) widget_control, tlb, set_uvalue=pstate xmanager, 'mg_show_axes', tlb, /no_block, $ cleanup='mg_show_axes_cleanup', $ event_handler='mg_show_axes_event' end