xref: /petsc/src/sys/classes/draw/interface/draw.c (revision 8cc725e69398de546bdc828d7b714aa2223f5218)
1 
2 /*
3        Provides the calling sequences for all the basic PetscDraw routines.
4 */
5 #include <petsc/private/drawimpl.h>  /*I "petscdraw.h" I*/
6 #include <petscviewer.h>
7 
8 PetscClassId PETSC_DRAW_CLASSID;
9 
10 static PetscBool PetscDrawPackageInitialized = PETSC_FALSE;
11 /*@C
12   PetscDrawFinalizePackage - This function destroys everything in the Petsc interface to the Draw package. It is
13   called from PetscFinalize().
14 
15   Level: developer
16 
17 .seealso: `PetscFinalize()`
18 @*/
19 PetscErrorCode  PetscDrawFinalizePackage(void)
20 {
21   PetscFunctionBegin;
22   PetscCall(PetscFunctionListDestroy(&PetscDrawList));
23   PetscDrawPackageInitialized = PETSC_FALSE;
24   PetscDrawRegisterAllCalled  = PETSC_FALSE;
25   PetscFunctionReturn(0);
26 }
27 
28 /*@C
29   PetscInitializeDrawPackage - This function initializes everything in the PetscDraw package. It is called
30   from PetscDLLibraryRegister_petsc() when using dynamic libraries, and on the call to PetscInitialize()
31   when using shared or static libraries.
32 
33   Level: developer
34 
35 .seealso: `PetscInitialize()`
36 @*/
37 PetscErrorCode  PetscDrawInitializePackage(void)
38 {
39   char           logList[256];
40   PetscBool      opt,pkg;
41 
42   PetscFunctionBegin;
43   if (PetscDrawPackageInitialized) PetscFunctionReturn(0);
44   PetscDrawPackageInitialized = PETSC_TRUE;
45   /* Register Classes */
46   PetscCall(PetscClassIdRegister("Draw",&PETSC_DRAW_CLASSID));
47   PetscCall(PetscClassIdRegister("Draw Axis",&PETSC_DRAWAXIS_CLASSID));
48   PetscCall(PetscClassIdRegister("Line Graph",&PETSC_DRAWLG_CLASSID));
49   PetscCall(PetscClassIdRegister("Histogram",&PETSC_DRAWHG_CLASSID));
50   PetscCall(PetscClassIdRegister("Bar Graph",&PETSC_DRAWBAR_CLASSID));
51   PetscCall(PetscClassIdRegister("Scatter Plot",&PETSC_DRAWSP_CLASSID));
52   /* Register Constructors */
53   PetscCall(PetscDrawRegisterAll());
54   /* Process Info */
55   {
56     PetscClassId  classids[6];
57 
58     classids[0] = PETSC_DRAW_CLASSID;
59     classids[1] = PETSC_DRAWAXIS_CLASSID;
60     classids[2] = PETSC_DRAWLG_CLASSID;
61     classids[3] = PETSC_DRAWHG_CLASSID;
62     classids[4] = PETSC_DRAWBAR_CLASSID;
63     classids[5] = PETSC_DRAWSP_CLASSID;
64     PetscCall(PetscInfoProcessClass("draw", 6, classids));
65   }
66   /* Process summary exclusions */
67   PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt));
68   if (opt) {
69     PetscCall(PetscStrInList("draw",logList,',',&pkg));
70     if (pkg) {
71       PetscCall(PetscLogEventExcludeClass(PETSC_DRAW_CLASSID));
72       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWAXIS_CLASSID));
73       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWLG_CLASSID));
74       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWHG_CLASSID));
75       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWBAR_CLASSID));
76       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWSP_CLASSID));
77     }
78   }
79   /* Register package finalizer */
80   PetscCall(PetscRegisterFinalize(PetscDrawFinalizePackage));
81   PetscFunctionReturn(0);
82 }
83 
84 /*@
85    PetscDrawResizeWindow - Allows one to resize a window from a program.
86 
87    Collective on PetscDraw
88 
89    Input Parameters:
90 +  draw - the window
91 -  w,h - the new width and height of the window
92 
93    Level: intermediate
94 
95 .seealso: `PetscDrawCheckResizedWindow()`
96 @*/
97 PetscErrorCode  PetscDrawResizeWindow(PetscDraw draw,int w,int h)
98 {
99   PetscFunctionBegin;
100   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
101   PetscValidLogicalCollectiveInt(draw,w,2);
102   PetscValidLogicalCollectiveInt(draw,h,3);
103   if (draw->ops->resizewindow) {
104     PetscCall((*draw->ops->resizewindow)(draw,w,h));
105   }
106   PetscFunctionReturn(0);
107 }
108 
109 /*@
110    PetscDrawGetWindowSize - Gets the size of the window.
111 
112    Not collective
113 
114    Input Parameter:
115 .  draw - the window
116 
117    Output Parameters:
118 .  w,h - the window width and height
119 
120    Level: intermediate
121 
122 .seealso: `PetscDrawResizeWindow()`, `PetscDrawCheckResizedWindow()`
123 @*/
124 PetscErrorCode  PetscDrawGetWindowSize(PetscDraw draw,int *w,int *h)
125 {
126   PetscFunctionBegin;
127   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
128   if (w) PetscValidPointer(w,2);
129   if (h) PetscValidPointer(h,3);
130   if (w) *w = draw->w;
131   if (h) *h = draw->h;
132   PetscFunctionReturn(0);
133 }
134 
135 /*@
136    PetscDrawCheckResizedWindow - Checks if the user has resized the window.
137 
138    Collective on PetscDraw
139 
140    Input Parameter:
141 .  draw - the window
142 
143    Level: advanced
144 
145 .seealso: `PetscDrawResizeWindow()`
146 
147 @*/
148 PetscErrorCode  PetscDrawCheckResizedWindow(PetscDraw draw)
149 {
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
152   if (draw->ops->checkresizedwindow) {
153     PetscCall((*draw->ops->checkresizedwindow)(draw));
154   }
155   PetscFunctionReturn(0);
156 }
157 
158 /*@C
159    PetscDrawGetTitle - Gets pointer to title of a PetscDraw context.
160 
161    Not collective
162 
163    Input Parameter:
164 .  draw - the graphics context
165 
166    Output Parameter:
167 .  title - the title
168 
169    Level: intermediate
170 
171 .seealso: `PetscDrawSetTitle()`
172 @*/
173 PetscErrorCode  PetscDrawGetTitle(PetscDraw draw,const char *title[])
174 {
175   PetscFunctionBegin;
176   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
177   PetscValidPointer(title,2);
178   *title = draw->title;
179   PetscFunctionReturn(0);
180 }
181 
182 /*@C
183    PetscDrawSetTitle - Sets the title of a PetscDraw context.
184 
185    Collective on PetscDraw
186 
187    Input Parameters:
188 +  draw - the graphics context
189 -  title - the title
190 
191    Level: intermediate
192 
193    Note: The title is positioned in the windowing system title bar for the window. Hence it will not be saved with -draw_save
194    in the image.
195 
196    A copy of the string is made, so you may destroy the
197    title string after calling this routine.
198 
199    You can use PetscDrawAxisSetLabels() to indicate a title within the window
200 
201 .seealso: `PetscDrawGetTitle()`, `PetscDrawAppendTitle()`
202 @*/
203 PetscErrorCode  PetscDrawSetTitle(PetscDraw draw,const char title[])
204 {
205   PetscFunctionBegin;
206   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
207   PetscValidCharPointer(title,2);
208   PetscCall(PetscFree(draw->title));
209   PetscCall(PetscStrallocpy(title,&draw->title));
210   if (draw->ops->settitle) {
211     PetscCall((*draw->ops->settitle)(draw,draw->title));
212   }
213   PetscFunctionReturn(0);
214 }
215 
216 /*@C
217    PetscDrawAppendTitle - Appends to the title of a PetscDraw context.
218 
219    Collective on PetscDraw
220 
221    Input Parameters:
222 +  draw - the graphics context
223 -  title - the title
224 
225    Note:
226    A copy of the string is made, so you may destroy the
227    title string after calling this routine.
228 
229    Level: advanced
230 
231 .seealso: `PetscDrawSetTitle()`, `PetscDrawGetTitle()`
232 @*/
233 PetscErrorCode  PetscDrawAppendTitle(PetscDraw draw,const char title[])
234 {
235   PetscFunctionBegin;
236   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
237   if (title) PetscValidCharPointer(title,2);
238   if (!title || !title[0]) PetscFunctionReturn(0);
239 
240   if (draw->title) {
241     size_t len1,len2;
242     char   *newtitle;
243     PetscCall(PetscStrlen(title,&len1));
244     PetscCall(PetscStrlen(draw->title,&len2));
245     PetscCall(PetscMalloc1(len1 + len2 + 1,&newtitle));
246     PetscCall(PetscStrcpy(newtitle,draw->title));
247     PetscCall(PetscStrcat(newtitle,title));
248     PetscCall(PetscFree(draw->title));
249     draw->title = newtitle;
250   } else {
251     PetscCall(PetscStrallocpy(title,&draw->title));
252   }
253   if (draw->ops->settitle) {
254     PetscCall((*draw->ops->settitle)(draw,draw->title));
255   }
256   PetscFunctionReturn(0);
257 }
258 
259 static PetscErrorCode PetscDrawDestroy_Private(PetscDraw draw)
260 {
261   PetscFunctionBegin;
262   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
263   PetscCall(PetscDrawSaveMovie(draw));
264   if (draw->savefinalfilename) {
265     draw->savesinglefile = PETSC_TRUE;
266     PetscCall(PetscDrawSetSave(draw,draw->savefinalfilename));
267     PetscCall(PetscDrawSave(draw));
268   }
269   PetscCall(PetscBarrier((PetscObject)draw));
270   PetscFunctionReturn(0);
271 }
272 
273 /*@
274    PetscDrawDestroy - Deletes a draw context.
275 
276    Collective on PetscDraw
277 
278    Input Parameters:
279 .  draw - the drawing context
280 
281    Level: beginner
282 
283 .seealso: `PetscDrawCreate()`
284 
285 @*/
286 PetscErrorCode  PetscDrawDestroy(PetscDraw *draw)
287 {
288   PetscFunctionBegin;
289   if (!*draw) PetscFunctionReturn(0);
290   PetscValidHeaderSpecific(*draw,PETSC_DRAW_CLASSID,1);
291   if (--((PetscObject)(*draw))->refct > 0) PetscFunctionReturn(0);
292 
293   if ((*draw)->pause == -2) {
294     (*draw)->pause = -1;
295     PetscCall(PetscDrawPause(*draw));
296   }
297 
298   /* if memory was published then destroy it */
299   PetscCall(PetscObjectSAWsViewOff((PetscObject)*draw));
300 
301   PetscCall(PetscDrawDestroy_Private(*draw));
302 
303   if ((*draw)->ops->destroy) {
304     PetscCall((*(*draw)->ops->destroy)(*draw));
305   }
306   PetscCall(PetscDrawDestroy(&(*draw)->popup));
307   PetscCall(PetscFree((*draw)->title));
308   PetscCall(PetscFree((*draw)->display));
309   PetscCall(PetscFree((*draw)->savefilename));
310   PetscCall(PetscFree((*draw)->saveimageext));
311   PetscCall(PetscFree((*draw)->savemovieext));
312   PetscCall(PetscFree((*draw)->savefinalfilename));
313   PetscCall(PetscHeaderDestroy(draw));
314   PetscFunctionReturn(0);
315 }
316 
317 /*@
318    PetscDrawGetPopup - Creates a popup window associated with a PetscDraw window.
319 
320    Collective on PetscDraw
321 
322    Input Parameter:
323 .  draw - the original window
324 
325    Output Parameter:
326 .  popup - the new popup window
327 
328    Level: advanced
329 
330 .seealso: `PetscDrawScalePopup()`, `PetscDrawCreate()`
331 
332 @*/
333 PetscErrorCode  PetscDrawGetPopup(PetscDraw draw,PetscDraw *popup)
334 {
335   PetscFunctionBegin;
336   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
337   PetscValidPointer(popup,2);
338 
339   if (draw->popup) *popup = draw->popup;
340   else if (draw->ops->getpopup) {
341     PetscCall((*draw->ops->getpopup)(draw,popup));
342     if (*popup) {
343       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*popup,"popup_"));
344       (*popup)->pause = 0.0;
345       PetscCall(PetscDrawSetFromOptions(*popup));
346     }
347   } else *popup = NULL;
348   PetscFunctionReturn(0);
349 }
350 
351 /*@C
352   PetscDrawSetDisplay - Sets the display where a PetscDraw object will be displayed
353 
354   Input Parameters:
355 + draw - the drawing context
356 - display - the X windows display
357 
358   Level: advanced
359 
360 .seealso: `PetscDrawCreate()`
361 
362 @*/
363 PetscErrorCode  PetscDrawSetDisplay(PetscDraw draw,const char display[])
364 {
365   PetscFunctionBegin;
366   PetscCall(PetscFree(draw->display));
367   PetscCall(PetscStrallocpy(display,&draw->display));
368   PetscFunctionReturn(0);
369 }
370 
371 /*@
372    PetscDrawSetDoubleBuffer - Sets a window to be double buffered.
373 
374    Logically Collective on PetscDraw
375 
376    Input Parameter:
377 .  draw - the drawing context
378 
379    Level: intermediate
380 
381 @*/
382 PetscErrorCode  PetscDrawSetDoubleBuffer(PetscDraw draw)
383 {
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
386   if (draw->ops->setdoublebuffer) {
387     PetscCall((*draw->ops->setdoublebuffer)(draw));
388   }
389   PetscFunctionReturn(0);
390 }
391 
392 /*@C
393    PetscDrawGetSingleton - Gain access to a PetscDraw object as if it were owned
394         by the one process.
395 
396    Collective on PetscDraw
397 
398    Input Parameter:
399 .  draw - the original window
400 
401    Output Parameter:
402 .  sdraw - the singleton window
403 
404    Level: advanced
405 
406 .seealso: `PetscDrawRestoreSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
407 
408 @*/
409 PetscErrorCode  PetscDrawGetSingleton(PetscDraw draw,PetscDraw *sdraw)
410 {
411   PetscMPIInt    size;
412 
413   PetscFunctionBegin;
414   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
415   PetscValidPointer(sdraw,2);
416 
417   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size));
418   if (size == 1) {
419     PetscCall(PetscObjectReference((PetscObject)draw));
420     *sdraw = draw;
421   } else {
422     if (draw->ops->getsingleton) {
423       PetscCall((*draw->ops->getsingleton)(draw,sdraw));
424     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get singleton for this type %s of draw object",((PetscObject)draw)->type_name);
425   }
426   PetscFunctionReturn(0);
427 }
428 
429 /*@C
430    PetscDrawRestoreSingleton - Remove access to a PetscDraw object as if it were owned
431         by the one process.
432 
433    Collective on PetscDraw
434 
435    Input Parameters:
436 +  draw - the original window
437 -  sdraw - the singleton window
438 
439    Level: advanced
440 
441 .seealso: `PetscDrawGetSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
442 
443 @*/
444 PetscErrorCode  PetscDrawRestoreSingleton(PetscDraw draw,PetscDraw *sdraw)
445 {
446   PetscMPIInt    size;
447 
448   PetscFunctionBegin;
449   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
450   PetscValidPointer(sdraw,2);
451   PetscValidHeaderSpecific(*sdraw,PETSC_DRAW_CLASSID,2);
452 
453   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size));
454   if (size == 1) {
455     if (draw == *sdraw) {
456       PetscCall(PetscObjectDereference((PetscObject)draw));
457       *sdraw = NULL;
458     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Cannot restore singleton, it is not the parent draw");
459   } else {
460     if (draw->ops->restoresingleton) {
461       PetscCall((*draw->ops->restoresingleton)(draw,sdraw));
462     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore singleton for this type %s of draw object",((PetscObject)draw)->type_name);
463   }
464   PetscFunctionReturn(0);
465 }
466