DialogManager.C 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $ */
  24. /*
  25. *+SNOTICE
  26. *
  27. * $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $
  28. *
  29. * RESTRICTED CONFIDENTIAL INFORMATION:
  30. *
  31. * The information in this document is subject to special
  32. * restrictions in a confidential disclosure agreement bertween
  33. * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
  34. * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
  35. * Sun's specific written approval. This documment and all copies
  36. * and derivative works thereof must be returned or destroyed at
  37. * Sun's request.
  38. *
  39. * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
  40. *
  41. *+ENOTICE
  42. */
  43. ///////////////////////////////////////////////////////////////////////////////
  44. //////////////////////////////////////////////////////////////////////////////
  45. // This example code is from the book:
  46. //
  47. // Object-Oriented Programming with C++ and OSF/Motif
  48. // by
  49. // Douglas Young
  50. // Prentice Hall, 1992
  51. // ISBN 0-13-630252-1
  52. //
  53. // Copyright 1991 by Prentice Hall
  54. // All Rights Reserved
  55. //
  56. // Permission to use, copy, modify, and distribute this software for
  57. // any purpose except publication and without fee is hereby granted, provided
  58. // that the above copyright notice appear in all copies of the software.
  59. ///////////////////////////////////////////////////////////////////////////////
  60. //////////////////////////////////////////////////////////////////////////////
  61. //////////////////////////////////////////////////////////
  62. // DialogManager.C: Support cached dialog widgets
  63. //////////////////////////////////////////////////////////
  64. #include "DialogManager.h"
  65. #include "Application.h"
  66. #include <Xm/MessageB.h>
  67. #include <assert.h>
  68. #include <nl_types.h>
  69. extern nl_catd catd;
  70. #include "NLS.hh"
  71. DialogManager::DialogManager ( char *name ): UIComponent ( name )
  72. {
  73. // Empty
  74. }
  75. Widget DialogManager::getDialog()
  76. {
  77. Widget newDialog = NULL;
  78. // If the permanent widget exists and is not in use,
  79. // just return it
  80. if ( _w && !XtIsManaged ( _w ) )
  81. return _w;
  82. // Get a widget from the derived class
  83. newDialog = createDialog ( theApplication->baseWidget() ) ;
  84. // If this is a temporary dialog, install callbacks to
  85. // destroy it when the user pops it down.
  86. if ( _w )
  87. {
  88. XtAddCallback ( newDialog,
  89. XmNokCallback,
  90. &DialogManager::destroyTmpDialogCallback,
  91. (XtPointer) this );
  92. XtAddCallback ( newDialog,
  93. XmNcancelCallback,
  94. &DialogManager::destroyTmpDialogCallback,
  95. (XtPointer) this );
  96. }
  97. else // If this is the first dialog to be
  98. _w = newDialog; // created, save it to be used again.
  99. return newDialog;
  100. }
  101. Widget DialogManager::getDialog(
  102. Widget w
  103. )
  104. {
  105. Widget newDialog = NULL;
  106. // If the permanent widget exists and is not in use,
  107. // just return it
  108. if ( _w && !XtIsManaged ( _w ) )
  109. return _w;
  110. // Get a widget from the derived class
  111. // Parent the dialog to the widget passed in
  112. newDialog = createDialog (w);
  113. // If this is a temporary dialog, install callbacks to
  114. // destroy it when the user pops it down.
  115. if ( _w )
  116. {
  117. XtAddCallback ( newDialog,
  118. XmNokCallback,
  119. &DialogManager::destroyTmpDialogCallback,
  120. (XtPointer) this );
  121. XtAddCallback ( newDialog,
  122. XmNcancelCallback,
  123. &DialogManager::destroyTmpDialogCallback,
  124. (XtPointer) this );
  125. }
  126. else // If this is the first dialog to be
  127. _w = newDialog; // created, save it to be used again.
  128. return newDialog;
  129. }
  130. void DialogManager::destroyTmpDialogCallback ( Widget w,
  131. XtPointer,
  132. XtPointer clientData)
  133. {
  134. XtDestroyWidget ( w );
  135. // We must set the wiget handle to NULL to prevent multiple
  136. // destroys.
  137. ((DialogManager *)clientData)->_w = NULL;
  138. }
  139. Widget DialogManager::post (char *title,
  140. char *text,
  141. Widget wid,
  142. void *clientData,
  143. DialogCallback ok,
  144. DialogCallback cancel,
  145. DialogCallback help)
  146. {
  147. // Get a dialog widget from the cache
  148. Widget dialog = getDialog(wid);
  149. // Make sure the dialog exists, and that it is an XmMessageBox
  150. // or subclass, since the callbacks assume this widget type
  151. assert ( dialog != NULL );
  152. // assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
  153. // Convert the text string to a compound string and
  154. // specify this to be the message displayed in the dialog.
  155. XmString titleStr = XmStringCreateLocalized (title);
  156. XmString xmstr = XmStringCreateLocalized ( text );
  157. XtVaSetValues ( dialog,
  158. XmNmessageString, xmstr,
  159. XmNdialogTitle, titleStr,
  160. NULL );
  161. XmStringFree ( xmstr );
  162. XmStringFree ( titleStr );
  163. // Create an object to carry the additional data needed
  164. // to cache the dialogs.
  165. DialogCallbackData *dcb = new DialogCallbackData( this,
  166. clientData,
  167. ok, cancel,
  168. help );
  169. // Install callback function for each button
  170. // support by Motif dialogs. If there is no help callback
  171. // unmanage the corresponding button instead, if possible.
  172. if ( ok )
  173. XtAddCallback ( dialog,
  174. XmNokCallback,
  175. &DialogManager::okCallback,
  176. (XtPointer) dcb );
  177. else
  178. {
  179. Widget w = XmMessageBoxGetChild ( dialog,
  180. XmDIALOG_OK_BUTTON );
  181. XtUnmanageChild ( w );
  182. }
  183. if ( cancel )
  184. XtAddCallback ( dialog,
  185. XmNcancelCallback,
  186. &DialogManager::cancelCallback,
  187. (XtPointer) dcb );
  188. else
  189. {
  190. Widget w = XmMessageBoxGetChild ( dialog,
  191. XmDIALOG_CANCEL_BUTTON );
  192. XtUnmanageChild ( w );
  193. }
  194. if ( help )
  195. XtAddCallback ( dialog,
  196. XmNhelpCallback,
  197. &DialogManager::helpCallback,
  198. (XtPointer) dcb );
  199. else
  200. {
  201. Widget w = XmMessageBoxGetChild ( dialog,
  202. XmDIALOG_HELP_BUTTON );
  203. XtUnmanageChild ( w );
  204. }
  205. // Post the dialog.
  206. XtManageChild ( dialog );
  207. return dialog;
  208. }
  209. Widget DialogManager::post (char *title,
  210. char *text,
  211. void *clientData,
  212. DialogCallback ok,
  213. DialogCallback cancel,
  214. DialogCallback help)
  215. {
  216. // Get a dialog widget from the cache
  217. Widget dialog = getDialog();
  218. // Make sure the dialog exists, and that it is an XmMessageBox
  219. // or subclass, since the callbacks assume this widget type
  220. assert ( dialog != NULL );
  221. // assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
  222. // Convert the text string to a compound string and
  223. // specify this to be the message displayed in the dialog.
  224. XmString titleStr = XmStringCreateLocalized (title);
  225. XmString xmstr = XmStringCreateLocalized ( text );
  226. XtVaSetValues ( dialog,
  227. XmNmessageString, xmstr,
  228. XmNdialogTitle, titleStr,
  229. NULL );
  230. XmStringFree ( xmstr );
  231. XmStringFree ( titleStr );
  232. // Create an object to carry the additional data needed
  233. // to cache the dialogs.
  234. DialogCallbackData *dcb = new DialogCallbackData( this,
  235. clientData,
  236. ok, cancel,
  237. help );
  238. // Install callback function for each button
  239. // support by Motif dialogs. If there is no help callback
  240. // unmanage the corresponding button instead, if possible.
  241. if ( ok )
  242. XtAddCallback ( dialog,
  243. XmNokCallback,
  244. &DialogManager::okCallback,
  245. (XtPointer) dcb );
  246. else
  247. {
  248. Widget w = XmMessageBoxGetChild ( dialog,
  249. XmDIALOG_OK_BUTTON );
  250. XtUnmanageChild ( w );
  251. }
  252. if ( cancel )
  253. XtAddCallback ( dialog,
  254. XmNcancelCallback,
  255. &DialogManager::cancelCallback,
  256. (XtPointer) dcb );
  257. else
  258. {
  259. Widget w = XmMessageBoxGetChild ( dialog,
  260. XmDIALOG_CANCEL_BUTTON );
  261. XtUnmanageChild ( w );
  262. }
  263. if ( help )
  264. XtAddCallback ( dialog,
  265. XmNhelpCallback,
  266. &DialogManager::helpCallback,
  267. (XtPointer) dcb );
  268. else
  269. {
  270. Widget w = XmMessageBoxGetChild ( dialog,
  271. XmDIALOG_HELP_BUTTON );
  272. XtUnmanageChild ( w );
  273. }
  274. // Post the dialog.
  275. XtManageChild ( dialog );
  276. return dialog;
  277. }
  278. void DialogManager::okCallback ( Widget w,
  279. XtPointer clientData,
  280. XtPointer )
  281. {
  282. DialogCallbackData *dcd = (DialogCallbackData *) clientData;
  283. DialogManager *obj = (DialogManager *) dcd->dialogManager();
  284. DialogCallback callback;
  285. // If caller specified an ok callback, call the function
  286. if ( ( callback = dcd->ok() ) != NULL )
  287. ( *callback )( dcd->clientData() );
  288. // Reset for the next time
  289. obj->cleanup ( w, dcd );
  290. }
  291. void DialogManager::cancelCallback ( Widget w,
  292. XtPointer clientData,
  293. XtPointer )
  294. {
  295. DialogCallbackData *dcd = (DialogCallbackData *) clientData;
  296. DialogManager *obj = (DialogManager *) dcd->dialogManager();
  297. DialogCallback callback;
  298. if ( ( callback = dcd->cancel() ) != NULL )
  299. ( *callback )( dcd->clientData() );
  300. obj->cleanup ( w, dcd );
  301. }
  302. void DialogManager::helpCallback ( Widget w,
  303. XtPointer clientData,
  304. XtPointer )
  305. {
  306. DialogCallbackData *dcd = (DialogCallbackData *) clientData;
  307. DialogManager *obj = (DialogManager *) dcd->dialogManager();
  308. DialogCallback callback;
  309. if ( ( callback = dcd->help() ) != NULL )
  310. ( *callback )( dcd->clientData() );
  311. obj->cleanup ( w, dcd );
  312. }
  313. void DialogManager::cleanup ( Widget w, DialogCallbackData *dcd )
  314. {
  315. // Remove all callbacks to avoid having duplicate
  316. // callback functions installed.
  317. XtRemoveCallback ( w,
  318. XmNokCallback,
  319. &DialogManager::okCallback,
  320. (XtPointer) dcd );
  321. XtRemoveCallback ( w,
  322. XmNcancelCallback,
  323. &DialogManager::cancelCallback,
  324. (XtPointer) dcd );
  325. XtRemoveCallback ( w,
  326. XmNhelpCallback,
  327. &DialogManager::helpCallback,
  328. (XtPointer) dcd );
  329. // Delete the DialogCallbackData instance for this posting
  330. delete dcd;
  331. }
  332. void
  333. DialogManager::forceUpdate( Widget w )
  334. {
  335. Widget diashell, topshell;
  336. Window diawindow, topwindow;
  337. Display *dpy;
  338. XWindowAttributes xwa;
  339. XEvent event;
  340. if ( !w )
  341. return;
  342. XtAppContext cxt=XtWidgetToApplicationContext( w );
  343. for (diashell=w;!XtIsShell(diashell);diashell=XtParent(diashell));
  344. for ( topshell=diashell;XtIsTopLevelShell( topshell );
  345. topshell = XtParent( topshell ) );
  346. // if (XtIsRealized(diashell) && XtIsRealized(topshell)){
  347. dpy=XtDisplay(diashell);
  348. diawindow=XtWindow(diashell);
  349. topwindow=XtWindow(topshell);
  350. while ( XGetWindowAttributes(dpy,diawindow,&xwa) &&
  351. xwa.map_state != IsViewable && XEventsQueued(dpy,QueuedAlready)){
  352. // if ( XGetWindowAttributes( dpy, topwindow, &xwa ) &&
  353. // xwa.map_state != IsViewable )
  354. // break;
  355. XtAppNextEvent( cxt, &event );
  356. XtDispatchEvent( &event );
  357. }
  358. // }
  359. XmUpdateDisplay(topshell);
  360. }
  361. // Added this extra functionality
  362. void
  363. my_okCallback( int *data )
  364. {
  365. *data=1;
  366. }
  367. void
  368. my_cancelCallback( int *data )
  369. {
  370. *data=2;
  371. }
  372. int
  373. DialogManager::post_and_return(
  374. char *title_str,
  375. char *text_str,
  376. Widget wid
  377. )
  378. {
  379. int answer = 0;
  380. XmString okLabel, cancelLabel;
  381. // They may have been set via the overloaded post_and_return()
  382. // method before. Reset them to their default values...
  383. okLabel = XmStringCreateLocalized(GETMSG(catd, 1, 2, "OK"));
  384. cancelLabel = XmStringCreateLocalized(GETMSG(catd, 1, 3, "Cancel"));
  385. Widget dlg = this->getDialog(wid);
  386. // Make sure the dialog exists, and that it is an XmMessageBox
  387. // or subclass, since the callbacks assume this widget type
  388. assert ( dlg != NULL );
  389. XtVaSetValues(dlg,
  390. XmNokLabelString, okLabel,
  391. XmNcancelLabelString, cancelLabel,
  392. NULL);
  393. Widget dialog =
  394. this->post(title_str,
  395. text_str,
  396. wid,
  397. (void *) &answer,
  398. ( DialogCallback ) &my_okCallback,
  399. ( DialogCallback ) &my_cancelCallback);
  400. forceUpdate( dialog );
  401. while ( answer==0 )
  402. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  403. // Process just one more event to pop down dialog.
  404. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  405. return(answer);
  406. }
  407. int
  408. DialogManager::post_and_return(
  409. char *title_str,
  410. char *text_str,
  411. char *okLabelString,
  412. Widget wid
  413. )
  414. {
  415. int answer = 0;
  416. XmString okLabel;
  417. okLabel = XmStringCreateLocalized(okLabelString);
  418. Widget dlg = this->getDialog(wid);
  419. // Make sure the dialog exists, and that it is an XmMessageBox
  420. // or subclass, since the callbacks assume this widget type
  421. assert ( dlg != NULL );
  422. XtVaSetValues(dlg,
  423. XmNokLabelString, okLabel,
  424. NULL);
  425. Widget dialog = this->post(title_str,
  426. text_str,
  427. wid,
  428. (void *) &answer,
  429. ( DialogCallback ) &my_okCallback);
  430. forceUpdate( dialog );
  431. while ( answer==0 )
  432. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  433. // Process just one more event to pop down dialog.
  434. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  435. return(answer);
  436. }
  437. int
  438. DialogManager::post_and_return(
  439. char *title_str,
  440. char *text_str,
  441. char *okLabelString,
  442. char *cancelLabelString,
  443. Widget wid
  444. )
  445. {
  446. int answer = 0;
  447. XmString okLabel, cancelLabel;
  448. okLabel = XmStringCreateLocalized(okLabelString);
  449. cancelLabel = XmStringCreateLocalized(cancelLabelString);
  450. Widget dlg = this->getDialog(wid);
  451. // Make sure the dialog exists, and that it is an XmMessageBox
  452. // or subclass, since the callbacks assume this widget type
  453. assert ( dlg != NULL );
  454. XtVaSetValues(dlg,
  455. XmNokLabelString, okLabel,
  456. XmNcancelLabelString, cancelLabel,
  457. NULL);
  458. Widget dialog = this->post(title_str,
  459. text_str,
  460. wid,
  461. (void *) &answer,
  462. ( DialogCallback ) &my_okCallback,
  463. ( DialogCallback ) &my_cancelCallback);
  464. forceUpdate( dialog );
  465. while ( answer==0 )
  466. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  467. // Process just one more event to pop down dialog.
  468. XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
  469. return(answer);
  470. }