source: trunk/MESOSCALE/PLOT/MINIMAL/fsc/fsc_plotwindow.pro @ 134

Last change on this file since 134 was 85, checked in by aslmd, 14 years ago

LMD_MM_MARS et LMD_LES_MARS: ajout des routines IDL pour tracer les sorties --> voir mesoscale/PLOT

File size: 35.9 KB
Line 
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
103FUNCTION FSC_PLOTWINDOW_Error_Message, theMessage, Traceback=traceback, NoName=noName
104
105On_Error, 2
106
107   ; Check for presence and type of message.
108
109IF N_Elements(theMessage) EQ 0 THEN theMessage = !Error_State.Msg
110s = Size(theMessage)
111messageType = s[s[0]+1]
112IF messageType NE 7 THEN BEGIN
113   Message, "The message parameter must be a string."
114ENDIF
115
116   ; Get the call stack and the calling routine's name.
117
118Help, Calls=callStack
119callingRoutine = (StrSplit(StrCompress(callStack[1])," ", /Extract))[0]
120
121   ; Are widgets supported? Doesn't matter in IDL 5.3 and higher.
122
123widgetsSupported = ((!D.Flags AND 65536L) NE 0) OR Float(!Version.Release) GE 5.3
124IF 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
129ENDIF ELSE BEGIN
130      Message, theMessage, /Continue, /NoPrint, /NoName, /NoPrefix
131      Print, '%' + callingRoutine + ': ' + theMessage
132      answer = 'OK'
133ENDELSE
134
135   ; Provide traceback information if requested.
136
137IF Keyword_Set(traceback) THEN BEGIN
138   Help, /Last_Message, Output=traceback
139   FOR j=0,N_Elements(traceback)-1 DO Print, traceback[j]
140ENDIF
141
142RETURN, answer
143END ;----------------------------------------------------------------------------------
144
145
146
147FUNCTION FSC_PLOTWINDOW_Normalize, range, Position=position
148
149On_Error, 1
150IF N_Params() EQ 0 THEN Message, 'Please pass range vector as argument.'
151
152IF (N_Elements(position) EQ 0) THEN position = [0.0, 1.0] ELSE $
153    position=Float(position)
154range = Float(range)
155
156scale = [((position[0]*range[1])-(position[1]*range[0])) / $
157    (range[1]-range[0]), (position[1]-position[0])/(range[1]-range[0])]
158
159RETURN, scale
160END ;----------------------------------------------------------------------------------
161
162
163
164PRO FSC_PLOTWINDOW::Refresh
165self.theWindow->Draw, self.theView
166END ;----------------------------------------------------------------------------------
167
168
169
170PRO FSC_PLOTWINDOW::SetWindowColor, theColor
171
172; Set the background color of the view.
173
174self.theView->SetProperty, Color=theColor
175self.theWindow->Draw, self.theView
176END ;----------------------------------------------------------------------------------
177
178
179
180FUNCTION FSC_PLOTWINDOW::GetUValue
181
182; Get the user value of the compound widget.
183
184parent = Widget_Info(self.drawID, /Parent)
185Widget_Control, parent, Get_UValue=theValue
186RETURN, theValue
187END ;----------------------------------------------------------------------------------
188
189
190
191PRO FSC_PLOTWINDOW::SetColor, on_off
192
193; Sets the color of the plot window. Different colors
194; depending on depth of visual class.
195
196IF on_off THEN BEGIN
197   self.theBackground->SetProperty, Color=[255,255,150]
198   self.thePlot->SetProperty, Color=[255, 0, 0]
199ENDIF 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]
204ENDELSE
205
206   ; Draw the view.
207
208IF Obj_Valid(self.theWindow) THEN self.theWindow->Draw, self.theView
209END ;----------------------------------------------------------------------------------
210
211
212
213PRO FSC_PLOTWINDOW::SetUnits, units
214
215; Sets the type of units to report in.
216
217possibleUnits = ["INCHES", "CENTIMETERS", ""]
218units = StrUpCase(units)
219index = WHERE(possibleUnits EQ units, count)
220IF count EQ 0 THEN BEGIN
221   ok = Dialog_Message('Unknown units: ' + units + '. Returning...')
222   RETURN
223ENDIF
224self.units = units
225END ;----------------------------------------------------------------------------------
226
227
228
229PRO 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
234xsize = self.xlength
235ysize = self.ylength
236xoffset = self.x1
237yoffset = self.y1
238
239factor = Float(self.pixels_per_inch)
240
241CASE 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...')
264ENDCASE
265
266END ;----------------------------------------------------------------------------------
267
268
269
270PRO 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
275factor = Float(self.pixels_per_inch)
276
277CASE 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...')
300ENDCASE
301
302self.xlength = x2 - x1
303self.ylength = y2 - y1
304self.x1 = x1
305self.x2 = x2
306self.y1 = y1
307self.y2 = y2
308self->SetWindowSize, [x1, y1, x2, y2]
309
310END ;----------------------------------------------------------------------------------
311
312PRO FSC_PLOTWINDOW::SetWindowSize, position
313
314; Set the size of the plot window. Axes have to be
315; rescaled appropriately.
316
317IF N_Elements(position) EQ 0 THEN position = [0.2, 0.2, 0.8, 0.8]
318
319x1 = position[0]
320y1 = position[1]
321x2 = position[2]
322y2 = position[3]
323
324new = FltArr(2,5)
325new[0,*] = [x1, x1, x2, x2, x1]
326new[1,*] = [y1, y2, y2, y1, y1]
327
328   ; Modify the graphics objects.
329
330self.theBackground->SetProperty, Data=new
331xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05])
332ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05])
333
334self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0]
335self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0]
336self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys
337self.x1 = new[0,0]
338self.x2 = new[0,2]
339self.y1 = new[1,0]
340self.y2 = new[1,1]
341self.xlength = self.x2 - self.x1
342self.ylength = self.y2 - self.y1
343
344   ; Draw the view after resetting the transformation matrix.
345
346self.theModel->Reset
347self.theWindow->Draw, self.theView
348END ;----------------------------------------------------------------------------------
349
350
351
352PRO 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
362STANDARD_SIZE = self.pixels_per_inch * 11.0
363
364IF N_Elements(pagesize) EQ 0 THEN pagesize = "LETTER"
365pagesize = StrUpCase(pagesize)
366IF N_Elements(tlb) EQ 0 THEN tlb = self.base
367
368CASE 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
394ENDCASE
395
396IF Keyword_Set(landscape) THEN BEGIN
397   temp = xsize
398   xsize = ysize
399   ysize = temp
400ENDIF
401
402self.xsize = ROUND(xsize)
403self.ysize = ROUND(ysize)
404self.pagesize = pagesize
405
406   ; Bugs in X windows implementation of window resizing necessitate
407   ; destroying and re-creating the draw widget window.
408
409IF !D.Name NE 'X' THEN BEGIN
410
411   self.theWindow->SetProperty, Dimensions=[xsize, ysize]
412
413ENDIF 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
427ENDELSE
428
429self.thewindow->Draw, self.theView
430
431END ;----------------------------------------------------------------------------------
432
433
434
435FUNCTION 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
446STANDARD_SIZE = self.pixels_per_inch * 11.0
447
448IF N_Elements(pagesize) EQ 0 THEN pagesize = "LETTER"
449pagesize = StrUpCase(pagesize)
450
451CASE 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
476ENDCASE
477
478IF Keyword_Set(landscape) THEN BEGIN
479   temp = xsize
480   xsize = ysize
481   ysize = temp
482ENDIF
483
484RETURN, [ROUND(xsize), ROUND(ysize)]
485
486END ;----------------------------------------------------------------------------------
487
488
489
490FUNCTION FSC_PLOTWINDOW::GetPosition
491
492; Returns the current position of the plot window in
493; the view. Normalized coordinates.
494
495RETURN, [self.x1, self.y1, self.x2, self.y2]
496END ;----------------------------------------------------------------------------------
497
498
499
500PRO FSC_PLOTWINDOW::Resize, event, direction
501
502; Performs window resizing, depending upon which of eight
503; possible directions you can move the window.
504
505IF direction EQ 'NONE' OR direction EQ 'MOVE' THEN BEGIN
506   RETURN
507ENDIF
508
509   ; Calculate movement in normalized coordinates. Update start coords.
510
511deltax = (event.x - self.currentX) / self.xsize
512deltay = (event.y - self.currentY) / self.ysize
513self.currentX = event.x
514self.currentY = event.y
515
516CASE 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
578ENDCASE
579
580new = FltArr(2,5)
581new[0,*] = [x1, x1, x2, x2, x1]
582new[1,*] = [y1, y2, y2, y1, y1]
583
584   ; Modify the graphics objects.
585
586self.theBackground->SetProperty, Data=new
587
588xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05]) > 10e-6
589ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05]) > 10e-6
590
591self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0]
592self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0]
593self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys
594self.x1 = new[0,0]
595self.x2 = new[0,2]
596self.y1 = new[1,0]
597self.y2 = new[1,1]
598self.xlength = self.x2 - self.x1
599self.ylength = self.y2 - self.y1
600
601   ; Draw the view after resetting the transformation matrix.
602
603self.theModel->Reset
604self.theWindow->Draw, self.theView
605
606END ;----------------------------------------------------------------------------------
607
608
609
610PRO FSC_PLOTWINDOW::CenterPlot, event
611
612   ; Centers the plot in the window.
613
614new = FltArr(2,5)
615self.x1 = (1.0 - self.xlength) / 2.0
616self.x2 = self.x1 + self.xlength
617self.y1 = (1.0 - self.ylength) / 2.0
618self.y2 = self.y1 + self.ylength
619
620new[0,*] = [self.x1, self.x1, self.x2, self.x2, self.x1]
621new[1,*] = [self.y1, self.y2, self.y2, self.y1, self.y1]
622
623   ; Modify the graphics objects.
624
625self.theBackground->SetProperty, Data=new
626
627xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05])
628ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05])
629
630self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0]
631self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0]
632self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys
633self.x1 = new[0,0]
634self.x2 = new[0,2]
635self.y1 = new[1,0]
636self.y2 = new[1,1]
637
638   ; Draw the view after resetting the transformation matrix.
639
640self.theModel->Reset
641self.theWindow->Draw, self.theView
642
643END ;----------------------------------------------------------------------------------
644
645
646
647PRO FSC_PLOTWINDOW::MovePlot, event
648
649   ; Calculate movement in normalized coordinates. Update start coords.
650
651deltax = (event.x - self.currentX) / self.xsize
652deltay = (event.y - self.currentY) / self.ysize
653self.currentX = event.x
654self.currentY = event.y
655
656   ; Translate the selected model.
657
658self.theModel->Translate, deltax, deltay, 0
659
660   ; Get the current transformation matrix.
661
662matrix = self.theModel->GetCTM()
663
664   ; Get the vertices of the polygon object.
665
666self.theBackground->GetProperty, Data=vertices
667
668   ; Apply the transformation matrix to the vertices.
669
670new = FltArr(2,5)
671FOR j=0,4 DO BEGIN
672   v = [vertices[*, j], 0.0, 1.0]
673   new[*, j] = (matrix ## v)[0:1]
674ENDFOR
675
676IF new[0,0] LT 0.0 THEN new[0,*] = [0.0, 0.0, self.xlength, self.xlength, 0.0]
677IF 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]
678IF new[1,0] LT 0.0 THEN new[1,*] = [0.0, self.ylength, self.ylength, 0.0, 0.0]
679IF 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
683self.theBackground->SetProperty, Data=new
684
685xs = FSC_PlotWindow_Normalize([0,100], Position=[new[0,0]+0.05, new[0,2]-0.05])
686ys = FSC_PlotWindow_Normalize([-1,1], Position=[new[1,0]+0.05, new[1,1]-0.05])
687
688self.theXAxis->SetProperty, XCoord_Conv=xs, Location=[1000, new[1,0]+0.05, 0]
689self.theYAxis->SetProperty, YCoord_Conv=ys, Location=[new[0,0]+.05, 1000, 0]
690self.thePlot->SetProperty, XCoord_Conv=xs, YCoord_Conv=ys
691self.x1 = new[0,0]
692self.x2 = new[0,2]
693self.y1 = new[1,0]
694self.y2 = new[1,1]
695
696   ; Draw the view after resetting the transformation matrix.
697
698self.theModel->Reset
699self.theWindow->Draw, self.theView
700
701END ;----------------------------------------------------------------------------------
702
703
704
705FUNCTION FSC_PLOTWINDOW::WhichButtonReleased, event
706
707; Determines which button was used.
708
709buttons = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT']
710RETURN, buttons[event.release]
711END ;----------------------------------------------------------------------------------
712
713
714
715FUNCTION FSC_PLOTWINDOW::WhichButtonPressed, event
716
717; Determines which button was used.
718
719buttons = ['NONE', 'LEFT', 'MIDDLE', 'NONE', 'RIGHT']
720RETURN, buttons[event.press]
721END ;----------------------------------------------------------------------------------
722
723
724
725FUNCTION 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
732x = x / self.xsize
733y = y / self.ysize
734
735xtest = -1
736IF x GE self.x1 AND x LE self.x1 + 0.025 THEN xtest = 0
737IF x GT self.x1 + 0.025 AND x LT self.x2 - 0.025 THEN xtest = 1
738IF x GE self.x2 - 0.025 AND x LE self.x2 THEN xtest = 2
739ytest = -1
740IF y GE self.y1 AND y LE self.y1 + 0.1 THEN ytest = 0
741IF y GT self.y1 + 0.025 AND y LT self.y2 - 0.025 THEN ytest = 1
742IF y GE self.y2 - 0.025 AND y LE self.y2 THEN ytest = 2
743
744IF xtest EQ -1 OR ytest EQ -1 THEN BEGIN
745   retVal = 'ORIGINAL'
746   direction = 'NONE'
747ENDIF
748IF xtest EQ 0 AND ytest EQ  0 THEN BEGIN
749   retVal = 'SIZE_SW'
750   direction = 'SW'
751ENDIF
752IF xtest EQ 0 AND ytest EQ  1 THEN BEGIN
753    retVal = 'SIZE_EW'
754   direction = 'W'
755ENDIF
756IF xtest EQ 0 AND ytest EQ  2 THEN BEGIN
757    retVal = 'SIZE_NW'
758   direction = 'NW'
759ENDIF
760IF xtest EQ 1 AND ytest EQ  0 THEN BEGIN
761    retVal = 'SIZE_NS'
762   direction = 'S'
763ENDIF
764IF xtest EQ 1 AND ytest EQ  1 THEN BEGIN
765    retVal = 'MOVE'
766   direction = 'MOVE'
767ENDIF
768IF xtest EQ 1 AND ytest EQ  2 THEN BEGIN
769    retVal = 'SIZE_NS'
770   direction = 'N'
771ENDIF
772IF xtest EQ 2 AND ytest EQ  0 THEN BEGIN
773    retVal = 'SIZE_SE'
774   direction = 'SE'
775ENDIF
776IF xtest EQ 2 AND ytest EQ  1 THEN BEGIN
777    retVal = 'SIZE_EW'
778   direction = 'E'
779ENDIF
780IF xtest EQ 2 AND ytest EQ  2 THEN BEGIN
781    retVal = 'SIZE_NE'
782   direction = 'NE'
783ENDIF
784
785RETURN, retVal
786END ;----------------------------------------------------------------------------------
787
788
789
790PRO FSC_PLOTWINDOW::Realize
791
792Widget_Control, self.drawID, Get_Value=theWindow
793self.theWindow = theWindow
794END ;----------------------------------------------------------------------------------
795
796
797
798PRO FSC_PLOTWINDOW_Notify_Realize, drawID
799Widget_Control, drawID, Get_UValue=self
800self->Realize
801END ;----------------------------------------------------------------------------------
802
803
804
805PRO FSC_PLOTWINDOW::Process_Events, event
806
807; Handles draw widget events.
808
809possibleEvents = ['DOWN', 'UP', 'MOTION', 'SCROLL', 'EXPOSE']
810thisEvent = possibleEvents[event.type]
811
812   ; Are we inside a target? If so, change cursor.
813
814target = self->InTarget(event.x, event.y, Direction=direction)
815self.theWindow->SetCurrentCursor, target
816
817
818   ; What kind of event is this?
819
820CASE 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
887ENDCASE
888
889END ;----------------------------------------------------------------------------------
890
891
892
893PRO FSC_PLOTWINDOW_Events, event
894
895; Widget event handler. Calls event handler method.
896
897Widget_Control, event.id, Get_UValue=self
898self->Process_Events, event
899END ;----------------------------------------------------------------------------------
900
901
902
903PRO FSC_PLOTWINDOW_Kill_Notify, drawID
904
905; Destroy the plot window object when the window is destroyed.
906
907Widget_Control, drawID, Get_UValue=self
908Obj_Destroy, self
909END ;----------------------------------------------------------------------------------
910
911
912
913PRO FSC_PLOTWINDOW::CLEANUP
914Obj_Destroy, self.theModel
915Obj_Destroy, self.theWindow
916Obj_Destroy, self.theView
917Obj_Destroy, self.plotModel
918END ;----------------------------------------------------------------------------------
919
920
921
922FUNCTION 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
934Catch, theError
935IF theError NE 0 THEN BEGIN
936   Catch, /Cancel
937   ok = FSC_PlotWindow_Error_Message(Traceback=Keyword_Set(debug))
938   RETURN, 0
939ENDIF
940
941IF N_Elements(pagesize) EQ 0 THEN pageSize = 'LETTER'
942IF N_Elements(windowsize) EQ 0 THEN windowsize = [0.2, 0.2, 0.8, 0.8]
943IF N_Elements(event_pro) EQ 0 THEN event_pro = ""
944IF N_Elements(units) EQ 0 THEN units=""
945IF N_Elements(uvalue) EQ 0 THEN uvalue=""
946IF N_Elements(landscape) EQ 0 THEN landscape = 0
947Device, Get_Visual_Depth=theDepth
948self.pixels_per_inch = 18
949sizes = self->GetPagePixels(pageSize, Landscape=landscape)
950xsize = sizes[0]
951ysize = sizes[1]
952IF N_Elements(windowColor) EQ 0 THEN $
953   IF theDepth GT 8 THEN windowColor = [60, 140, 140] ELSE windowColor = [80, 80, 80]
954
955IF N_Elements(color) EQ 0 THEN BEGIN
956   Device, Get_Visual_Depth=theDepth
957   IF theDepth GT 8 THEN color = 1 ELSE color = 0
958ENDIF ELSE color = Keyword_Set(color)
959
960x1 = windowsize[0]
961x2 = windowsize[2]
962y1 = windowsize[1]
963y2 = windowsize[3]
964
965data = Findgen(101)
966data = Sin(data/5) / Exp(data/20)
967
968self.thePlot = Obj_New('IDLgrPlot', data, Color=[0,0,0])
969self.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
973self.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)
975self.theXAxis->SetProperty, XCoord_Conv=FSC_PlotWindow_Normalize([0,100], $
976   Position=[x1+0.05, x2-0.05]) > 10e-6
977
978self.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)
980self.theYAxis->SetProperty, YCoord_Conv=FSC_PlotWindow_Normalize([-1,1], $
981   Position=[y1+0.05, y2-0.05]) > 10e-6
982
983self.plotModel = Obj_New('IDLgrModel')
984
985IF theDepth GT 8 THEN theColor = [210, 200, 180] ELSE theColor = [255,255,255]
986self.theBackground = Obj_New('IDLgrPolygon', Color=theColor, $
987   [x1, x1, x2, x2, x1], [y1, y2, y2, y1, y1])
988
989self.theModel = Obj_New('IDLgrModel', Select_Target=1)
990self.theModel->Add, self.theBackground
991
992self.plotModel->Add, self.theXAxis
993self.plotModel->Add, self.theYAxis
994self.plotModel->Add, self.thePlot
995self.plotModel->Translate, 0, 0, 0.1
996
997self.theView = Obj_New('IDLgrView', Color=windowColor,  Viewplane_Rect=[0,0,1,1])
998self.theView->Add, self.theModel
999self.theView->Add, self.plotModel
1000
1001self.base = Widget_Base(parent, UValue=uvalue)
1002self.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
1008self.pagesize = pagesize
1009self.landscape = Keyword_Set(landscape)
1010self.x1 = x1
1011self.x2 = x2
1012self.y1 = y1
1013self.y2 = y2
1014self.xsize = Float(xsize)
1015self.ysize = Float(ysize)
1016self.currentX = -1
1017self.currentY = -1
1018self.xlength = x2 - x1
1019self.ylength = y2 - y1
1020self.units = units
1021self.event_pro = event_pro
1022self.color = color
1023self->SetColor, color
1024RETURN, 1
1025END ;----------------------------------------------------------------------------------
1026
1027
1028
1029PRO 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            }
1061END ;----------------------------------------------------------------------------------
1062
1063
1064
1065FUNCTION 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
1072IF N_Elements(pagesize) EQ 0 THEN pageSize = 'LETTER'
1073IF N_Elements(windowsize) EQ 0 THEN windowsize = [0.15, 0.15, 0.85, 0.85]
1074IF N_Elements(event_pro) EQ 0 THEN event_pro = ""
1075IF N_Elements(units) EQ 0 THEN units=""
1076color = Keyword_Set(color)
1077landscape = Keyword_Set(landscape)
1078IF N_Elements(parent) EQ 0 THEN BEGIN
1079   ok = Dialog_Message('Parent parameter is required. Returning...')
1080   RETURN, Obj_New()
1081ENDIF
1082
1083RETURN, Obj_New('FSC_PLOTWINDOW', parent, PageSize=pagesize, WindowSize=windowsize, $
1084   Event_Pro=event_pro, Units=units, UValue=uvalue, Landscape=landscape, Color=color)
1085END ;----------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.