;+ ; NAME: ; SELECT_OBJECTS ; ; PURPOSE: ; The purpose of this program is to demonstrate how to select ; and move objects in an object graphics window. Once the objects ; appear in the window, use your mouse to select the objects and ; move them in the window. The window is resizeable. ; ; AUTHOR: ; FANNING SOFTWARE CONSULTING ; David Fanning, Ph.D. ; 1645 Sheely Drive ; Fort Collins, CO 80526 USA ; Phone: 970-221-0438 ; E-mail: david@idlcoyote.com ; Coyote's Guide to IDL Programming: http://www.idlcoyote.com ; ; CATEGORY: ; Object Graphics. ; ; CALLING SEQUENCE: ; SELECT_OBJECTS ; ; REQUIRED INPUTS: ; None. ; ; KEYWORD PARAMETERS: ; None. ; ; COMMON BLOCKS: ; None. ; ; SIDE EFFECTS: ; None. ; ; RESTRICTIONS: ; Requires VCOLORBAR from the Coyote Library: ; http://www.idlcoyote.com/programs/vcolorbar__define.pro. ; ; EXAMPLE: ; Select_Objects ; ; MODIFICATION HISTORY: ; Written by David Fanning, 21 September 98. ; Added the ability to shrink and expand the objects. 27 Sept 98. DWF. ; Changed FSC_Normalize to cgNormalize to reflect new name. 6 Feb 2013. DWF. ;- ;******************************************************************************************; ; Copyright (c) 2008, by Fanning Software Consulting, Inc. ; ; All rights reserved. ; ; ; ; Redistribution and use in source and binary forms, with or without ; ; modification, are permitted provided that the following conditions are met: ; ; ; ; * Redistributions of source code must retain the above copyright ; ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; ; notice, this list of conditions and the following disclaimer in the ; ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ; ; contributors may be used to endorse or promote products derived from this ; ; software without specific prior written permission. ; ; ; ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ; ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ; ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ; ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ; ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;******************************************************************************************; PRO Select_Button_Events, event ; This event handler responds to draw widget events. ; Get the info structure. Widget_Control, event.top, Get_UValue=info ; What kind of an event is this? possibleEvents = ['DOWN', 'UP', 'MOTION', 'SCROLL', 'EXPOSE'] possibleButtons = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT'] thisEvent = possibleEvents(event.type) thisButton = possibleButtons(event.press) ; Do the right thing. CASE thisEvent OF 'EXPOSE': info.thisWindow->Draw, info.thisView 'DOWN': BEGIN ; Has the user selected an object? item = info.thisWindow->Select(info.thisView, [event.x, event.y]) ; Get the first (closest) object in the list of selected objects. IF Obj_Valid(item[0]) THEN BEGIN item = item[0] CASE thisButton OF ; Move the selected object. 'LEFT': BEGIN ; Turn motion events ON. Record starting coordinates. Widget_Control, info.drawID, Draw_Motion_Events=1 info.xstart = event.x info.ystart = event.y ; Save the selected item. Get its name. Store it. info.selectedItem = item info.selectedItem->GetProperty, Name=selectedName info.selectedName = selectedName Print, 'Object Selected: ', selectedName ENDCASE ; Shrink the selected object. 'RIGHT': BEGIN item->Scale, 0.95, 0.95, 1.00 info.thisWindow->Draw, info.thisView ENDCASE ; Expand the selected object. 'MIDDLE': BEGIN item->Scale, 1.05, 1.05, 1.00 info.thisWindow->Draw, info.thisView ENDCASE ENDCASE ENDIF ELSE Print, 'No Object Selected.' ENDCASE 'UP': BEGIN ; Turn motion events OFF. Reinitialize selected object fields. Widget_Control, info.drawID, Draw_Motion_Events=0, /Clear_Events info.selectedName = '' info.selectedItem = Obj_New() END 'MOTION': BEGIN ; Calculate movement in normalized coordinates. Update start coords. deltax = (event.x - info.xstart) / Float(info.xsize) deltay = (event.y - info.ystart) / Float(info.ysize) info.xstart = event.x info.ystart = event.y ; Translate the selected model. info.selectedItem->Translate, deltax, deltay, 0 ; Draw the view. info.thisWindow->Draw, info.thisView END ELSE: ENDCASE ; Store info structure. Widget_Control, event.top, Set_UValue=info END ;------------------------------------------------------------------------ PRO Select_Cleanup, tlb ; This procedure cleans up all the persistent objects. Widget_Control, tlb, Get_UValue=info Obj_Destroy, info.thisContainer END ;------------------------------------------------------------------------ PRO Select_Resize, event ; This procedure resizes the graphics window. Widget_Control, event.top, Get_UValue=info, /No_Copy ; Resize the draw widget. Widget_Control, info.drawID, Draw_XSize=event.x, Draw_YSize=event.y ; Update the size fields in the info structure. info.xsize = event.x info.ysize = event.y ; Redisplay the graphic. info.thisWindow->Draw, info.thisView Widget_Control, event.top, Set_UValue=info, /No_Copy END ;------------------------------------------------------------------------ PRO Select_Objects ; This is an example program that shows you how to select ; and move objects in an object graphics window. ; Load an image data file. filename = FilePath(SubDirectory=['examples', 'data'], 'worldelv.dat') image = BytArr(360,360) OpenR, lun, filename, /Get_Lun ReadU, lun, image Free_Lun, lun ; Create an object graphics display window. tlb = Widget_Base(Title='Object Selection Example', TLB_Size_Events=1, $ Base_Align_Center=1, Column=1) drawID = Widget_Draw(tlb, Button_Events=1, Expose_Events=1, $ Retain=0, Graphics_Level=2, XSize=400, YSize=400, $ Event_Pro='Select_Button_Events') labelID = Widget_Label(tlb, $ Value='Left Button: Drag. Middle Button: Expand. Right Button: Contract.') ; Realize the widgets. Get window object. Widget_Control, tlb, /Realize Widget_Control, drawID, Get_Value=thisWindow ; Create the coordinate system for the window. thisView = Obj_New('IDLgrView', Viewplane_Rect=[0,0,1,1], Color=[100,100,100]) ; Create a color palette for the image and colorbar. thisPalette = Obj_New('IDLgrPalette') thisPalette->LoadCT, 5 ; Create objects to be selected and moved in the window. thisImage = Obj_New('IDLgrImage', image, Palette=thisPalette) thisImage->GetProperty, XRange=xrange, YRange=yrange xs = cgNormalize(xrange, Position=[0.2, 0.9]) ys = cgNormalize(yrange, Position=[0.1, 0.8]) thisImage->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys thisColorbar = Obj_New('VColorbar', Palette=thisPalette, $ Position=[0.10, 0.10, 0.15, 0.80], Color=[255,255,255], $ Title='Color Range') thisTitle = Obj_New('IDLgrText', 'World Elevation Data Set', $ Location=[0.5, 0.9], Alignment=0.5, Color=[255,255,255]) ; The easiest way to move objects in a window is to put ; each object to be moved in its own model. The models ; are easy to translate and move. ; Create a model for each of the objects to be moved. ; Make each model a selection target. imageModel = Obj_New('IDLgrModel', Name='IMAGE', Select_Target=1) imageModel->Add, thisImage colorbarModel = Obj_New('IDLgrModel', Name='COLORBAR', Select_Target=1) colorbarModel->Add, thisColorbar titleModel = Obj_New('IDLgrModel', Name='TITLE', Select_Target=1) titleModel->Add, thisTitle ; Add the models to the view. thisView->Add, imageModel thisView->Add, colorbarModel thisView->Add, titleModel ; Create a container for later cleanup. thisContainer = Obj_New('IDL_Container') thisContainer->Add, thisView thisContainer->Add, thisWindow thisContainer->Add, thisPalette thisContainer->Add, imageModel thisContainer->Add, colorbarModel thisContainer->Add, titleModel ; Select an ARROW cursor. thisWindow->SetCurrentCursor, 'Arrow' ; Create info structure to hold program information. info = { thisContainer:thisContainer, $ ; The graphics container. thisWindow:thisWindow, $ ; The window object. thisView:thisView, $ ; The view to be displayed in the window. xstart:0, $ ; The starting x coordinate in a drag action. ystart:0, $ ; The starting y coordinate in a drag action. drawID:drawID, $ ; The draw widget ID. xsize:400, $ ; The current X size of the draw widget. ysize:400, $ ; The current Y size of the draw widget. selectedItem:Obj_New(),$ ; The selected object. Currently NULL. selectedName:'' $ ; The name of the selected object. } ; Store the info structure in the UVALUE of the TLB. Widget_Control, tlb, Set_UValue=info XManager, 'select', tlb, Cleanup='Select_Cleanup', /No_Block, $ Event_Handler='Select_Resize' END