[85] | 1 | ;+ |
---|
| 2 | ; NAME: |
---|
| 3 | ; FSC_PLOTWINDOW |
---|
| 4 | ; |
---|
| 5 | ; PURPOSE: |
---|
| 6 | ; |
---|
| 7 | ; The purpose of this compound widget is to create a resizeable |
---|
| 8 | ; "plot window" inside a larger "page window". I'm not sure it |
---|
| 9 | ; has any value except as a utility routine for the PostScript |
---|
| 10 | ; configuration object FSC_PSCONFIG__DEFINE, but it's a neat |
---|
| 11 | ; program anyway. :-) |
---|
| 12 | ; |
---|
| 13 | ; AUTHOR: |
---|
| 14 | ; |
---|
| 15 | ; FANNING SOFTWARE CONSULTING |
---|
| 16 | ; David Fanning, Ph.D. |
---|
| 17 | ; 1645 Sheely Drive |
---|
| 18 | ; Fort Collins, CO 80526 USA |
---|
| 19 | ; Phone: 970-221-0438 |
---|
| 20 | ; E-mail: davidf@dfanning.com |
---|
| 21 | ; Coyote's Guide to IDL Programming: http://www.dfanning.com/ |
---|
| 22 | ; |
---|
| 23 | ; CATEGORY: |
---|
| 24 | ; |
---|
| 25 | ; Utility routine for FSC_PSCONFIG__DEFINE. |
---|
| 26 | ; |
---|
| 27 | ; CALLING SEQUENCE: |
---|
| 28 | ; |
---|
| 29 | ; plotwindowObject = CW_PlotWindow(parent) |
---|
| 30 | ; |
---|
| 31 | ; REQUIRED INPUT PARAMETERS: |
---|
| 32 | ; |
---|
| 33 | ; parent - The parent base widget of this compound widget. |
---|
| 34 | ; |
---|
| 35 | ; RETURN VALUE: |
---|
| 36 | ; |
---|
| 37 | ; plotwindowObject - The object reference of the compound widget. |
---|
| 38 | ; |
---|
| 39 | ; KEYWORDS: |
---|
| 40 | ; |
---|
| 41 | ; COLOR - If set, display the window in "color". This is the default on 24-bit devices. |
---|
| 42 | ; DEBUG - Set this keyword to turn traceback error handling on in the error handling code. |
---|
| 43 | ; EVENT_PRO - The event procedure for the widget. Required for events to be generated. Otherwise, all events are handled internally. |
---|
| 44 | ; LANDSCAPE - If set, display the page in landscape mode. Otherwise the page is display in portrait mode. |
---|
| 45 | ; PAGESIZE - The "pagesize" of the widget. Possible values are: "LETTER", "LEDGER", "LEGAL", "A4", and "DISPLAY". |
---|
| 46 | ; UNITS - A string indicating INCHES or CENTIMETER units. DEVICE units represented by a null string, "". |
---|
| 47 | ; UVALUE - A user value for the caller of this program. |
---|
| 48 | ; WINDOWCOLOR - A three-element array specifying the background window color (RGB). |
---|
| 49 | ; WINDOWSIZE - The size of the "window" on the page. A four-element array of normalized coordinates in the form [x0, y0, x1, y1]. |
---|
| 50 | ; |
---|
| 51 | ; EVENT STRUCTURE: |
---|
| 52 | ; |
---|
| 53 | ; The event structure that is returned from this compound widget is defined like this, |
---|
| 54 | ; where the sizes and offsets locate the target "window" on the page in normalized units: |
---|
| 55 | ; |
---|
| 56 | ; event = {ID:0L, TOP:0L, HANDLER:0L, XSize:0.0, YSize:0.0, XOffset:0.0, YOffset:0.0} |
---|
| 57 | ; |
---|
| 58 | ; MODIFICATIONS: |
---|
| 59 | ; |
---|
| 60 | ; Written by David Fanning, 31 January 2000. |
---|
| 61 | ; Fixed a small bug that prevented it working on Macintosh computers. 26 Sept 2000. DWF. |
---|
| 62 | ; Added a "DISPLAY" page size, so the program can be used to position |
---|
| 63 | ; plots and other graphics in a display window. The "page area" will |
---|
| 64 | ; have the same aspect ratio is the current graphics window. 17 March 2001. DWF. |
---|
| 65 | ; Changed some of the tolerances for "closeness" from 0.1 to 0.025 to allow smaller |
---|
| 66 | ; sizing for colorbars and other small objects. 6 July 2005. DWF. |
---|
| 67 | ;- |
---|
| 68 | ; |
---|
| 69 | ;########################################################################### |
---|
| 70 | ; |
---|
| 71 | ; LICENSE |
---|
| 72 | ; |
---|
| 73 | ; This software is OSI Certified Open Source Software. |
---|
| 74 | ; OSI Certified is a certification mark of the Open Source Initiative. |
---|
| 75 | ; |
---|
| 76 | ; Copyright © 2000-2001 Fanning Software Consulting |
---|
| 77 | ; |
---|
| 78 | ; This software is provided "as-is", without any express or |
---|
| 79 | ; implied warranty. In no event will the authors be held liable |
---|
| 80 | ; for any damages arising from the use of this software. |
---|
| 81 | ; |
---|
| 82 | ; Permission is granted to anyone to use this software for any |
---|
| 83 | ; purpose, including commercial applications, and to alter it and |
---|
| 84 | ; redistribute it freely, subject to the following restrictions: |
---|
| 85 | ; |
---|
| 86 | ; 1. The origin of this software must not be misrepresented; you must |
---|
| 87 | ; not claim you wrote the original software. If you use this software |
---|
| 88 | ; in a product, an acknowledgment in the product documentation |
---|
| 89 | ; would be appreciated, but is not required. |
---|
| 90 | ; |
---|
| 91 | ; 2. Altered source versions must be plainly marked as such, and must |
---|
| 92 | ; not be misrepresented as being the original software. |
---|
| 93 | ; |
---|
| 94 | ; 3. This notice may not be removed or altered from any source distribution. |
---|
| 95 | ; |
---|
| 96 | ; For more information on Open Source Software, visit the Open Source |
---|
| 97 | ; web site: http://www.opensource.org. |
---|
| 98 | ; |
---|
| 99 | ;########################################################################### |
---|
| 100 | ; |
---|
| 101 | |
---|
| 102 | |
---|
| 103 | FUNCTION FSC_PLOTWINDOW_Error_Message, theMessage, Traceback=traceback, NoName=noName |
---|
| 104 | |
---|
| 105 | On_Error, 2 |
---|
| 106 | |
---|
| 107 | ; Check for presence and type of message. |
---|
| 108 | |
---|
| 109 | IF N_Elements(theMessage) EQ 0 THEN theMessage = !Error_State.Msg |
---|
| 110 | s = Size(theMessage) |
---|
| 111 | messageType = s[s[0]+1] |
---|
| 112 | IF messageType NE 7 THEN BEGIN |
---|
| 113 | Message, "The message parameter must be a string." |
---|
| 114 | ENDIF |
---|
| 115 | |
---|
| 116 | ; Get the call stack and the calling routine's name. |
---|
| 117 | |
---|
| 118 | Help, Calls=callStack |
---|
| 119 | callingRoutine = (StrSplit(StrCompress(callStack[1])," ", /Extract))[0] |
---|
| 120 | |
---|
| 121 | ; Are widgets supported? Doesn't matter in IDL 5.3 and higher. |
---|
| 122 | |
---|
| 123 | widgetsSupported = ((!D.Flags AND 65536L) NE 0) OR Float(!Version.Release) GE 5.3 |
---|
| 124 | IF widgetsSupported THEN BEGIN |
---|
| 125 | IF Keyword_Set(noName) THEN answer = Dialog_Message(theMessage) ELSE BEGIN |
---|
| 126 | IF StrUpCase(callingRoutine) EQ "$MAIN$" THEN answer = Dialog_Message(theMessage) ELSE $ |
---|
| 127 | answer = Dialog_Message(StrUpCase(callingRoutine) + ": " + theMessage) |
---|
| 128 | ENDELSE |
---|
| 129 | ENDIF ELSE BEGIN |
---|
| 130 | Message, theMessage, /Continue, /NoPrint, /NoName, /NoPrefix |
---|
| 131 | Print, '%' + callingRoutine + ': ' + theMessage |
---|
| 132 | answer = 'OK' |
---|
| 133 | ENDELSE |
---|
| 134 | |
---|
| 135 | ; Provide traceback information if requested. |
---|
| 136 | |
---|
| 137 | IF Keyword_Set(traceback) THEN BEGIN |
---|
| 138 | Help, /Last_Message, Output=traceback |
---|
| 139 | FOR j=0,N_Elements(traceback)-1 DO Print, traceback[j] |
---|
| 140 | ENDIF |
---|
| 141 | |
---|
| 142 | RETURN, answer |
---|
| 143 | END ;---------------------------------------------------------------------------------- |
---|
| 144 | |
---|
| 145 | |
---|
| 146 | |
---|
| 147 | FUNCTION FSC_PLOTWINDOW_Normalize, range, Position=position |
---|
| 148 | |
---|
| 149 | On_Error, 1 |
---|
| 150 | IF N_Params() EQ 0 THEN Message, 'Please pass range vector as argument.' |
---|
| 151 | |
---|
| 152 | IF (N_Elements(position) EQ 0) THEN position = [0.0, 1.0] ELSE $ |
---|
| 153 | position=Float(position) |
---|
| 154 | range = Float(range) |
---|
| 155 | |
---|
| 156 | scale = [((position[0]*range[1])-(position[1]*range[0])) / $ |
---|
| 157 | (range[1]-range[0]), (position[1]-position[0])/(range[1]-range[0])] |
---|
| 158 | |
---|
| 159 | RETURN, scale |
---|
| 160 | END ;---------------------------------------------------------------------------------- |
---|
| 161 | |
---|
| 162 | |
---|
| 163 | |
---|
| 164 | PRO FSC_PLOTWINDOW::Refresh |
---|
| 165 | self.theWindow->Draw, self.theView |
---|
| 166 | END ;---------------------------------------------------------------------------------- |
---|
| 167 | |
---|
| 168 | |
---|
| 169 | |
---|
| 170 | PRO FSC_PLOTWINDOW::SetWindowColor, theColor |
---|
| 171 | |
---|
| 172 | ; Set the background color of the view. |
---|
| 173 | |
---|
| 174 | self.theView->SetProperty, Color=theColor |
---|
| 175 | self.theWindow->Draw, self.theView |
---|
| 176 | END ;---------------------------------------------------------------------------------- |
---|
| 177 | |
---|
| 178 | |
---|
| 179 | |
---|
| 180 | FUNCTION FSC_PLOTWINDOW::GetUValue |
---|
| 181 | |
---|
| 182 | ; Get the user value of the compound widget. |
---|
| 183 | |
---|
| 184 | parent = Widget_Info(self.drawID, /Parent) |
---|
| 185 | Widget_Control, parent, Get_UValue=theValue |
---|
| 186 | RETURN, theValue |
---|
| 187 | END ;---------------------------------------------------------------------------------- |
---|
| 188 | |
---|
| 189 | |
---|
| 190 | |
---|
| 191 | PRO FSC_PLOTWINDOW::SetColor, on_off |
---|
| 192 | |
---|
| 193 | ; Sets the color of the plot window. Different colors |
---|
| 194 | ; depending on depth of visual class. |
---|
| 195 | |
---|
| 196 | IF on_off THEN BEGIN |
---|
| 197 | self.theBackground->SetProperty, Color=[255,255,150] |
---|
| 198 | self.thePlot->SetProperty, Color=[255, 0, 0] |
---|
| 199 | ENDIF ELSE BEGIN |
---|
| 200 | Device, Get_Visual_Depth=theDepth |
---|
| 201 | IF theDepth GT 8 THEN backColor = [210, 200, 180] ELSE backColor = [220, 220, 220] |
---|
| 202 | self.theBackground->SetProperty, Color=backColor |
---|
| 203 | self.thePlot->SetProperty, Color=[0, 0, 0] |
---|
| 204 | ENDELSE |
---|
| 205 | |
---|
| 206 | ; Draw the view. |
---|
| 207 | |
---|
| 208 | IF Obj_Valid(self.theWindow) THEN self.theWindow->Draw, self.theView |
---|
| 209 | END ;---------------------------------------------------------------------------------- |
---|
| 210 | |
---|
| 211 | |
---|
| 212 | |
---|
| 213 | PRO FSC_PLOTWINDOW::SetUnits, units |
---|
| 214 | |
---|
| 215 | ; Sets the type of units to report in. |
---|
| 216 | |
---|
| 217 | possibleUnits = ["INCHES", "CENTIMETERS", ""] |
---|
| 218 | units = StrUpCase(units) |
---|
| 219 | index = WHERE(possibleUnits EQ units, count) |
---|
| 220 | IF count EQ 0 THEN BEGIN |
---|
| 221 | ok = Dialog_Message('Unknown units: ' + units + '. Returning...') |
---|
| 222 | RETURN |
---|
| 223 | ENDIF |
---|
| 224 | self.units = units |
---|
| 225 | END ;---------------------------------------------------------------------------------- |
---|
| 226 | |
---|
| 227 | |
---|
| 228 | |
---|
| 229 | PRO FSC_PLOTWINDOW::GetWindowLocation, xsize, ysize, xoffset, yoffset |
---|
| 230 | |
---|
| 231 | ; Returns the current size and offsets of the plot window in |
---|
| 232 | ; units of inches or centimeters, as appropriate. |
---|
| 233 | |
---|
| 234 | xsize = self.xlength |
---|
| 235 | ysize = self.ylength |
---|
| 236 | xoffset = self.x1 |
---|
| 237 | yoffset = self.y1 |
---|
| 238 | |
---|
| 239 | factor = Float(self.pixels_per_inch) |
---|
| 240 | |
---|
| 241 | CASE self.units OF |
---|
| 242 | 'INCHES': BEGIN |
---|
| 243 | xsize_in_pixels = (xsize * self.xsize) |
---|
| 244 | ysize_in_pixels = (ysize * self.ysize) |
---|
| 245 | xoff_in_pixels = (xoffset * self.xsize) |
---|
| 246 | yoff_in_pixels = (yoffset * self.ysize) |
---|
| 247 | xsize = (xsize_in_pixels / factor) |
---|
| 248 | ysize = (ysize_in_pixels / factor) |
---|
| 249 | xoffset = (xoff_in_pixels / factor) |
---|
| 250 | yoffset = (yoff_in_pixels / factor) |
---|
| 251 | ENDCASE |
---|
| 252 | 'CENTIMETERS': BEGIN |
---|
| 253 | xsize_in_pixels = (xsize * self.xsize) |
---|
| 254 | ysize_in_pixels = (ysize * self.ysize) |
---|
| 255 | xoff_in_pixels = (xoffset * self.xsize) |
---|
| 256 | yoff_in_pixels = (yoffset * self.ysize) |
---|
| 257 | xsize = (xsize_in_pixels / factor * 2.54) |
---|
| 258 | ysize = (ysize_in_pixels / factor * 2.54) |
---|
| 259 | xoffset = (xoff_in_pixels / factor * 2.54) |
---|
| 260 | yoffset = (yoff_in_pixels / factor * 2.54) |
---|
| 261 | ENDCASE |
---|
| 262 | "" : |
---|
| 263 | ELSE: ok = Dialog_Message('Unknown units: ' + self.units + '. Returning...') |
---|
| 264 | ENDCASE |
---|
| 265 | |
---|
| 266 | END ;---------------------------------------------------------------------------------- |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | |
---|
| 270 | PRO FSC_PLOTWINDOW::SetWindowLocation, xsize, ysize, xoffset, yoffset |
---|
| 271 | |
---|
| 272 | ; Sets the location of the plot window in the view. |
---|
| 273 | ; Converts inches or centimeters to pixels. |
---|
| 274 | |
---|
| 275 | factor = Float(self.pixels_per_inch) |
---|
| 276 | |
---|
| 277 | CASE self.units OF |
---|
| 278 | 'INCHES': BEGIN |
---|
| 279 | xsize_in_pixels = (xsize * factor) |
---|
| 280 | ysize_in_pixels = (ysize * factor) |
---|
| 281 | xoff_in_pixels = (xoffset * factor) |
---|
| 282 | yoff_in_pixels = (yoffset * factor) |
---|
| 283 | x1 = 0.0 > (xoff_in_pixels / self.xsize) < 0.85 |
---|
| 284 | y1 = 0.0 > (yoff_in_pixels / self.ysize) < 0.85 |
---|
| 285 | x2 = (x1 + (xsize_in_pixels / self.xsize)) < 1.0 |
---|
| 286 | y2 = (y1 + (ysize_in_pixels / self.ysize)) < 1.0 |
---|
| 287 | ENDCASE |
---|
| 288 | 'CENTIMETERS': BEGIN |
---|
| 289 | xsize_in_pixels = (xsize * factor / 2.54) |
---|
| 290 | ysize_in_pixels = (ysize * factor / 2.54) |
---|
| 291 | xoff_in_pixels = (xoffset * factor / 2.54) |
---|
| 292 | yoff_in_pixels = (yoffset * factor / 2.54) |
---|
| 293 | x1 = 0.0 > (xoff_in_pixels / self.xsize) < 0.85 |
---|
| 294 | y1 = 0.0 > (yoff_in_pixels / self.ysize) < 0.85 |
---|
| 295 | x2 = (x1 + (xsize_in_pixels / self.xsize)) < 1.0 |
---|
| 296 | y2 = (y1 + (ysize_in_pixels / self.ysize)) < 1.0 |
---|
| 297 | ENDCASE |
---|
| 298 | "" : |
---|
| 299 | ELSE: ok = Dialog_Message('Unknown units: ' + self.units + '. Returning...') |
---|
| 300 | ENDCASE |
---|
| 301 | |
---|
| 302 | self.xlength = x2 - x1 |
---|
| 303 | self.ylength = y2 - y1 |
---|
| 304 | self.x1 = x1 |
---|
| 305 | self.x2 = x2 |
---|
| 306 | self.y1 = y1 |
---|
| 307 | self.y2 = y2 |
---|
| 308 | self->SetWindowSize, [x1, y1, x2, y2] |
---|
| 309 | |
---|
| 310 | END ;---------------------------------------------------------------------------------- |
---|
| 311 | |
---|
| 312 | PRO FSC_PLOTWINDOW::SetWindowSize, position |
---|
| 313 | |
---|
| 314 | ; Set the size of the plot window. Axes have to be |
---|
| 315 | ; rescaled appropriately. |
---|
| 316 | |
---|
| 317 | IF N_Elements(position) EQ 0 THEN position = [0.2, 0.2, 0.8, 0.8] |
---|
| 318 | |
---|
| 319 | x1 = position[0] |
---|
| 320 | y1 = position[1] |
---|
| 321 | x2 = position[2] |
---|
| 322 | y2 = position[3] |
---|
| 323 | |
---|
| 324 | new = FltArr(2,5) |
---|
| 325 | new[0,*] = [x1, x1, x2, x2, x1] |
---|
| 326 | new[1,*] = [y1, y2, y2, y1, y1] |
---|
| 327 | |
---|
| 328 | ; Modify the graphics objects. |
---|
| 329 | |
---|
| 330 | self.theBackground->SetProperty, Data=new |
---|
| 331 | xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05]) |
---|
| 332 | ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05]) |
---|
| 333 | |
---|
| 334 | self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0] |
---|
| 335 | self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0] |
---|
| 336 | self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys |
---|
| 337 | self.x1 = new[0,0] |
---|
| 338 | self.x2 = new[0,2] |
---|
| 339 | self.y1 = new[1,0] |
---|
| 340 | self.y2 = new[1,1] |
---|
| 341 | self.xlength = self.x2 - self.x1 |
---|
| 342 | self.ylength = self.y2 - self.y1 |
---|
| 343 | |
---|
| 344 | ; Draw the view after resetting the transformation matrix. |
---|
| 345 | |
---|
| 346 | self.theModel->Reset |
---|
| 347 | self.theWindow->Draw, self.theView |
---|
| 348 | END ;---------------------------------------------------------------------------------- |
---|
| 349 | |
---|
| 350 | |
---|
| 351 | |
---|
| 352 | PRO FSC_PLOTWINDOW::SetPageSize, pagesize, Landscape=landscape, TLB=tlb |
---|
| 353 | |
---|
| 354 | ; Sets the page size of the window. |
---|
| 355 | |
---|
| 356 | ; 200 pixels = 11 inches. |
---|
| 357 | ; Letter 8.5 x 11. |
---|
| 358 | ; Ledger 11 x 17. |
---|
| 359 | ; Legal 8.5 x 14. |
---|
| 360 | ; A4 8.27 x 11.7. |
---|
| 361 | |
---|
| 362 | STANDARD_SIZE = self.pixels_per_inch * 11.0 |
---|
| 363 | |
---|
| 364 | IF N_Elements(pagesize) EQ 0 THEN pagesize = "LETTER" |
---|
| 365 | pagesize = StrUpCase(pagesize) |
---|
| 366 | IF N_Elements(tlb) EQ 0 THEN tlb = self.base |
---|
| 367 | |
---|
| 368 | CASE pagesize OF |
---|
| 369 | 'LETTER': BEGIN |
---|
| 370 | xsize = STANDARD_SIZE * (8.5/11.0) |
---|
| 371 | ysize = STANDARD_SIZE |
---|
| 372 | ENDCASE |
---|
| 373 | 'LEDGER': BEGIN |
---|
| 374 | xsize = STANDARD_SIZE |
---|
| 375 | ysize = STANDARD_SIZE * (17.0/11.0) |
---|
| 376 | ENDCASE |
---|
| 377 | 'LEGAL': BEGIN |
---|
| 378 | xsize = STANDARD_SIZE * (8.5/11.0) |
---|
| 379 | ysize = STANDARD_SIZE * (14.0/11.0) |
---|
| 380 | ENDCASE |
---|
| 381 | 'A4': BEGIN |
---|
| 382 | xsize = STANDARD_SIZE * (8.27/11.0) |
---|
| 383 | ysize = STANDARD_SIZE * (11.7/11.0) |
---|
| 384 | ENDCASE |
---|
| 385 | 'DISPLAY': BEGIN |
---|
| 386 | xsize = 300 |
---|
| 387 | ratio = Float(!D.Y_Size) / !D.X_Size |
---|
| 388 | ysize = 300 * ratio |
---|
| 389 | ENDCASE |
---|
| 390 | ELSE: BEGIN |
---|
| 391 | ok = Dialog_Message('Unknown page size: ' + pagesize + '. Returning...') |
---|
| 392 | RETURN |
---|
| 393 | ENDCASE |
---|
| 394 | ENDCASE |
---|
| 395 | |
---|
| 396 | IF Keyword_Set(landscape) THEN BEGIN |
---|
| 397 | temp = xsize |
---|
| 398 | xsize = ysize |
---|
| 399 | ysize = temp |
---|
| 400 | ENDIF |
---|
| 401 | |
---|
| 402 | self.xsize = ROUND(xsize) |
---|
| 403 | self.ysize = ROUND(ysize) |
---|
| 404 | self.pagesize = pagesize |
---|
| 405 | |
---|
| 406 | ; Bugs in X windows implementation of window resizing necessitate |
---|
| 407 | ; destroying and re-creating the draw widget window. |
---|
| 408 | |
---|
| 409 | IF !D.Name NE 'X' THEN BEGIN |
---|
| 410 | |
---|
| 411 | self.theWindow->SetProperty, Dimensions=[xsize, ysize] |
---|
| 412 | |
---|
| 413 | ENDIF ELSE BEGIN |
---|
| 414 | |
---|
| 415 | Widget_Control, tlb, Update=0 |
---|
| 416 | Widget_Control, self.drawID, Kill_Notify="" |
---|
| 417 | Widget_Control, self.drawID, /Destroy |
---|
| 418 | self.drawID = Widget_Draw(self.base, Button_Events=1, Expose_Events=1, $ |
---|
| 419 | Retain=0, Graphics_Level=2, XSize=xsize, YSize=ysize, $ |
---|
| 420 | Event_Pro='FSC_PLOTWINDOW_Events', UValue=self, Renderer=1, $ |
---|
| 421 | Kill_Notify='FSC_PLOTWINDOW_Kill_Notify', Motion_Events=1) |
---|
| 422 | Widget_Control, self.drawID, /Realize |
---|
| 423 | Widget_Control, self.drawID, Get_Value=theWindow |
---|
| 424 | self.theWindow = theWindow |
---|
| 425 | Widget_Control, tlb, Update=1 |
---|
| 426 | |
---|
| 427 | ENDELSE |
---|
| 428 | |
---|
| 429 | self.thewindow->Draw, self.theView |
---|
| 430 | |
---|
| 431 | END ;---------------------------------------------------------------------------------- |
---|
| 432 | |
---|
| 433 | |
---|
| 434 | |
---|
| 435 | FUNCTION FSC_PLOTWINDOW::GetPagePixels, pagesize, Landscape=landscape |
---|
| 436 | |
---|
| 437 | ; Given the page size or type, returns the xsize and ysize |
---|
| 438 | ; of the draw widget in pixels. |
---|
| 439 | |
---|
| 440 | ; 198 pixels = 11 inches. |
---|
| 441 | ; Letter 8.5 x 11. |
---|
| 442 | ; Ledger 11 x 17. |
---|
| 443 | ; Legal 8.5 x 14. |
---|
| 444 | ; A4 8.27 x 11.7. |
---|
| 445 | |
---|
| 446 | STANDARD_SIZE = self.pixels_per_inch * 11.0 |
---|
| 447 | |
---|
| 448 | IF N_Elements(pagesize) EQ 0 THEN pagesize = "LETTER" |
---|
| 449 | pagesize = StrUpCase(pagesize) |
---|
| 450 | |
---|
| 451 | CASE pagesize OF |
---|
| 452 | 'LETTER': BEGIN |
---|
| 453 | xsize = STANDARD_SIZE * (8.5/11.0) |
---|
| 454 | ysize = STANDARD_SIZE |
---|
| 455 | ENDCASE |
---|
| 456 | 'LEDGER': BEGIN |
---|
| 457 | xsize = STANDARD_SIZE |
---|
| 458 | ysize = STANDARD_SIZE * (17.0/11.0) |
---|
| 459 | ENDCASE |
---|
| 460 | 'LEGAL': BEGIN |
---|
| 461 | xsize = STANDARD_SIZE * (8.5/11.0) |
---|
| 462 | ysize = STANDARD_SIZE * (14.0/11.0) |
---|
| 463 | ENDCASE |
---|
| 464 | 'A4': BEGIN |
---|
| 465 | xsize = STANDARD_SIZE * (8.27/11.0) |
---|
| 466 | ysize = STANDARD_SIZE * (11.7/11.0) |
---|
| 467 | ENDCASE |
---|
| 468 | 'DISPLAY': BEGIN |
---|
| 469 | xsize = 300 |
---|
| 470 | ratio = Float(!D.Y_Size) / !D.X_Size |
---|
| 471 | ; Check for *very* strange windows. |
---|
| 472 | IF ratio LT 0.2 THEN ratio = 1.0 |
---|
| 473 | IF ratio GT 5 THEN ratio = 1.0 |
---|
| 474 | ysize = 300 * ratio |
---|
| 475 | ENDCASE |
---|
| 476 | ENDCASE |
---|
| 477 | |
---|
| 478 | IF Keyword_Set(landscape) THEN BEGIN |
---|
| 479 | temp = xsize |
---|
| 480 | xsize = ysize |
---|
| 481 | ysize = temp |
---|
| 482 | ENDIF |
---|
| 483 | |
---|
| 484 | RETURN, [ROUND(xsize), ROUND(ysize)] |
---|
| 485 | |
---|
| 486 | END ;---------------------------------------------------------------------------------- |
---|
| 487 | |
---|
| 488 | |
---|
| 489 | |
---|
| 490 | FUNCTION FSC_PLOTWINDOW::GetPosition |
---|
| 491 | |
---|
| 492 | ; Returns the current position of the plot window in |
---|
| 493 | ; the view. Normalized coordinates. |
---|
| 494 | |
---|
| 495 | RETURN, [self.x1, self.y1, self.x2, self.y2] |
---|
| 496 | END ;---------------------------------------------------------------------------------- |
---|
| 497 | |
---|
| 498 | |
---|
| 499 | |
---|
| 500 | PRO FSC_PLOTWINDOW::Resize, event, direction |
---|
| 501 | |
---|
| 502 | ; Performs window resizing, depending upon which of eight |
---|
| 503 | ; possible directions you can move the window. |
---|
| 504 | |
---|
| 505 | IF direction EQ 'NONE' OR direction EQ 'MOVE' THEN BEGIN |
---|
| 506 | RETURN |
---|
| 507 | ENDIF |
---|
| 508 | |
---|
| 509 | ; Calculate movement in normalized coordinates. Update start coords. |
---|
| 510 | |
---|
| 511 | deltax = (event.x - self.currentX) / self.xsize |
---|
| 512 | deltay = (event.y - self.currentY) / self.ysize |
---|
| 513 | self.currentX = event.x |
---|
| 514 | self.currentY = event.y |
---|
| 515 | |
---|
| 516 | CASE direction OF |
---|
| 517 | 'SE': BEGIN |
---|
| 518 | x1 = self.x1 |
---|
| 519 | x2 = (self.x2 + deltax) < 1.0 |
---|
| 520 | y1 = (self.y1 + deltay) > 0.0 |
---|
| 521 | y2 = self.y2 |
---|
| 522 | IF x2 LE x1 + 0.025 THEN x2 = x1 + 0.025 |
---|
| 523 | IF y1 GE y2 - 0.025 THEN y1 = y2 - 0.025 |
---|
| 524 | END |
---|
| 525 | 'E' : BEGIN |
---|
| 526 | x1 = self.x1 |
---|
| 527 | x2 = (self.x2 + deltax) < 1.0 |
---|
| 528 | y1 = self.y1 |
---|
| 529 | y2 = self.y2 |
---|
| 530 | IF x2 LE x1 + 0.025 THEN x2 = x1 + 0.1 |
---|
| 531 | END |
---|
| 532 | 'SW': BEGIN |
---|
| 533 | x1 = (self.x1 + deltax) > 0.0 |
---|
| 534 | x2 = self.x2 |
---|
| 535 | y1 = (self.y1 + deltay) > 0.0 |
---|
| 536 | y2 = self.y2 |
---|
| 537 | IF x1 GE x2 - 0.025 THEN x1 = x2 - 0.025 |
---|
| 538 | IF y1 GE y2 - 0.025 THEN y1 = y2 - 0.025 |
---|
| 539 | END |
---|
| 540 | 'S' : BEGIN |
---|
| 541 | x1 = self.x1 |
---|
| 542 | x2 = self.x2 |
---|
| 543 | y1 = (self.y1 + deltay) > 0.0 |
---|
| 544 | y2 = self.y2 |
---|
| 545 | IF y1 GE y2 - 0.025 THEN y1 = y2 - 0.025 |
---|
| 546 | END |
---|
| 547 | 'N' : BEGIN |
---|
| 548 | x1 = self.x1 |
---|
| 549 | x2 = self.x2 |
---|
| 550 | y1 = self.y1 |
---|
| 551 | y2 = (self.y2 + deltay) < 1.0 |
---|
| 552 | IF y2 LE y1 + 0.025 THEN y2 = y1 + 0.025 |
---|
| 553 | END |
---|
| 554 | 'NE': BEGIN |
---|
| 555 | x1 = self.x1 |
---|
| 556 | x2 = (self.x2 + deltax) < 1.0 |
---|
| 557 | y1 = self.y1 |
---|
| 558 | y2 = (self.y2 + deltay) < 1.0 |
---|
| 559 | IF x2 LE x1 + 0.025 THEN x2 = x1 + 0.025 |
---|
| 560 | IF y2 LE y1 + 0.025 THEN y2 = y1 + 0.025 |
---|
| 561 | END |
---|
| 562 | 'W' : BEGIN |
---|
| 563 | x1 = (self.x1 + deltax) > 0.0 |
---|
| 564 | x2 = self.x2 |
---|
| 565 | y1 = self.y1 |
---|
| 566 | y2 = self.y2 |
---|
| 567 | IF x1 GE x2 - 0.025 THEN x1 = x2 - 0.025 |
---|
| 568 | END |
---|
| 569 | 'NW': BEGIN |
---|
| 570 | x1 = (self.x1 + deltax) > 0.0 |
---|
| 571 | x2 = self.x2 |
---|
| 572 | y1 = self.y1 |
---|
| 573 | y2 = (self.y2 + deltay) < 1.0 |
---|
| 574 | IF x1 GE x2 - 0.025 THEN x1 = x2 - 0.025 |
---|
| 575 | IF y2 LE y1 + 0.025 THEN y2 = y1 + 0.025 |
---|
| 576 | |
---|
| 577 | END |
---|
| 578 | ENDCASE |
---|
| 579 | |
---|
| 580 | new = FltArr(2,5) |
---|
| 581 | new[0,*] = [x1, x1, x2, x2, x1] |
---|
| 582 | new[1,*] = [y1, y2, y2, y1, y1] |
---|
| 583 | |
---|
| 584 | ; Modify the graphics objects. |
---|
| 585 | |
---|
| 586 | self.theBackground->SetProperty, Data=new |
---|
| 587 | |
---|
| 588 | xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05]) > 10e-6 |
---|
| 589 | ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05]) > 10e-6 |
---|
| 590 | |
---|
| 591 | self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0] |
---|
| 592 | self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0] |
---|
| 593 | self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys |
---|
| 594 | self.x1 = new[0,0] |
---|
| 595 | self.x2 = new[0,2] |
---|
| 596 | self.y1 = new[1,0] |
---|
| 597 | self.y2 = new[1,1] |
---|
| 598 | self.xlength = self.x2 - self.x1 |
---|
| 599 | self.ylength = self.y2 - self.y1 |
---|
| 600 | |
---|
| 601 | ; Draw the view after resetting the transformation matrix. |
---|
| 602 | |
---|
| 603 | self.theModel->Reset |
---|
| 604 | self.theWindow->Draw, self.theView |
---|
| 605 | |
---|
| 606 | END ;---------------------------------------------------------------------------------- |
---|
| 607 | |
---|
| 608 | |
---|
| 609 | |
---|
| 610 | PRO FSC_PLOTWINDOW::CenterPlot, event |
---|
| 611 | |
---|
| 612 | ; Centers the plot in the window. |
---|
| 613 | |
---|
| 614 | new = FltArr(2,5) |
---|
| 615 | self.x1 = (1.0 - self.xlength) / 2.0 |
---|
| 616 | self.x2 = self.x1 + self.xlength |
---|
| 617 | self.y1 = (1.0 - self.ylength) / 2.0 |
---|
| 618 | self.y2 = self.y1 + self.ylength |
---|
| 619 | |
---|
| 620 | new[0,*] = [self.x1, self.x1, self.x2, self.x2, self.x1] |
---|
| 621 | new[1,*] = [self.y1, self.y2, self.y2, self.y1, self.y1] |
---|
| 622 | |
---|
| 623 | ; Modify the graphics objects. |
---|
| 624 | |
---|
| 625 | self.theBackground->SetProperty, Data=new |
---|
| 626 | |
---|
| 627 | xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05]) |
---|
| 628 | ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05]) |
---|
| 629 | |
---|
| 630 | self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0] |
---|
| 631 | self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0] |
---|
| 632 | self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys |
---|
| 633 | self.x1 = new[0,0] |
---|
| 634 | self.x2 = new[0,2] |
---|
| 635 | self.y1 = new[1,0] |
---|
| 636 | self.y2 = new[1,1] |
---|
| 637 | |
---|
| 638 | ; Draw the view after resetting the transformation matrix. |
---|
| 639 | |
---|
| 640 | self.theModel->Reset |
---|
| 641 | self.theWindow->Draw, self.theView |
---|
| 642 | |
---|
| 643 | END ;---------------------------------------------------------------------------------- |
---|
| 644 | |
---|
| 645 | |
---|
| 646 | |
---|
| 647 | PRO FSC_PLOTWINDOW::MovePlot, event |
---|
| 648 | |
---|
| 649 | ; Calculate movement in normalized coordinates. Update start coords. |
---|
| 650 | |
---|
| 651 | deltax = (event.x - self.currentX) / self.xsize |
---|
| 652 | deltay = (event.y - self.currentY) / self.ysize |
---|
| 653 | self.currentX = event.x |
---|
| 654 | self.currentY = event.y |
---|
| 655 | |
---|
| 656 | ; Translate the selected model. |
---|
| 657 | |
---|
| 658 | self.theModel->Translate, deltax, deltay, 0 |
---|
| 659 | |
---|
| 660 | ; Get the current transformation matrix. |
---|
| 661 | |
---|
| 662 | matrix = self.theModel->GetCTM() |
---|
| 663 | |
---|
| 664 | ; Get the vertices of the polygon object. |
---|
| 665 | |
---|
| 666 | self.theBackground->GetProperty, Data=vertices |
---|
| 667 | |
---|
| 668 | ; Apply the transformation matrix to the vertices. |
---|
| 669 | |
---|
| 670 | new = FltArr(2,5) |
---|
| 671 | FOR j=0,4 DO BEGIN |
---|
| 672 | v = [vertices[*, j], 0.0, 1.0] |
---|
| 673 | new[*, j] = (matrix ## v)[0:1] |
---|
| 674 | ENDFOR |
---|
| 675 | |
---|
| 676 | IF new[0,0] LT 0.0 THEN new[0,*] = [0.0, 0.0, self.xlength, self.xlength, 0.0] |
---|
| 677 | IF new[0,2] GT 1.0 THEN new[0,*] = [1.0-self.xlength, 1.0-self.xlength, 1.0, 1.0, 1.0-self.xlength] |
---|
| 678 | IF new[1,0] LT 0.0 THEN new[1,*] = [0.0, self.ylength, self.ylength, 0.0, 0.0] |
---|
| 679 | IF new[1,1] GT 1.0 THEN new[1,*] = [1.0-self.ylength, 1.0, 1.0, 1.0-self.ylength, 1.0-self.ylength] |
---|
| 680 | |
---|
| 681 | ; Modify the graphics objects. |
---|
| 682 | |
---|
| 683 | self.theBackground->SetProperty, Data=new |
---|
| 684 | |
---|
| 685 | xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05]) |
---|
| 686 | ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05]) |
---|
| 687 | |
---|
| 688 | self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0] |
---|
| 689 | self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0] |
---|
| 690 | self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys |
---|
| 691 | self.x1 = new[0,0] |
---|
| 692 | self.x2 = new[0,2] |
---|
| 693 | self.y1 = new[1,0] |
---|
| 694 | self.y2 = new[1,1] |
---|
| 695 | |
---|
| 696 | ; Draw the view after resetting the transformation matrix. |
---|
| 697 | |
---|
| 698 | self.theModel->Reset |
---|
| 699 | self.theWindow->Draw, self.theView |
---|
| 700 | |
---|
| 701 | END ;---------------------------------------------------------------------------------- |
---|
| 702 | |
---|
| 703 | |
---|
| 704 | |
---|
| 705 | FUNCTION FSC_PLOTWINDOW::WhichButtonReleased, event |
---|
| 706 | |
---|
| 707 | ; Determines which button was used. |
---|
| 708 | |
---|
| 709 | buttons = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT'] |
---|
| 710 | RETURN, buttons[event.release] |
---|
| 711 | END ;---------------------------------------------------------------------------------- |
---|
| 712 | |
---|
| 713 | |
---|
| 714 | |
---|
| 715 | FUNCTION FSC_PLOTWINDOW::WhichButtonPressed, event |
---|
| 716 | |
---|
| 717 | ; Determines which button was used. |
---|
| 718 | |
---|
| 719 | buttons = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT'] |
---|
| 720 | RETURN, buttons[event.press] |
---|
| 721 | END ;---------------------------------------------------------------------------------- |
---|
| 722 | |
---|
| 723 | |
---|
| 724 | |
---|
| 725 | FUNCTION FSC_PLOTWINDOW::InTarget, x, y, DIRECTION=direction |
---|
| 726 | |
---|
| 727 | ; Given a location of the cursor in the window returns the |
---|
| 728 | ; target location and the direction the window should be |
---|
| 729 | ; resized in. Have to be within 2.5% of window edge to be |
---|
| 730 | ; in moveable target. |
---|
| 731 | |
---|
| 732 | x = x / self.xsize |
---|
| 733 | y = y / self.ysize |
---|
| 734 | |
---|
| 735 | xtest = -1 |
---|
| 736 | IF x GE self.x1 AND x LE self.x1 + 0.025 THEN xtest = 0 |
---|
| 737 | IF x GT self.x1 + 0.025 AND x LT self.x2 - 0.025 THEN xtest = 1 |
---|
| 738 | IF x GE self.x2 - 0.025 AND x LE self.x2 THEN xtest = 2 |
---|
| 739 | ytest = -1 |
---|
| 740 | IF y GE self.y1 AND y LE self.y1 + 0.1 THEN ytest = 0 |
---|
| 741 | IF y GT self.y1 + 0.025 AND y LT self.y2 - 0.025 THEN ytest = 1 |
---|
| 742 | IF y GE self.y2 - 0.025 AND y LE self.y2 THEN ytest = 2 |
---|
| 743 | |
---|
| 744 | IF xtest EQ -1 OR ytest EQ -1 THEN BEGIN |
---|
| 745 | retVal = 'ORIGINAL' |
---|
| 746 | direction = 'NONE' |
---|
| 747 | ENDIF |
---|
| 748 | IF xtest EQ 0 AND ytest EQ 0 THEN BEGIN |
---|
| 749 | retVal = 'SIZE_SW' |
---|
| 750 | direction = 'SW' |
---|
| 751 | ENDIF |
---|
| 752 | IF xtest EQ 0 AND ytest EQ 1 THEN BEGIN |
---|
| 753 | retVal = 'SIZE_EW' |
---|
| 754 | direction = 'W' |
---|
| 755 | ENDIF |
---|
| 756 | IF xtest EQ 0 AND ytest EQ 2 THEN BEGIN |
---|
| 757 | retVal = 'SIZE_NW' |
---|
| 758 | direction = 'NW' |
---|
| 759 | ENDIF |
---|
| 760 | IF xtest EQ 1 AND ytest EQ 0 THEN BEGIN |
---|
| 761 | retVal = 'SIZE_NS' |
---|
| 762 | direction = 'S' |
---|
| 763 | ENDIF |
---|
| 764 | IF xtest EQ 1 AND ytest EQ 1 THEN BEGIN |
---|
| 765 | retVal = 'MOVE' |
---|
| 766 | direction = 'MOVE' |
---|
| 767 | ENDIF |
---|
| 768 | IF xtest EQ 1 AND ytest EQ 2 THEN BEGIN |
---|
| 769 | retVal = 'SIZE_NS' |
---|
| 770 | direction = 'N' |
---|
| 771 | ENDIF |
---|
| 772 | IF xtest EQ 2 AND ytest EQ 0 THEN BEGIN |
---|
| 773 | retVal = 'SIZE_SE' |
---|
| 774 | direction = 'SE' |
---|
| 775 | ENDIF |
---|
| 776 | IF xtest EQ 2 AND ytest EQ 1 THEN BEGIN |
---|
| 777 | retVal = 'SIZE_EW' |
---|
| 778 | direction = 'E' |
---|
| 779 | ENDIF |
---|
| 780 | IF xtest EQ 2 AND ytest EQ 2 THEN BEGIN |
---|
| 781 | retVal = 'SIZE_NE' |
---|
| 782 | direction = 'NE' |
---|
| 783 | ENDIF |
---|
| 784 | |
---|
| 785 | RETURN, retVal |
---|
| 786 | END ;---------------------------------------------------------------------------------- |
---|
| 787 | |
---|
| 788 | |
---|
| 789 | |
---|
| 790 | PRO FSC_PLOTWINDOW::Realize |
---|
| 791 | |
---|
| 792 | Widget_Control, self.drawID, Get_Value=theWindow |
---|
| 793 | self.theWindow = theWindow |
---|
| 794 | END ;---------------------------------------------------------------------------------- |
---|
| 795 | |
---|
| 796 | |
---|
| 797 | |
---|
| 798 | PRO FSC_PLOTWINDOW_Notify_Realize, drawID |
---|
| 799 | Widget_Control, drawID, Get_UValue=self |
---|
| 800 | self->Realize |
---|
| 801 | END ;---------------------------------------------------------------------------------- |
---|
| 802 | |
---|
| 803 | |
---|
| 804 | |
---|
| 805 | PRO FSC_PLOTWINDOW::Process_Events, event |
---|
| 806 | |
---|
| 807 | ; Handles draw widget events. |
---|
| 808 | |
---|
| 809 | possibleEvents = ['DOWN', 'UP', 'MOTION', 'SCROLL', 'EXPOSE'] |
---|
| 810 | thisEvent = possibleEvents[event.type] |
---|
| 811 | |
---|
| 812 | ; Are we inside a target? If so, change cursor. |
---|
| 813 | |
---|
| 814 | target = self->InTarget(event.x, event.y, Direction=direction) |
---|
| 815 | self.theWindow->SetCurrentCursor, target |
---|
| 816 | |
---|
| 817 | |
---|
| 818 | ; What kind of event is this? |
---|
| 819 | |
---|
| 820 | CASE thisEvent OF |
---|
| 821 | 'EXPOSE': self.theWindow->Draw, self.theView |
---|
| 822 | 'UP': BEGIN |
---|
| 823 | thisButton = self->WhichButtonReleased(event) |
---|
| 824 | Widget_Control, event.id, Clear_Events=1 |
---|
| 825 | CASE self.action OF |
---|
| 826 | 'MOVE': BEGIN |
---|
| 827 | self.currentX = -1 |
---|
| 828 | self.currentY = -1 |
---|
| 829 | self.action = "" |
---|
| 830 | self->GetWindowLocation, xsize, ysize, xoffset, yoffset |
---|
| 831 | IF self.event_pro NE "" THEN BEGIN |
---|
| 832 | thisEvent = {ID:event.id, TOP:event.top, HANDLER:event.handler, $ |
---|
| 833 | xsize:xsize, ysize:ysize, xoffset:xoffset, yoffset:yoffset} |
---|
| 834 | Call_Procedure, self.event_pro, thisEvent |
---|
| 835 | ENDIF |
---|
| 836 | ENDCASE |
---|
| 837 | 'ORIGINAL': |
---|
| 838 | 'RESIZE': BEGIN |
---|
| 839 | self.currentX = -1 |
---|
| 840 | self.currentY = -1 |
---|
| 841 | self.action = "" |
---|
| 842 | self.direction = "NONE" |
---|
| 843 | self->GetWindowLocation, xsize, ysize, xoffset, yoffset |
---|
| 844 | IF self.event_pro NE "" THEN BEGIN |
---|
| 845 | thisEvent = {ID:event.id, TOP:event.top, HANDLER:event.handler, $ |
---|
| 846 | xsize:xsize, ysize:ysize, xoffset:xoffset, yoffset:yoffset} |
---|
| 847 | Call_Procedure, self.event_pro, thisEvent |
---|
| 848 | ENDIF |
---|
| 849 | ENDCASE |
---|
| 850 | ELSE: |
---|
| 851 | ENDCASE |
---|
| 852 | ENDCASE |
---|
| 853 | 'DOWN': BEGIN |
---|
| 854 | thisButton = self->WhichButtonPressed(event) |
---|
| 855 | IF thisButton EQ 'MIDDLE' THEN BEGIN |
---|
| 856 | self->CenterPlot, event |
---|
| 857 | self->GetWindowLocation, xsize, ysize, xoffset, yoffset |
---|
| 858 | IF self.event_pro NE "" THEN BEGIN |
---|
| 859 | thisEvent = {ID:event.id, TOP:event.top, HANDLER:event.handler, $ |
---|
| 860 | xsize:xsize, ysize:ysize, xoffset:xoffset, yoffset:yoffset} |
---|
| 861 | Call_Procedure, self.event_pro, thisEvent |
---|
| 862 | ENDIF |
---|
| 863 | RETURN |
---|
| 864 | ENDIF |
---|
| 865 | CASE target OF |
---|
| 866 | 'ORIGINAL': RETURN |
---|
| 867 | 'MOVE': BEGIN |
---|
| 868 | self.currentX = event.x |
---|
| 869 | self.currentY = event.y |
---|
| 870 | self.action = 'MOVE' |
---|
| 871 | ENDCASE |
---|
| 872 | ELSE: BEGIN |
---|
| 873 | self.currentX = event.x |
---|
| 874 | self.currentY = event.y |
---|
| 875 | self.action = 'RESIZE' |
---|
| 876 | self.direction = direction |
---|
| 877 | ENDCASE |
---|
| 878 | ENDCASE |
---|
| 879 | ENDCASE |
---|
| 880 | 'MOTION': BEGIN |
---|
| 881 | CASE self.action OF |
---|
| 882 | 'MOVE': self->MovePlot, event |
---|
| 883 | 'RESIZE': self->Resize, event, self.direction |
---|
| 884 | ELSE: |
---|
| 885 | ENDCASE |
---|
| 886 | ENDCASE |
---|
| 887 | ENDCASE |
---|
| 888 | |
---|
| 889 | END ;---------------------------------------------------------------------------------- |
---|
| 890 | |
---|
| 891 | |
---|
| 892 | |
---|
| 893 | PRO FSC_PLOTWINDOW_Events, event |
---|
| 894 | |
---|
| 895 | ; Widget event handler. Calls event handler method. |
---|
| 896 | |
---|
| 897 | Widget_Control, event.id, Get_UValue=self |
---|
| 898 | self->Process_Events, event |
---|
| 899 | END ;---------------------------------------------------------------------------------- |
---|
| 900 | |
---|
| 901 | |
---|
| 902 | |
---|
| 903 | PRO FSC_PLOTWINDOW_Kill_Notify, drawID |
---|
| 904 | |
---|
| 905 | ; Destroy the plot window object when the window is destroyed. |
---|
| 906 | |
---|
| 907 | Widget_Control, drawID, Get_UValue=self |
---|
| 908 | Obj_Destroy, self |
---|
| 909 | END ;---------------------------------------------------------------------------------- |
---|
| 910 | |
---|
| 911 | |
---|
| 912 | |
---|
| 913 | PRO FSC_PLOTWINDOW::CLEANUP |
---|
| 914 | Obj_Destroy, self.theModel |
---|
| 915 | Obj_Destroy, self.theWindow |
---|
| 916 | Obj_Destroy, self.theView |
---|
| 917 | Obj_Destroy, self.plotModel |
---|
| 918 | END ;---------------------------------------------------------------------------------- |
---|
| 919 | |
---|
| 920 | |
---|
| 921 | |
---|
| 922 | FUNCTION FSC_PLOTWINDOW::INIT, $ |
---|
| 923 | parent, $ ; The parent base widget of this compound widget. Required. |
---|
| 924 | PageSize=pagesize, $ ; The "pagesize" of the widget. Possible values are: "LETTER", "LEDGER", "LEGAL", "A4", and "DISPLAY". |
---|
| 925 | WindowSize=windowsize, $ ; The size of the "window" on the page. A four-element array of normalized coordinates in the form [x0, y0, x1, y1]. |
---|
| 926 | Event_Pro=event_pro, $ ; The event procedure for the widget. |
---|
| 927 | Units=units, $ ; A string indicating INCHES or CENTIMETER units. DEVICE units represented by a null string, "". |
---|
| 928 | UValue=uvalue, $ ; A user value for the caller of this program. |
---|
| 929 | Landscape=landscape, $ ; If set, display the page in landscape mode. Otherwise the page is display in portrait mode. |
---|
| 930 | Color=color, $ ; If set, display the window in "color". This is the default on 24-bit devices. |
---|
| 931 | Debug=debug, $ ; Set this keyword to turn traceback error handling on in the error handling code. |
---|
| 932 | WindowColor=windowColor ; A three-element array specifying the background window color (RGB). |
---|
| 933 | |
---|
| 934 | Catch, theError |
---|
| 935 | IF theError NE 0 THEN BEGIN |
---|
| 936 | Catch, /Cancel |
---|
| 937 | ok = FSC_PlotWindow_Error_Message(Traceback=Keyword_Set(debug)) |
---|
| 938 | RETURN, 0 |
---|
| 939 | ENDIF |
---|
| 940 | |
---|
| 941 | IF N_Elements(pagesize) EQ 0 THEN pageSize = 'LETTER' |
---|
| 942 | IF N_Elements(windowsize) EQ 0 THEN windowsize = [0.2, 0.2, 0.8, 0.8] |
---|
| 943 | IF N_Elements(event_pro) EQ 0 THEN event_pro = "" |
---|
| 944 | IF N_Elements(units) EQ 0 THEN units="" |
---|
| 945 | IF N_Elements(uvalue) EQ 0 THEN uvalue="" |
---|
| 946 | IF N_Elements(landscape) EQ 0 THEN landscape = 0 |
---|
| 947 | Device, Get_Visual_Depth=theDepth |
---|
| 948 | self.pixels_per_inch = 18 |
---|
| 949 | sizes = self->GetPagePixels(pageSize, Landscape=landscape) |
---|
| 950 | xsize = sizes[0] |
---|
| 951 | ysize = sizes[1] |
---|
| 952 | IF N_Elements(windowColor) EQ 0 THEN $ |
---|
| 953 | IF theDepth GT 8 THEN windowColor = [60, 140, 140] ELSE windowColor = [80, 80, 80] |
---|
| 954 | |
---|
| 955 | IF N_Elements(color) EQ 0 THEN BEGIN |
---|
| 956 | Device, Get_Visual_Depth=theDepth |
---|
| 957 | IF theDepth GT 8 THEN color = 1 ELSE color = 0 |
---|
| 958 | ENDIF ELSE color = Keyword_Set(color) |
---|
| 959 | |
---|
| 960 | x1 = windowsize[0] |
---|
| 961 | x2 = windowsize[2] |
---|
| 962 | y1 = windowsize[1] |
---|
| 963 | y2 = windowsize[3] |
---|
| 964 | |
---|
| 965 | data = Findgen(101) |
---|
| 966 | data = Sin(data/5) / Exp(data/20) |
---|
| 967 | |
---|
| 968 | self.thePlot = Obj_New('IDLgrPlot', data, Color=[0,0,0]) |
---|
| 969 | self.thePlot->SetProperty, XCoord_Conv=FSC_PlotWindow_Normalize([0,100], $ |
---|
| 970 | Position=[x1+0.05, x2-0.05]) > 10e-6, $ |
---|
| 971 | YCoord_Conv=FSC_PlotWindow_Normalize([-1,1], Position=[y1+0.05, y2-0.05]) > 10e-6 |
---|
| 972 | |
---|
| 973 | self.theXAxis = Obj_New('IDLgrAxis', 0, Color=[0,0,0], Ticklen=0.025, $ |
---|
| 974 | Minor=4, Range=[0,100], Location=[1000, y1+0.05 , 0.0], /NoText) |
---|
| 975 | self.theXAxis->SetProperty, XCoord_Conv=FSC_PlotWindow_Normalize([0,100], $ |
---|
| 976 | Position=[x1+0.05, x2-0.05]) > 10e-6 |
---|
| 977 | |
---|
| 978 | self.theYAxis = Obj_New('IDLgrAxis', 1, Color=[0,0,0], Ticklen=0.025, $ |
---|
| 979 | Minor=4, Range=[-1,1], Location=[x1+0.05, 1000, 0.0], /NoText) |
---|
| 980 | self.theYAxis->SetProperty, YCoord_Conv=FSC_PlotWindow_Normalize([-1,1], $ |
---|
| 981 | Position=[y1+0.05, y2-0.05]) > 10e-6 |
---|
| 982 | |
---|
| 983 | self.plotModel = Obj_New('IDLgrModel') |
---|
| 984 | |
---|
| 985 | IF theDepth GT 8 THEN theColor = [210, 200, 180] ELSE theColor = [255,255,255] |
---|
| 986 | self.theBackground = Obj_New('IDLgrPolygon', Color=theColor, $ |
---|
| 987 | [x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1]) |
---|
| 988 | |
---|
| 989 | self.theModel = Obj_New('IDLgrModel', Select_Target=1) |
---|
| 990 | self.theModel->Add, self.theBackground |
---|
| 991 | |
---|
| 992 | self.plotModel->Add, self.theXAxis |
---|
| 993 | self.plotModel->Add, self.theYAxis |
---|
| 994 | self.plotModel->Add, self.thePlot |
---|
| 995 | self.plotModel->Translate, 0, 0, 0.1 |
---|
| 996 | |
---|
| 997 | self.theView = Obj_New('IDLgrView', Color=windowColor, Viewplane_Rect=[0,0,1,1]) |
---|
| 998 | self.theView->Add, self.theModel |
---|
| 999 | self.theView->Add, self.plotModel |
---|
| 1000 | |
---|
| 1001 | self.base = Widget_Base(parent, UValue=uvalue) |
---|
| 1002 | self.drawID = Widget_Draw(self.base, Button_Events=1, Expose_Events=1, $ |
---|
| 1003 | Retain=0, Graphics_Level=2, XSize=xsize, YSize=ysize, $ |
---|
| 1004 | Event_Pro='FSC_PLOTWINDOW_Events', UValue=self, Renderer=1, $ |
---|
| 1005 | Kill_Notify='FSC_PLOTWINDOW_Kill_Notify', Motion_Events=1, $ |
---|
| 1006 | Notify_Realize='FSC_PLOTWINDOW_Notify_Realize') |
---|
| 1007 | |
---|
| 1008 | self.pagesize = pagesize |
---|
| 1009 | self.landscape = Keyword_Set(landscape) |
---|
| 1010 | self.x1 = x1 |
---|
| 1011 | self.x2 = x2 |
---|
| 1012 | self.y1 = y1 |
---|
| 1013 | self.y2 = y2 |
---|
| 1014 | self.xsize = Float(xsize) |
---|
| 1015 | self.ysize = Float(ysize) |
---|
| 1016 | self.currentX = -1 |
---|
| 1017 | self.currentY = -1 |
---|
| 1018 | self.xlength = x2 - x1 |
---|
| 1019 | self.ylength = y2 - y1 |
---|
| 1020 | self.units = units |
---|
| 1021 | self.event_pro = event_pro |
---|
| 1022 | self.color = color |
---|
| 1023 | self->SetColor, color |
---|
| 1024 | RETURN, 1 |
---|
| 1025 | END ;---------------------------------------------------------------------------------- |
---|
| 1026 | |
---|
| 1027 | |
---|
| 1028 | |
---|
| 1029 | PRO FSC_PLOTWINDOW__DEFINE |
---|
| 1030 | |
---|
| 1031 | struct = { FSC_PLOTWINDOW, $ ; The object class name. |
---|
| 1032 | action:"", $ ; A flag to indicate whether you are moving or resizing the plot window. |
---|
| 1033 | base: 0L, $ ; The top-level base of the compound widget. |
---|
| 1034 | color:0, $ ; A flag to indicate if the window is in "color" or not. |
---|
| 1035 | currentX:0, $ ; The starting X location for resizing. |
---|
| 1036 | currentY:0, $ ; The starting Y location for resizing. |
---|
| 1037 | direction:"", $ ; The direction of resizing movement. |
---|
| 1038 | event_pro:"", $ ; The name of an event handler to call. |
---|
| 1039 | drawID:0L, $ ; The draw widget identifier. |
---|
| 1040 | pageSize:"", $ ; A string to indicate the "type" of page: Letter, A4, etc. |
---|
| 1041 | pixels_per_inch:0, $ ; The pixel per inch scaling. 18 pixels/inch hardcoded. |
---|
| 1042 | landscape: 0, $ ; A flag to indicate the window should be in landscape mode. |
---|
| 1043 | plotModel:Obj_New(), $ ; The model for the plot and axes objects. |
---|
| 1044 | theBackground:Obj_New(), $ ; The background filled polygon. |
---|
| 1045 | thePlot:Obj_New(), $ ; The plot object. |
---|
| 1046 | theModel:Obj_New(), $ ; The model for the background object. |
---|
| 1047 | theView:Obj_New(), $ ; The object view. |
---|
| 1048 | theWindow:Obj_New(), $ ; The object window. |
---|
| 1049 | theXAxis:Obj_New(), $ ; The X axis object. |
---|
| 1050 | theYAxis:Obj_New(), $ ; The Y axis object. |
---|
| 1051 | units:"", $ ; A string indicating INCHES or CENTIMETER units. |
---|
| 1052 | x1:0.0, $ ; The x location of lower-left corner of plot window. (Normalized coordinates.) |
---|
| 1053 | x2:0.0, $ ; The x location of upper-right corner of plot window. (Normalized coordinates.) |
---|
| 1054 | xlength:0.0, $ ; The length of the plot window in x. (Normalized coordinates.) |
---|
| 1055 | xsize:0.0, $ ; The current X size of the draw widget. (Device coordinates.) |
---|
| 1056 | y1:0.0, $ ; The y location of lower-left corner of plot window. (Normalized coordinates.) |
---|
| 1057 | y2:0.0, $ ; The yx location of upper-right corner of plot window. (Normalized coordinates.) |
---|
| 1058 | ylength:0.0, $ ; The length of the plot window in y. (Normalized coordinates.) |
---|
| 1059 | ysize:0.0 $ ; The current X size of the draw widget. (Device coordinates.) |
---|
| 1060 | } |
---|
| 1061 | END ;---------------------------------------------------------------------------------- |
---|
| 1062 | |
---|
| 1063 | |
---|
| 1064 | |
---|
| 1065 | FUNCTION FSC_PLOTWINDOW, parent, PageSize=pagesize, WindowSize=windowsize, $ |
---|
| 1066 | Event_Pro=event_pro, Units=units, UValue=uvalue, Landscape=landscape, $ |
---|
| 1067 | Color=color |
---|
| 1068 | |
---|
| 1069 | ; A wrapper function so this object can be treated as a compound |
---|
| 1070 | ; widget function. |
---|
| 1071 | |
---|
| 1072 | IF N_Elements(pagesize) EQ 0 THEN pageSize = 'LETTER' |
---|
| 1073 | IF N_Elements(windowsize) EQ 0 THEN windowsize = [0.15, 0.15, 0.85, 0.85] |
---|
| 1074 | IF N_Elements(event_pro) EQ 0 THEN event_pro = "" |
---|
| 1075 | IF N_Elements(units) EQ 0 THEN units="" |
---|
| 1076 | color = Keyword_Set(color) |
---|
| 1077 | landscape = Keyword_Set(landscape) |
---|
| 1078 | IF N_Elements(parent) EQ 0 THEN BEGIN |
---|
| 1079 | ok = Dialog_Message('Parent parameter is required. Returning...') |
---|
| 1080 | RETURN, Obj_New() |
---|
| 1081 | ENDIF |
---|
| 1082 | |
---|
| 1083 | RETURN, Obj_New('FSC_PLOTWINDOW', parent, PageSize=pagesize, WindowSize=windowsize, $ |
---|
| 1084 | Event_Pro=event_pro, Units=units, UValue=uvalue, Landscape=landscape, Color=color) |
---|
| 1085 | END ;---------------------------------------------------------------------------------- |
---|