NEURON
apwindow.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 #ifdef WIN32
5 #include <IV-Win/MWlib.h>
6 #endif
7 
8 #include <InterViews/style.h>
9 #include <InterViews/action.h>
10 #ifdef WIN32
11 #include <IV-Win/event.h>
12 #include <IV-Win/window.h>
13 #else
14 #include <IV-X11/xevent.h>
15 #include <IV-X11/xwindow.h>
16 #endif
17 #include <InterViews/event.h>
18 #include <InterViews/handler.h>
19 #include <IV-look/kit.h>
20 #include <InterViews/background.h>
21 #include <InterViews/layout.h>
22 #include <InterViews/box.h>
23 #include <InterViews/session.h>
24 #include <OS/string.h>
25 
26 #include "apwindow.h"
27 #include "ocglyph.h"
28 #include "ivoc.h"
29 #include <stdio.h>
30 #include <string.h>
31 
32 declareActionCallback(PrintableWindow);
33 implementActionCallback(PrintableWindow);
34 
35 extern void single_event_run();
36 
37 extern void handle_old_focus();
38 
39 #ifdef WIN32
40 #include <windows.h>
41 extern int iv_mere_dismiss;
42 #endif
43 
44 // just because avoiding virtual resource
45 /*static*/ class DBAction: public Action {
46  public:
47  DBAction(WinDismiss*);
48  virtual ~DBAction();
49  virtual void diswin(WinDismiss*);
50  virtual void execute();
51 
52  private:
53  friend class DismissableWindow;
54  WinDismiss* wd_;
55 };
56 DBAction::DBAction(WinDismiss* wd) {
57  wd_ = wd;
59 }
60 DBAction::~DBAction() {
61  // printf("~DBAction wd_=%p\n", wd_);
63 }
64 void DBAction::execute() {
65  if (wd_) {
66  wd_->execute();
67  }
68 }
69 
70 void DBAction::diswin(WinDismiss* wd) {
71  Resource::ref(wd);
73  wd_ = wd;
74 }
75 
76 // WinDismiss
77 
79  win_ = w;
80 }
81 
83  // printf("~WinDismiss %p win_=%p\n", this, win_);
84 }
85 
88 
89 void WinDismiss::execute() {
90  if (Oc::helpmode()) {
91  Oc::help("Dismiss GUI");
92  return;
93  }
94  // printf("WinDismiss:: execute win_defer_=%p win_=%p\n", win_defer_,win_);
95  if (win_) {
96  win_->unmap();
97  }
98  Session::instance()->quit();
99  dismiss_defer();
100  win_defer_ = win_;
101  win_ = NULL;
102 }
103 
104 // the win_defer_longer_ mechanism is a hack to both avoid changing InterViews and to
105 // prevent the deletion of the window during receive processing (A close
106 // event from the window manager). The problem
107 // is that if the window is deleted, then during the Event::handle phase,
108 // the event will still access the window to figure out the target.
109 // Unfortunately, the dismiss_defer mechanism was broken because of the
110 // multiple times it was called (from within Oc::notify()). It is no longer
111 // known what problem that fixed so it is dangerous to remove it from there
112 // For this reason we avoid deleting the window while inside WinDismiss::event
113 
114 bool WinDismiss::event(Event&) {
116  execute();
117  // but maybe it is not supposed to be dismissed
118  if (!win_) {
119  dismiss_defer();
122  }
123  return true;
124 }
125 
126 void ivoc_dismiss_defer() {
128 }
129 
131  /* purify complains when window is deleted during handling of
132  event that occurred in the window. So we defer the deletion
133  */
135  // printf("WinDismiss::dismiss_defer %p %p\n", win_defer_, win_defer_longer_);
136  DismissableWindow* w = win_defer_; // prevents BadDrawable X Errors
137  win_defer_ = NULL;
138  delete w;
139  }
140 }
141 
142 // DismissableWindow
143 
146 
147 
148 #ifdef WIN32
149 DismissableWindow::DismissableWindow(Glyph* g, bool force_menubar)
150  : TransientWindow(
151  new Background(LayoutKit::instance()->vbox(2), WidgetKit::instance()->background()))
152 #else
153 DismissableWindow::DismissableWindow(Glyph* g, bool force_menubar)
154  : TransientWindow(LayoutKit::instance()->vbox(2))
155 #endif
156 {
157  glyph_ = g;
158  Resource::ref(g);
159 #ifdef WIN32
160  PolyGlyph* pg = (PolyGlyph*) ((MonoGlyph*) Window::glyph())->body();
161 #else
162  PolyGlyph* pg = (PolyGlyph*) Window::glyph();
163 #endif
164  wd_ = new WinDismiss(this);
165  wd_->ref();
166  wm_delete(wd_);
167  dbutton_ = NULL;
168  Style* style = Session::instance()->style();
169  String str("Close");
170  if ((style->find_attribute("dismiss_button", str) && str != "off") || force_menubar) {
171  if (!PrintableWindow::leader()) {
172  style->find_attribute("pwm_dismiss_button", str);
173  }
174  dbutton_ = new DBAction(wd_);
176  menubar_ = WidgetKit::instance()->menubar();
178  pg->append(menubar_);
179  MenuItem* mi = append_menubar(str.string());
180  mi->action(dbutton_);
181  } else {
182  menubar_ = NULL;
183  }
184  if (style->find_attribute("use_transient_windows", str) && str == "yes") {
185  is_transient_ = true;
186  }
187  pg->append(g);
188 }
190  // printf("~DismissableWindow %p\n", this);
196 }
197 
199  MenuItem* mi;
200  if (menubar_) {
201  mi = WidgetKit::instance()->menubar_item(LayoutKit::instance()->r_margin(
202  WidgetKit::instance()->fancy_label(name), 0.0, fil, 0.0));
203  menubar_->append_item(mi);
204  return mi;
205  }
206  return NULL;
207 }
208 
210  // unmap();
211  // delete this;
212  wd_->execute();
213 }
214 
215 const char* DismissableWindow::name() const {
216  String v;
217  if (!style()->find_attribute("name", v)) {
218  v = Session::instance()->name();
219  }
220  // printf("DismissableWindow::name %s\n", v.string());
221  return v.string();
222 }
223 #ifdef MINGW
224 static const char* s_;
225 static void setwindowtext(void* v) {
226  HWND hw = (HWND) v;
227  SetWindowText(hw, s_);
228 }
229 #endif
230 
231 void DismissableWindow::name(const char* s) {
232 #ifdef WIN32
233  HWND hw = Window::rep()->msWindow();
234  if (hw) {
235 #ifdef MINGW
236  if (!nrn_is_gui_thread()) {
237  s_ = s;
238  nrn_gui_exec(setwindowtext, hw);
239  } else
240 #endif
241  {
242  SetWindowText(hw, s);
243  }
244  } else if (style()) {
245 #else // not WIN32
246  if (style()) {
247 #endif
248  style()->attribute("name", s);
249  set_props(); // replaces following two statements
250  // rep()->wm_name(this);
251  // rep()->do_set(this, &ManagedWindowRep::set_name);
252  // printf("DismissableWindow::name set to %s\n", name());
253  } else {
254  style(new Style(Session::instance()->style()));
255  style()->attribute("name", s);
256  }
257 }
258 
260  Resource::ref(wd);
262  wd_ = wd;
263  wm_delete(wd_);
264  if (dbutton_) {
265  ((DBAction*) dbutton_)->diswin(wd_);
266  }
267 }
268 
270  if (is_transient()) {
271  TransientWindow::configure();
272  } else {
273  TopLevelWindow::configure();
274  }
275 }
277  if (is_transient()) {
278  TransientWindow::set_attributes();
279  } else {
280  TopLevelWindow::set_attributes();
281  }
282 }
283 
284 // PrintableWindow
286  : DismissableWindow(g) {
287  // printf("PrintableWindow %p\n", this);
288  xplace_ = false;
289  g->window(this);
290  if (intercept_) {
291  intercept_->box_append(g);
292  mappable_ = false;
293  } else {
294  if (!leader_) {
295  leader_ = this;
296  } else {
297  MenuItem* mi = append_menubar("Hide");
298  if (mi) {
299  mi->action(new ActionCallback(PrintableWindow)(this, &PrintableWindow::hide));
300  }
301  }
303  mappable_ = true;
304  }
305  type_ = "";
306 };
308  // printf("~PrintableWindow %p\n", this);
309  ((OcGlyph*) glyph())->window(NULL);
310  if (leader_ == this) {
311  leader_ = NULL; // mswin deletes everthing on quit
312  }
314 }
316  return Window::left();
317 }
319  return Window::bottom();
320 }
322  return Window::width();
323 }
325  return Window::height();
326 }
327 
329  ((Window*) this)->rep()->request_on_resize_ = b;
330 }
331 
333 #if 0
334  Coord decor = 0.;
335  if (style()) {
336  style()->find_attribute("pwm_win_left_decor", decor);
337  }
338  return Window::left() - decor;
339 #else
340  return Coord(xleft());
341 #endif
342 }
343 
345 #if 0
346  Coord decor = 0.;
347  if (style()) {
348  style()->find_attribute("pwm_win_top_decor", decor);
349  }
350  return Window::bottom() + decor;
351 #else
352  return Coord(xtop());
353 #endif
354 }
355 
357  return glyph();
358 }
359 
360 void PrintableWindow::map() {
361  if (mappable_) {
364  notify();
365  } else {
366  delete this;
367  }
368 }
369 
370 void PrintableWindow::unmap() {
372  if (is_mapped()) {
373  // printf("unmap %p xleft=%d xtop=%d\n", this, xleft(), xtop());
374  xplace_ = true;
375  xleft_ = xleft();
376  xtop_ = xtop();
378  }
379  notify();
380 }
381 
383 
386  Resource::ref(b);
388  intercept_ = b;
389  return i;
390 }
391 #ifdef WIN32
392 void virtual_window_top();
393 bool iv_user_keydown(long w) {
394  if (w == 0x70) { // F1
395  virtual_window_top();
396  }
397  return false;
398 }
399 
400 bool PrintableWindow::receive(const Event& e) {
401  if (e.rep()->messageOf() == WM_WINDOWPOSCHANGED) {
402  reconfigured();
403  notify();
404  }
405  return DismissableWindow::receive(e);
406 }
407 #else
408 bool PrintableWindow::receive(const Event& e) {
409  DismissableWindow::receive(e);
410  if (e.type() == Event::other_event) {
411  XEvent& xe = e.rep()->xevent_;
412  switch (xe.type) {
413  // LCOV_EXCL_START
414  case ConfigureNotify:
415  reconfigured();
416  notify();
417  break;
418  // LCOV_EXCL_STOP
419  case MapNotify:
420  if (xplace_) {
421  if (xtop() != xtop_ || xleft() != xleft_) {
422  // printf("MapNotify move %p (%d, %d) to (%d, %d)\n", this, xleft(), xtop(),
423  // xleft_, xtop_);
424  xmove(xleft_, xtop_);
425  }
426  }
427  map_notify();
428  notify();
429  break;
430  case UnmapNotify:
431  // printf("UnMapNotify %p xleft=%d xtop=%d\n", this, xleft(), xtop());
432  // having trouble with remapping after a "hide" that the left and top are
433  // set to incorrect values. i.e.the symptom is that xleft() and xtop() are
434  // wrong by the time we get this event.
435  // xplace_ = true;
436  // xleft_ = xleft();
437  // xtop_ = xtop();
438  unmap_notify();
439  notify();
440  break;
441  case EnterNotify:
442  // printf("EnterNotify\n");
443  Oc::helpmode(this);
444  break;
445  }
446  }
447  return false;
448 }
449 #endif
450 
451 void PrintableWindow::type(const char* s) {
452  type_ = s;
453 }
454 const char* PrintableWindow::type() const {
455  return type_.c_str();
456 }
457 
458 // StandardWindow
459 
461  : PrintableWindow(new OcGlyph(
462  new Background(LayoutKit::instance()->variable_span(LayoutKit::instance()->vbox(
463  info,
464  m,
465  LayoutKit::instance()->variable_span(LayoutKit::instance()->hbox(
466  l,
467  LayoutKit::instance()->variable_span(
468  LayoutKit::instance()->vbox(WidgetKit::instance()->inset_frame(
469  LayoutKit::instance()->variable_span(main)))),
470  r)))),
471  WidgetKit::instance()->background()))) {
472  m_ = m;
473  can_ = main;
474  info_ = info;
475  l_ = l;
476  r_ = r;
477  Resource::ref(m_);
478  Resource::ref(can_);
479  Resource::ref(info_);
480  Resource::ref(l_);
481  Resource::ref(r_);
482 }
483 
485  // printf("~StandardWindow\n");
491 }
492 
494  return can_;
495 }
497  return m_;
498 }
500  return info_;
501 }
503  return l_;
504 }
506  return r_;
507 }
508 
509 OcGlyph::OcGlyph(Glyph* body)
510  : MonoGlyph(body) {
511  w_ = NULL;
512  parents_ = 0;
513  def_w_ = -1;
514  def_h_ = -1;
515  d_ = NULL;
516  session_priority_ = 1;
517 }
518 
520  // printf("~OcGlyph\n");
521 }
522 
523 void OcGlyph::def_size(Coord& w, Coord& h) const {
524  if (def_w_ > 0) {
525  w = def_w_;
526  h = def_h_;
527  }
528 }
529 
530 void OcGlyph::save(std::ostream&) {
531  printf("OcGlyph::save (not implemented for relevant class)\n");
532 }
533 
534 bool OcGlyph::has_window() {
535  return (w_ != NULL);
536 }
537 
539  return w_;
540 }
542  w_ = w;
543  parents(w_ != NULL);
544 }
545 
547  new PrintableWindow(this);
548 #if 0
549 if (has_window()) {
550 printf("%s %g %g\n", window()->name(), window()->width(), window()->height());
551 }
552 #endif
553  def_w_ = w;
554  def_h_ = h;
555  if (left >= 0) {
556  w_->xplace((int) left, (int) top);
557  // w_->place(left, bottom);
558  }
559  return w_;
560 }
561 
562 void OcGlyph::parents(bool b) {
563  if (b) {
564  ++parents_;
565  } else {
566  --parents_;
567  }
568  if (parents_ <= 0) {
569  no_parents();
570  parents_ = 0;
571  }
572 }
573 
574 void OcGlyph::no_parents() {}
575 #endif
#define Window
Definition: _defines.h:330
#define Background
Definition: _defines.h:41
#define Menu
Definition: _defines.h:174
#define Style
Definition: _defines.h:278
#define Coord
Definition: _defines.h:17
#define WidgetKit
Definition: _defines.h:328
#define MonoGlyph
Definition: _defines.h:179
#define MenuItem
Definition: _defines.h:177
#define Event
Definition: _defines.h:105
#define PolyGlyph
Definition: _defines.h:205
#define TransientWindow
Definition: _defines.h:315
#define LayoutKit
Definition: _defines.h:159
#define Action
Definition: _defines.h:25
#define Glyph
Definition: _defines.h:130
virtual Glyph * glyph() const
Definition: apwindow.h:47
Action * dbutton_
Definition: apwindow.h:61
DismissableWindow(Glyph *, bool force_menubar=false)
static bool is_transient_
Definition: apwindow.h:62
virtual const char * name() const
MenuItem * append_menubar(const char *)
virtual void dismiss()
virtual ~DismissableWindow()
virtual void set_attributes()
virtual void configure()
Glyph * glyph_
Definition: apwindow.h:59
static bool is_transient()
Definition: apwindow.h:54
WinDismiss * wd_
Definition: apwindow.h:60
virtual void replace_dismiss_action(WinDismiss *)
Menu * menubar_
Definition: apwindow.h:63
virtual void notify()
Definition: observe.cpp:53
Coord def_w_
Definition: ocglyph.h:42
int parents_
Definition: ocglyph.h:41
virtual void save(std::ostream &)
virtual ~OcGlyph()
PrintableWindow * w_
Definition: ocglyph.h:40
void parents(bool)
virtual PrintableWindow * make_window(Coord left=-1, Coord bottom=-1, Coord width=-1, Coord height=-1)
Coord def_h_
Definition: ocglyph.h:42
virtual PrintableWindow * window()
OcGlyph(Glyph *body=NULL)
virtual bool has_window()
virtual void no_parents()
virtual void def_size(Coord &w, Coord &h) const
static void help(const char *)
static bool helpmode()
Definition: ivoc.h:70
virtual Coord width_pw() const
virtual void reconfigured()
void xmove(int left, int top)
static OcGlyphContainer * intercept(OcGlyphContainer *)
static PrintableWindow * leader_
Definition: apwindow.h:113
virtual bool receive(const Event &)
static PrintableWindow * leader()
Definition: apwindow.h:96
virtual Coord save_left() const
static OcGlyphContainer * intercept_
Definition: apwindow.h:108
virtual Coord save_bottom() const
const char * type() const
PrintableWindow(OcGlyph *)
void xplace(int left, int top)
virtual void hide()
virtual void unmap()
virtual void unmap_notify()
Definition: apwindow.h:88
int xleft() const
int xtop() const
void request_on_resize(bool)
virtual Coord height_pw() const
virtual ~PrintableWindow()
std::string type_
Definition: apwindow.h:107
virtual void map_notify()
virtual Coord bottom_pw() const
virtual Glyph * print_glyph()
virtual Coord left_pw() const
virtual void map()
static PrintableWindowManager * current()
void append(PrintableWindow *)
void remove(PrintableWindow *)
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
Glyph * info_
Definition: apwindow.h:135
Glyph * canvas_glyph()
Glyph * r_
Definition: apwindow.h:135
Glyph * info()
Glyph * can_
Definition: apwindow.h:134
Menu * menubar()
Glyph * rbox()
Glyph * lbox()
StandardWindow(Glyph *main, Glyph *info=NULL, Menu *m=NULL, Glyph *l=NULL, Glyph *r=NULL)
Glyph * l_
Definition: apwindow.h:135
virtual ~StandardWindow()
virtual bool event(Event &)
static void dismiss_defer()
static DismissableWindow * win_defer_
Definition: apwindow.h:33
WinDismiss(DismissableWindow *)
DismissableWindow * win_
Definition: apwindow.h:30
virtual ~WinDismiss()
virtual void execute()
static DismissableWindow * win_defer_longer_
Definition: apwindow.h:34
#define fil
Definition: coord.h:41
#define v
Definition: md1redef.h:11
#define i
Definition: md1redef.h:19
int main(int argc, char **argv)
Definition: coreneuron.cpp:12
static double map(void *v)
Definition: mlinedit.cpp:43
printf
Definition: extdef.h:5
const char * name
Definition: init.cpp:16
static List * info
void single_event_run()
s
Definition: multisend.cpp:521
static N_Vector w_
static double unmap(void *v)
Definition: ocbox.cpp:245
void handle_old_focus()
#define NULL
Definition: spdefs.h:105