Function What_Button_Type, event ; Checks event.type to find out what kind of button ; was clicked in a draw widget. This is NOT an event handler. type = ['DOWN', 'UP', 'MOTION', 'SCROLL'] Return, type(event.type) END ;******************************************************************* PRO Overlay_Events, event ; If this is UP event, switch event handlers, turn motion events off. ; Otherwise, repair window damage with pixmap and copy other image. ; Get the info structure. Widget_Control, event.top, Get_UValue=ptr Handle_Value, ptr, info, /No_Copy ; Interested in UP events. buttonType = What_Button_Type(event) IF buttonType EQ 'UP' THEN BEGIN ; Change the event handler. Turn motion events off. Widget_Control, info.grayDraw, Draw_Motion_Events=0, Event_Pro='XLinkWin_Draw_Events' Widget_Control, info.colorDraw, Draw_Motion_Events=0, Event_Pro='XLinkWin_Draw_Events' ; Copy the pixmap into the current window for the last time. Device, Copy=[0, 0, info.xsize, info.ysize, 0, 0, info.pixmapIndex] ENDIF $ ; buttonType='UP' ELSE BEGIN ; button not UP yet! ; To avoid flicker in the display you will just update the part of the window ; that needs updating. There are eight possible situations, depending upon the ; direction the cursor is moving. ; Keep the new x and y values inside the window. x = info.minx > event.x < info.maxx y = info.miny > event.y < info.maxy ; Update the coordinates of the edges of the new box. info.rsnew = x + 50 info.lsnew = x - 50 info.topnew = y + 50 info.botnew = y - 50 ; Make the current window the active window. WSet, info.currentWindow ; Which of the eight possibilities is it? IF info.topnew GT info.topold AND info.rsnew GT info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.topold, (info.rsnew-info.lsnew), (info.topnew-info.topold), $ info.lsnew, info.topold, info.copyWindow] Device, Copy=[info.rsold, info.botnew, (info.rsnew-info.rsold), (info.topold-info.botnew), $ info.rsold, info.botnew, info.copyWindow] Device, Copy=[info.lsold, info.botold, (info.lsnew-info.lsold), (info.topold-info.botold), $ info.lsold, info.botold, info.pixmapIndex] Device, Copy=[info.lsnew, info.botold, (info.rsold-info.lsnew), (info.botnew-info.botold), $ info.lsnew, info.botold, info.pixmapIndex] ENDIF IF info.topnew GT info.topold AND info.rsnew LT info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.topold, (info.rsnew-info.lsnew), (info.topnew-info.topold), $ info.lsnew, info.topold, info.copyWindow] Device, Copy=[info.lsnew, info.botnew, (info.lsold-info.lsnew), (info.topold-info.botnew), $ info.lsnew, info.botnew, info.copyWindow] Device, Copy=[info.lsold, info.botold, (info.rsold-info.lsold), (info.botnew-info.botold), $ info.lsold, info.botold, info.pixmapIndex] Device, Copy=[info.rsnew, info.botnew, (info.rsold-info.rsnew), (info.topold-info.botnew), $ info.rsnew, info.botnew, info.pixmapIndex] ENDIF IF info.topnew LT info.topold AND info.rsnew LT info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.botnew, (info.lsold-info.lsnew), (info.topnew-info.botnew), $ info.lsnew, info.botnew, info.copyWindow] Device, Copy=[info.lsold, info.botnew, (info.rsnew-info.lsold), (info.botold-info.botnew), $ info.lsold, info.botnew, info.copyWindow] Device, Copy=[info.lsold, info.topnew, (info.rsold-info.lsold), (info.topold-info.topnew), $ info.lsold, info.topnew, info.pixmapIndex] Device, Copy=[info.rsnew, info.botold, (info.rsold-info.rsnew), (info.topnew-info.botold), $ info.rsnew, info.botold, info.pixmapIndex] ENDIF IF info.topnew LT info.topold AND info.rsnew GT info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.botnew, (info.rsnew-info.lsnew), (info.botold-info.botnew), $ info.lsnew, info.botnew, info.copyWindow] Device, Copy=[info.rsold, info.botold, (info.rsnew-info.rsold), (info.topnew-info.botold), $ info.rsold, info.botold, info.copyWindow] Device, Copy=[info.lsold, info.botold, (info.lsnew-info.lsold), (info.topnew-info.botold), $ info.lsold, info.botold, info.pixmapIndex] Device, Copy=[info.lsold, info.topnew, (info.rsold-info.lsold), (info.topold-info.topnew), $ info.lsold, info.topnew, info.pixmapIndex] ENDIF IF info.topnew GT info.topold AND info.rsnew EQ info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.topold, (info.rsnew-info.lsnew), (info.topnew-info.topold), $ info.lsnew, info.topold, info.copyWindow] Device, Copy=[info.lsold, info.botold, (info.rsnew-info.lsnew), (info.botnew-info.botold), $ info.lsold, info.botold, info.pixmapIndex] ENDIF IF info.topnew EQ info.topold AND info.rsnew LT info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.botnew, (info.lsold-info.lsnew), (info.topnew-info.botnew), $ info.lsnew, info.botnew, info.copyWindow] Device, Copy=[info.rsnew, info.botnew, (info.rsold-info.rsnew), (info.topnew-info.botnew), $ info.rsnew, info.botnew, info.pixmapIndex] ENDIF IF info.topnew EQ info.topold AND info.rsnew GT info.rsold THEN BEGIN Device, Copy=[info.rsold, info.botnew, (info.rsnew-info.rsold), (info.topnew-info.botnew), $ info.rsold, info.botnew, info.copyWindow] Device, Copy=[info.lsold, info.botnew, (info.lsnew-info.lsold), (info.topnew-info.botnew), $ info.lsold, info.botnew, info.pixmapIndex] ENDIF IF info.topnew LT info.topold AND info.rsnew EQ info.rsold THEN BEGIN Device, Copy=[info.lsnew, info.botnew, (info.rsnew-info.lsnew), (info.botold-info.botnew), $ info.lsnew, info.botnew, info.copyWindow] Device, Copy=[info.lsnew, info.topnew, (info.rsnew-info.lsold), (info.topold-info.topnew), $ info.lsnew, info.topnew, info.pixmapIndex] ENDIF ; Save the old coordinates. info.oldx = x info.oldy = y info.rsold = info.rsnew info.lsold = info.lsnew info.topold = info.topnew info.botold = info.botnew ENDELSE ; Put the info structure back. Handle_Value, ptr, info, /Set, /No_Copy END ; ******* of OVERLAY event handler ************************ PRO XLinkWin_Events, event ; Get the info structure. Widget_Control, event.top, Get_UValue=ptr Handle_Value, ptr, info, /No_Copy ; What kind of event is this? Check UValue of event.id. Widget_Control, event.id, Get_UValue=thisEvent CASE thisEvent OF 'EXIT': Begin ; Destroy pixmap and free handle WDelete, info.pixmapIndex Handle_Free, ptr ; Out of here! Widget_Control, event.top, /Destroy END ; of EXIT code 'LINK CHOICE': Begin ; If LINKED turn motion events on. ; If UNLINKED turn motion event off. CASE event.index OF 0: Begin ; Unlinked choice selected Widget_Control, info.grayDraw, Draw_Button_Events=0 Widget_Control, info.colorDraw, Draw_Button_Events=0 END ; of Unlinked choice 1: Begin ; Linked choice selected Widget_Control, info.grayDraw, Draw_Button_Events=1 Widget_Control, info.colorDraw, Draw_Button_Events=1 END ; of Linked choice ENDCASE END ; of LINK CHOICE code 'COLORS1': XColors, NColors=100, Bottom=0, Group=event.top, Title='Window 1 Colors' 'COLORS2': XColors, NColors=100, Bottom=100, Group=event.top, Title='Window 2 Colors' ENDCASE ; Put the info structure back. IF Widget_Info(event.top, /Valid) THEN Handle_Value, ptr, info, /Set, /No_Copy END ; ********** of XLinkWin_Events ***************** PRO XLinkWin_Draw_Events, event ; Get the info structure. Widget_Control, event.top, Get_UValue=ptr Handle_Value, ptr, info, /No_Copy ; Only interested in down events. buttonType = What_Button_Type(event) IF buttonType NE 'DOWN' THEN RETURN ; Change the event handler. Turn motion events on. Widget_Control, info.grayDraw, Draw_Motion_Events=1, Event_Pro='Overlay_Events' Widget_Control, info.colorDraw, Draw_Motion_Events=1, Event_Pro='Overlay_Events' ; What kind of event is this? Check UValue of event.id. Widget_Control, event.id, Get_UValue=thisEvent CASE thisEvent OF 'GRAY-SCALE WINDOW': Begin info.currentWindow = info.grayIndex info.copyWindow = info.colorIndex END ; of GRAY-SCALE WINDOW code 'COLOR WINDOW': Begin info.currentWindow = info.colorIndex info.copyWindow = info.grayIndex END ; of COLOR WINDOW code ENDCASE ; Copy from the current window location to the pixmap. x = info.minx > event.x < info.maxx y = info.miny > event.y < info.maxy WSet, info.pixmapIndex Device, Copy=[0,0, info.xsize, info.ysize, 0, 0, info.currentWindow] WSet, info.currentWindow ; Save the old coordinates. info.oldx = x info.oldy = y info.rsold = x + 50 info.lsold = x - 50 info.topold = y + 50 info.botold = y - 50 ; Copy the contents of the other window into the current window. Device, Copy=[x-50, y-50, 100,100, x-50, y-50, info.copyWindow] ; Put the info structure back. Handle_Value, ptr, info, /Set, /No_Copy END ; ********** of XLinkWin_Draw_Events ***************** PRO XLinkWin, image On_Error, 1 ; If there is no image parameter, open the worldelv.dat file. IF N_Elements(image) EQ 0 THEN BEGIN file = Filepath(Subdir='training', 'worldelv.dat') OpenR, lun, file, /Get_lun image = BytArr(360,360) ReadU, lun, image Free_lun, lun ENDIF ; What size is the image data? imsize = Size(image) IF imsize(0) NE 2 THEN $ Message, 'Sorry, the argument is not a 2D dataset' xsize = imsize(1) ysize = imsize(2) ; Establish box coordinate limits. boxmaxx = xsize - 50 boxmaxy = ysize - 50 boxminx = 50 boxminy = 50 ; Scale the image data so it can appear in two windows ; using different portions of the colortable. image1 = BytScl(image, Top=100) image2 = BytScl(image, Top=100) + 100B ; Load different colortables into the one physical table. LoadCt, 0, NColors=100, Bottom=0 ; Gray-scale LoadCt, 11, NColors=100, Bottom=100 ; Colored ; Create control panel. tlb = Widget_Base(Column=1, Title='Control Panel') linker = Widget_DropList(tlb, Value=['Unlinked', 'Linked'], $ Title='Image Status: ', UValue='LINK CHOICE') colors = Widget_Button(tlb, Value='Colors', Menu=2) colors1 = Widget_Button(colors, Value='Window 1 Colors', UValue='COLORS1') colors1 = Widget_Button(colors, Value='Window 2 Colors', UValue='COLORS2') quitter = Widget_Button(tlb, Value='Exit Program', $ UValue='EXIT') ; Create gray-scale window. win1base = Widget_Base(Title='Window 1', Group=tlb, $ XOffSet=50, YOffSet=50) grayDraw = Widget_Draw(win1base, XSize=xsize, YSize=ysize, $ UValue='GRAY-SCALE WINDOW', Event_Pro='XLinkWin_Draw_Events') ; Create color window. win2base = Widget_Base(Title='Window 2', Group=tlb, $ XOffSet=150, YOffSet=150) colorDraw = Widget_Draw(win2base, XSize=xsize, YSize=ysize, $ UValue='COLOR WINDOW', Event_Pro='XLinkWin_Draw_Events') ; Create a pixmap window for erasing. Window, /Free, XSize=xsize, YSize=ysize, /Pixmap pixmapIndex = !D.Window ; Realize all windows. Widget_Control, tlb, /Realize Widget_Control, win1base, /Realize Widget_Control, win2base, /Realize ; Get window index numbers. Widget_Control, grayDraw, Get_Value=grayIndex Widget_Control, colorDraw, Get_Value=colorIndex ; Load the images. WSet, grayIndex Tv, image1 WSet, colorIndex Tv, image2 ; Create an info structure to hold program information. info = { $ pixmapIndex:pixmapIndex, $ ; The window ID of the pixmap window grayIndex:grayIndex, $ ; The window ID of the gray-scale window. colorIndex:colorIndex, $ ; The window ID of the color window. maxx:boxmaxx, $ maxy:boxmaxy, $ minx:boxminx, $ miny:boxminy, $ oldx:0, $ oldy:0, $ xsize:xsize, $ ysize:ysize, $ rsold:0, rsnew:0, lsold:0, lsnew:0, topnew:0, topold:0, botold:0, botnew:0, $ currentWindow:0, $ copyWindow:0, $ grayDraw:graydraw, $ ; The widget ID of the gray-scale draw widget. colorDraw:colorDraw} ; The widget ID of the color draw widget. ; Store the info structure in a pointer. ptr = Handle_Create(Value=info, /No_Copy) ; Store the pointer in the TLB of each window. Widget_Control, tlb, Set_UValue=ptr Widget_Control, win1base, Set_UValue=ptr Widget_Control, win2base, Set_UValue=ptr ; Move the control panel forward. Widget_Control, tlb, Show=1 ; Call XManager and set up event loop. XManager, 'xlinkwin', tlb, Event_Handler='XLinkWin_Events' END