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