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 #ifdef MAC
15 #include <IV-Mac/event.h>
16 #include <IV-Mac/window.h>
17 #else
18 #include <IV-X11/xevent.h>
19 #include <IV-X11/xwindow.h>
20 #endif
21 #endif
22 #include <InterViews/event.h>
23 #include <InterViews/handler.h>
24 #include <IV-look/kit.h>
25 #include <InterViews/background.h>
26 #include <InterViews/layout.h>
27 #include <InterViews/box.h>
28 #include <InterViews/session.h>
29 #include <OS/string.h>
30 
31 #include "apwindow.h"
32 #include "ocglyph.h"
33 #include "ivoc.h"
34 #include <stdio.h>
35 #include <string.h>
36 
37 declareActionCallback(PrintableWindow);
38 implementActionCallback(PrintableWindow);
39 
40 extern void single_event_run();
41 
42 extern void handle_old_focus();
43 
44 #ifdef WIN32
45 #include <windows.h>
46 extern int iv_mere_dismiss;
47 #endif
48 
49 #if MAC
50 extern void ivoc_dismiss_defer();
51 #endif
52 
53 // just because avoiding virtual resource
54 /*static*/ class DBAction: public Action {
55  public:
56  DBAction(WinDismiss*);
57  virtual ~DBAction();
58  virtual void diswin(WinDismiss*);
59  virtual void execute();
60 
61  private:
62  friend class DismissableWindow;
63  WinDismiss* wd_;
64 };
65 DBAction::DBAction(WinDismiss* wd) {
66  wd_ = wd;
68 }
69 DBAction::~DBAction() {
70  // printf("~DBAction wd_=%p\n", wd_);
72 }
73 void DBAction::execute() {
74  if (wd_) {
75  wd_->execute();
76  }
77 }
78 
79 void DBAction::diswin(WinDismiss* wd) {
80  Resource::ref(wd);
82  wd_ = wd;
83 }
84 
85 // WinDismiss
86 
88  win_ = w;
89 }
90 
92  // printf("~WinDismiss %p win_=%p\n", this, win_);
93 }
94 
97 
98 void WinDismiss::execute() {
99  if (Oc::helpmode()) {
100  Oc::help("Dismiss GUI");
101  return;
102  }
103  // printf("WinDismiss:: execute win_defer_=%p win_=%p\n", win_defer_,win_);
104  if (win_) {
105  win_->unmap();
106  }
107 #if MAC
108 #else
109  Session::instance()->quit();
110 #endif
111  dismiss_defer();
112  win_defer_ = win_;
113  win_ = NULL;
114 }
115 
116 // the win_defer_longer_ mechanism is a hack to both avoid changing InterViews and to
117 // prevent the deletion of the window during receive processing (A close
118 // event from the window manager). The problem
119 // is that if the window is deleted, then during the Event::handle phase,
120 // the event will still access the window to figure out the target.
121 // Unfortunately, the dismiss_defer mechanism was broken because of the
122 // multiple times it was called (from within Oc::notify()). It is no longer
123 // known what problem that fixed so it is dangerous to remove it from there
124 // For this reason we avoid deleting the window while inside WinDismiss::event
125 
126 bool WinDismiss::event(Event&) {
128  execute();
129  // but maybe it is not supposed to be dismissed
130  if (!win_) {
131  dismiss_defer();
134  }
135  return true;
136 }
137 
138 void ivoc_dismiss_defer() {
140 }
141 
143  /* purify complains when window is deleted during handling of
144  event that occurred in the window. So we defer the deletion
145  */
147  // printf("WinDismiss::dismiss_defer %p %p\n", win_defer_, win_defer_longer_);
148  DismissableWindow* w = win_defer_; // prevents BadDrawable X Errors
149  win_defer_ = NULL;
150  delete w;
151  }
152 }
153 
154 // DismissableWindow
155 
158 
159 
160 #ifdef WIN32
161 DismissableWindow::DismissableWindow(Glyph* g, bool force_menubar)
162  : TransientWindow(
163  new Background(LayoutKit::instance()->vbox(2), WidgetKit::instance()->background()))
164 #else
165 DismissableWindow::DismissableWindow(Glyph* g, bool force_menubar)
166  : TransientWindow(LayoutKit::instance()->vbox(2))
167 #endif
168 {
169  glyph_ = g;
170  Resource::ref(g);
171 #ifdef WIN32
172  PolyGlyph* pg = (PolyGlyph*) ((MonoGlyph*) Window::glyph())->body();
173 #else
174  PolyGlyph* pg = (PolyGlyph*) Window::glyph();
175 #endif
176  wd_ = new WinDismiss(this);
177  wd_->ref();
178  wm_delete(wd_);
179  dbutton_ = NULL;
180  Style* style = Session::instance()->style();
181  String str("Close");
182 #if MAC
183  if (0) {
184 #else
185  if ((style->find_attribute("dismiss_button", str) && str != "off") || force_menubar) {
186 #endif
187  if (!PrintableWindow::leader()) {
188  style->find_attribute("pwm_dismiss_button", str);
189  }
190  dbutton_ = new DBAction(wd_);
192  menubar_ = WidgetKit::instance()->menubar();
194  pg->append(menubar_);
195  MenuItem* mi = append_menubar(str.string());
196  mi->action(dbutton_);
197  } else {
198  menubar_ = NULL;
199  }
200  if (style->find_attribute("use_transient_windows", str) && str == "yes") {
201  is_transient_ = true;
202  }
203  pg->append(g);
204 }
206  // printf("~DismissableWindow %p\n", this);
212 }
213 
215  MenuItem* mi;
216  if (menubar_) {
217  mi = WidgetKit::instance()->menubar_item(LayoutKit::instance()->r_margin(
218  WidgetKit::instance()->fancy_label(name), 0.0, fil, 0.0));
219  menubar_->append_item(mi);
220  return mi;
221  }
222  return NULL;
223 }
224 
226  // unmap();
227  // delete this;
228  wd_->execute();
229 }
230 
231 const char* DismissableWindow::name() const {
232  String v;
233  if (!style()->find_attribute("name", v)) {
234  v = Session::instance()->name();
235  }
236  // printf("DismissableWindow::name %s\n", v.string());
237  return v.string();
238 }
239 #ifdef MINGW
240 static const char* s_;
241 static void setwindowtext(void* v) {
242  HWND hw = (HWND) v;
243  SetWindowText(hw, s_);
244 }
245 #endif
246 
247 void DismissableWindow::name(const char* s) {
248 #ifdef WIN32
249  HWND hw = Window::rep()->msWindow();
250  if (hw) {
251 #ifdef MINGW
252  if (!nrn_is_gui_thread()) {
253  s_ = s;
254  nrn_gui_exec(setwindowtext, hw);
255  } else
256 #endif
257  {
258  SetWindowText(hw, s);
259  }
260  } else
261 #endif
262 #if MAC
263  Str255 st;
264  strncpy(&st[1], s, 254);
265  st[0] = strlen(s);
266  WindowPtr theWin = Window::rep()->macWindow();
267  if (theWin) {
268  SetWTitle(theWin, st);
269  }
270 #endif
271  if (style()) {
272  style()->attribute("name", s);
273  set_props(); // replaces following two statements
274  // rep()->wm_name(this);
275  // rep()->do_set(this, &ManagedWindowRep::set_name);
276  // printf("DismissableWindow::name set to %s\n", name());
277  } else {
278  style(new Style(Session::instance()->style()));
279  style()->attribute("name", s);
280  }
281 }
282 
284  Resource::ref(wd);
286  wd_ = wd;
287  wm_delete(wd_);
288  if (dbutton_) {
289  ((DBAction*) dbutton_)->diswin(wd_);
290  }
291 }
292 
294  if (is_transient()) {
295  TransientWindow::configure();
296  } else {
297  TopLevelWindow::configure();
298  }
299 }
301  if (is_transient()) {
302  TransientWindow::set_attributes();
303  } else {
304  TopLevelWindow::set_attributes();
305  }
306 }
307 
308 // PrintableWindow
310  : DismissableWindow(g) {
311  // printf("PrintableWindow %p\n", this);
312  xplace_ = false;
313  g->window(this);
314  if (intercept_) {
315  intercept_->box_append(g);
316  mappable_ = false;
317  } else {
318  if (!leader_) {
319  leader_ = this;
320  } else {
321  MenuItem* mi = append_menubar("Hide");
322  if (mi) {
323  mi->action(new ActionCallback(PrintableWindow)(this, &PrintableWindow::hide));
324  }
325  }
327  mappable_ = true;
328  }
329  type_ = "";
330 };
332  // printf("~PrintableWindow %p\n", this);
333  ((OcGlyph*) glyph())->window(NULL);
334  if (leader_ == this) {
335  leader_ = NULL; // mswin deletes everthing on quit
336  }
338 }
340  return Window::left();
341 }
343  return Window::bottom();
344 }
346  return Window::width();
347 }
349  return Window::height();
350 }
351 
353  ((Window*) this)->rep()->request_on_resize_ = b;
354 }
355 
357 #if 0
358  Coord decor = 0.;
359  if (style()) {
360  style()->find_attribute("pwm_win_left_decor", decor);
361  }
362  return Window::left() - decor;
363 #else
364  return Coord(xleft());
365 #endif
366 }
367 
369 #if 0
370  Coord decor = 0.;
371  if (style()) {
372  style()->find_attribute("pwm_win_top_decor", decor);
373  }
374  return Window::bottom() + decor;
375 #else
376  return Coord(xtop());
377 #endif
378 }
379 
381  return glyph();
382 }
383 
384 #if MAC && carbon
385 // Apparently the collapse item does not send an event to the application.
386 // Would like to do this only for PrintableWindows but this handler must be
387 // removed whenever theMacWindow is destroyed ( can unbind without deleteing he
388 // PrintableWindow
389 static EventTypeSpec myCollapseTypeSpec[] = {{kEventClassWindow, kEventWindowClickCollapseRgn}};
390 static OSStatus MyHandleCollapse(EventHandlerCallRef, EventRef, void*);
391 static OSStatus MyHandleCollapse(EventHandlerCallRef, EventRef, void* v) {
393  if (PrintableWindow::leader() != w) {
394  w->unmap();
395  } else {
396  return eventNotHandledErr;
397  }
398  return noErr;
399 }
400 #endif
401 
402 void PrintableWindow::map() {
403  if (mappable_) {
405 #if MAC
406  // just can't transform between top and bottom and also take into account decorations.
407  if (xplace_) {
408  xmove(xleft_, xtop_);
409  }
410 #if carbon
411  // it's bound due to the map and according to my checking it will not become
412  // unbound til window deletion
413  EventHandlerUPP myHandleCollapse = NewEventHandlerUPP(
414  (EventHandlerProcPtr) MyHandleCollapse);
415  InstallWindowEventHandler(Window::rep()->macWindow(),
416  myHandleCollapse,
417  1,
418  myCollapseTypeSpec,
419  (void*) this,
420  NULL);
421 #endif
422 #endif
424  notify();
425  } else {
426  delete this;
427  }
428 }
429 
430 void PrintableWindow::unmap() {
432  if (is_mapped()) {
433  // printf("unmap %p xleft=%d xtop=%d\n", this, xleft(), xtop());
434  xplace_ = true;
435  xleft_ = xleft();
436  xtop_ = xtop();
438  }
439  notify();
440 }
441 
443 
446  Resource::ref(b);
448  intercept_ = b;
449  return i;
450 }
451 #ifdef WIN32
452 void virtual_window_top();
453 bool iv_user_keydown(long w) {
454  if (w == 0x70) { // F1
455  virtual_window_top();
456  }
457  return false;
458 }
459 
460 bool PrintableWindow::receive(const Event& e) {
461  if (e.rep()->messageOf() == WM_WINDOWPOSCHANGED) {
462  reconfigured();
463  notify();
464  }
465  return DismissableWindow::receive(e);
466 }
467 #else
468 #if MAC
469 bool PrintableWindow::receive(const Event& e) {
470  reconfigured();
471  notify();
472  return (false);
473 }
474 #else
475 bool PrintableWindow::receive(const Event& e) {
476  DismissableWindow::receive(e);
477  if (e.type() == Event::other_event) {
478  XEvent& xe = e.rep()->xevent_;
479  switch (xe.type) {
480  case ConfigureNotify:
481  reconfigured();
482  notify();
483  break;
484  case MapNotify:
485  if (xplace_) {
486  if (xtop() != xtop_ || xleft() != xleft_) {
487  // printf("MapNotify move %p (%d, %d) to (%d, %d)\n", this, xleft(), xtop(),
488  // xleft_, xtop_);
489  xmove(xleft_, xtop_);
490  }
491  }
492  map_notify();
493  notify();
494  break;
495  case UnmapNotify:
496  // printf("UnMapNotify %p xleft=%d xtop=%d\n", this, xleft(), xtop());
497  // having trouble with remapping after a "hide" that the left and top are
498  // set to incorrect values. i.e.the symptom is that xleft() and xtop() are
499  // wrong by the time we get this event.
500  // xplace_ = true;
501  // xleft_ = xleft();
502  // xtop_ = xtop();
503  unmap_notify();
504  notify();
505  break;
506  case EnterNotify:
507  // printf("EnterNotify\n");
508  Oc::helpmode(this);
509  break;
510  }
511  }
512  return false;
513 }
514 #endif
515 #endif
516 
517 void PrintableWindow::type(const char* s) {
518  type_ = s;
519 }
520 const char* PrintableWindow::type() const {
521  return type_.string();
522 }
523 
524 // StandardWindow
525 
527  : PrintableWindow(new OcGlyph(
528  new Background(LayoutKit::instance()->variable_span(LayoutKit::instance()->vbox(
529  info,
530  m,
531  LayoutKit::instance()->variable_span(LayoutKit::instance()->hbox(
532  l,
533  LayoutKit::instance()->variable_span(
534  LayoutKit::instance()->vbox(WidgetKit::instance()->inset_frame(
535  LayoutKit::instance()->variable_span(main)))),
536  r)))),
537  WidgetKit::instance()->background()))) {
538  m_ = m;
539  can_ = main;
540  info_ = info;
541  l_ = l;
542  r_ = r;
543  Resource::ref(m_);
544  Resource::ref(can_);
545  Resource::ref(info_);
546  Resource::ref(l_);
547  Resource::ref(r_);
548 }
549 
551  // printf("~StandardWindow\n");
557 }
558 
560  return can_;
561 }
563  return m_;
564 }
566  return info_;
567 }
569  return l_;
570 }
572  return r_;
573 }
574 
575 OcGlyph::OcGlyph(Glyph* body)
576  : MonoGlyph(body) {
577  w_ = NULL;
578  parents_ = 0;
579  def_w_ = -1;
580  def_h_ = -1;
581  d_ = NULL;
582  session_priority_ = 1;
583 }
584 
586  // printf("~OcGlyph\n");
587 }
588 
589 void OcGlyph::def_size(Coord& w, Coord& h) const {
590  if (def_w_ > 0) {
591  w = def_w_;
592  h = def_h_;
593  }
594 }
595 
596 void OcGlyph::save(ostream&) {
597  printf("OcGlyph::save (not implemented for relevant class)\n");
598 }
599 
600 bool OcGlyph::has_window() {
601  return (w_ != NULL);
602 }
603 
605  return w_;
606 }
608  w_ = w;
609  parents(w_ != NULL);
610 }
611 
613  new PrintableWindow(this);
614 #if 0
615 if (has_window()) {
616 printf("%s %g %g\n", window()->name(), window()->width(), window()->height());
617 }
618 #endif
619  def_w_ = w;
620  def_h_ = h;
621  if (left >= 0) {
622  w_->xplace((int) left, (int) top);
623  // w_->place(left, bottom);
624  }
625  return w_;
626 }
627 
628 void OcGlyph::parents(bool b) {
629  if (b) {
630  ++parents_;
631  } else {
632  --parents_;
633  }
634  if (parents_ <= 0) {
635  no_parents();
636  parents_ = 0;
637  }
638 }
639 
640 void OcGlyph::no_parents() {}
641 #endif
#define Window
Definition: _defines.h:333
#define Background
Definition: _defines.h:43
#define Menu
Definition: _defines.h:176
#define Style
Definition: _defines.h:281
#define Coord
Definition: _defines.h:19
#define WidgetKit
Definition: _defines.h:331
#define MonoGlyph
Definition: _defines.h:181
#define MenuItem
Definition: _defines.h:179
#define Event
Definition: _defines.h:107
#define PolyGlyph
Definition: _defines.h:207
#define TransientWindow
Definition: _defines.h:318
#define LayoutKit
Definition: _defines.h:161
#define Action
Definition: _defines.h:27
#define Glyph
Definition: _defines.h:132
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:75
Coord def_w_
Definition: ocglyph.h:44
int parents_
Definition: ocglyph.h:43
virtual void save(std::ostream &)
virtual ~OcGlyph()
PrintableWindow * w_
Definition: ocglyph.h:42
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:44
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)
Definition: ivocmac.cpp:187
CopyString type_
Definition: apwindow.h:107
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)
Definition: ivocmac.cpp:242
virtual void unmap()
virtual void unmap_notify()
Definition: apwindow.h:88
int xleft() const
Definition: ivocmac.cpp:195
int xtop() const
Definition: ivocmac.cpp:218
void request_on_resize(bool)
virtual Coord height_pw() const
virtual ~PrintableWindow()
virtual void map_notify()
virtual Coord bottom_pw() const
virtual void hide()
Definition: ivocmac.cpp:183
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:47
virtual void unref() const
Definition: resource.cpp:52
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()
Definition: string.h:34
const char * string() const
Definition: string.h:139
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
void execute(Inst *p)
Definition: code.cpp:2661
#define fil
Definition: coord.h:42
int main()
Definition: macmain.cpp:5
#define v
Definition: md1redef.h:4
#define i
Definition: md1redef.h:12
static double map(void *v)
Definition: mlinedit.cpp:47
char * name
Definition: init.cpp:16
#define printf
Definition: mwprefix.h:26
void single_event_run()
static List * info
static N_Vector w_
static double unmap(void *v)
Definition: ocbox.cpp:248
void handle_old_focus()
#define g
Definition: passive0.cpp:21
#define e
Definition: passive0.cpp:22
#define left
Definition: rbtqueue.cpp:45
#define NULL
Definition: sptree.h:16