NEURON
field.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #if HAVE_IV // to end of file
3 
4 /*
5  * Copyright (c) 1991 Stanford University
6  * Copyright (c) 1991 Silicon Graphics, Inc.
7  *
8  * Permission to use, copy, modify, distribute, and sell this software and
9  * its documentation for any purpose is hereby granted without fee, provided
10  * that (i) the above copyright notices and this permission notice appear in
11  * all copies of the software and related documentation, and (ii) the names of
12  * Stanford and Silicon Graphics may not be used in any advertising or
13  * publicity relating to the software without the specific, prior written
14  * permission of Stanford and Silicon Graphics.
15  *
16  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR
21  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
22  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
24  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
25  * OF THIS SOFTWARE.
26  */
27 
28 /*
29  * FieldSEditor -- simple editor for text fields
30  */
31 
32 #include <Dispatch/dispatcher.h>
33 #include <Dispatch/iocallback.h>
34 //#include <IV-look/field.h>
35 #include "field.h"
36 #include <IV-look/kit.h>
37 #include <InterViews/background.h>
38 #include <InterViews/canvas.h>
39 #include <InterViews/display.h>
40 #include <InterViews/font.h>
41 #include <InterViews/event.h>
42 #include <InterViews/hit.h>
43 #include <InterViews/layout.h>
44 #include <InterViews/printer.h>
45 #include <InterViews/selection.h>
46 #include <InterViews/style.h>
47 #include <InterViews/window.h>
48 #include <IV-2_6/InterViews/button.h>
49 #include <IV-2_6/InterViews/painter.h>
50 #include <IV-2_6/InterViews/sensor.h>
51 #include <IV-2_6/InterViews/streditor.h>
52 #include <IV-2_6/InterViews/textdisplay.h>
53 #include <OS/math.h>
54 #include <OS/string.h>
55 #include <stdio.h>
56 
57 class FieldStringSEditor: public StringEditor {
58  public:
59  FieldStringSEditor(ButtonState* bs, const char* sample, WidgetKit*, Style*);
60  virtual ~FieldStringSEditor();
61 
62  virtual void print(Printer*, const Allocation&) const;
63  virtual void pick(Canvas*, const Allocation&, int depth, Hit&);
64 
65  void press(const Event&);
66  void drag(const Event&);
67  void release(const Event&);
68  bool keystroke(const Event&);
69  void cursor_on();
70  void cursor_off();
71  void focus_in();
72  void focus_out();
73  void cut(SelectionManager*);
74  void paste(SelectionManager*);
75 
76  void Select(int pos);
77  void Select(int left, int right);
78  void selection(int& start, int& index);
79 
80  protected:
81  virtual void Reconfig();
82 
83  private:
84  WidgetKit* kit_;
85  Style* style_;
86  int start_;
87  int index_;
88  int origin_;
89  int width_;
90 
91  void do_select(Event&);
92  void do_grab_scroll(Event&);
93  void do_rate_scroll(Event&);
94 };
95 
96 declareSelectionCallback(FieldStringSEditor)
97 implementSelectionCallback(FieldStringSEditor)
98 
99 FieldStringSEditor::FieldStringSEditor(ButtonState* bs,
100  const char* sample,
101  WidgetKit* kit,
102  Style* style)
103  : StringEditor(bs, sample) {
104  kit_ = kit;
105  style_ = style;
106  Resource::ref(style);
107  delete input;
108  input = NULL;
109  start_ = index_ = -1;
110 }
111 
112 FieldStringSEditor::~FieldStringSEditor() {
113  Resource::unref(style_);
114 }
115 
116 void FieldStringSEditor::Select(int pos) {
117  start_ = index_ = pos;
118  StringEditor::Select(pos);
119 }
120 void FieldStringSEditor::Select(int left, int right) {
121  start_ = left;
122  index_ = right;
123  StringEditor::Select(left, right);
124 }
125 void FieldStringSEditor::selection(int& start, int& index) {
126  start = start_;
127  index = index_;
128 }
129 
130 void FieldStringSEditor::print(Printer* p, const Allocation& a) const {
131  const Font* f = output->GetFont();
132  const Color* fg = output->GetFgColor();
133  FontBoundingBox b;
134  f->font_bbox(b);
135  Coord x = a.left(), y = a.bottom() + b.font_descent();
136  FieldStringSEditor* e = (FieldStringSEditor*) this;
137  for (const char* s = e->Text(); *s != '\0'; s++) {
138  Coord w = f->width(*s);
139  p->character(f, *s, w, fg, x, y);
140  x += w;
141  }
142 }
143 
144 void FieldStringSEditor::pick(Canvas*, const Allocation& a, int depth, Hit& h) {
145  const Event* ep = h.event();
146  if (ep != NULL && h.left() < a.right() && h.right() >= a.left() && h.bottom() < a.top() &&
147  h.top() >= a.bottom()) {
148  h.target(depth, this, 0);
149  }
150 }
151 
152 void FieldStringSEditor::press(const Event& event) {
153  Event e;
154  display->Draw(output, canvas);
155  switch (event.pointer_button()) {
156  case Event::left:
157  case Event::middle:
158  case Event::right:
159  origin_ = display->Left(0, 0);
160  width_ = display->Width();
161  Poll(e);
162  start_ = display->LineIndex(0, e.x);
163  do_select(e);
164  break;
165 #if 0
166  case Event::middle:
167  do_grab_scroll(e);
168  break;
169  case Event::right:
170  do_rate_scroll(e);
171  break;
172 #endif
173  }
174 }
175 
176 void FieldStringSEditor::drag(const Event&) {
177  Event e;
178  // I have no idea why the event.pointer_button() is 0.
179  Poll(e);
180  // if (e.leftmouse)
181  { do_select(e); }
182 }
183 
184 void FieldStringSEditor::release(const Event& event) {
185  Event e;
186  switch (event.pointer_button()) {
187  case Event::left:
188  case Event::middle:
189  case Event::right: {
190  Poll(e);
191  do_select(e);
192  SelectionManager* s = e.display()->primary_selection();
193  s->own(new SelectionCallback(FieldStringSEditor)(this, &FieldStringSEditor::cut));
194  } break;
195  }
196 }
197 
198 void FieldStringSEditor::do_select(Event& e) {
199  if (e.x < 0) {
200  origin_ = Math::min(0, origin_ - e.x);
201  } else if (e.x > xmax) {
202  origin_ = Math::max(xmax - width_, origin_ - (e.x - xmax));
203  }
204  display->Scroll(0, origin_, ymax);
205  index_ = display->LineIndex(0, e.x);
206  DoSelect(start_, index_);
207 }
208 
209 void FieldStringSEditor::do_grab_scroll(Event& e) {
210  Window* w = canvas->window();
211  Cursor* c = w->cursor();
212  w->cursor(kit_->hand_cursor());
213  int origin = display->Left(0, 0);
214  int width = display->Width();
215  Poll(e);
216  int x = e.x;
217  do {
218  origin += e.x - x;
219  origin = Math::min(0, Math::max(Math::min(0, xmax - width), origin));
220  display->Scroll(0, origin, ymax);
221  x = e.x;
222  Poll(e);
223  } while (e.middlemouse);
224  w->cursor(c);
225 }
226 
227 void FieldStringSEditor::do_rate_scroll(Event& e) {
228  Window* w = canvas->window();
229  Cursor* c = w->cursor();
230  WidgetKit& kit = *kit_;
231  Cursor* left = kit.lfast_cursor();
232  Cursor* right = kit.rfast_cursor();
233  int origin = display->Left(0, 0);
234  int width = display->Width();
235  Poll(e);
236  int x = e.x;
237  do {
238  origin += x - e.x;
239  origin = Math::min(0, Math::max(Math::min(0, xmax - width), origin));
240  display->Scroll(0, origin, ymax);
241  if (e.x - x < 0) {
242  w->cursor(left);
243  } else {
244  w->cursor(right);
245  }
246  Poll(e);
247  } while (e.rightmouse);
248  w->cursor(c);
249 }
250 
251 bool FieldStringSEditor::keystroke(const Event& e) {
252  char c;
253  return e.mapkey(&c, 1) != 0 && HandleChar(c) && c == '\t';
254 }
255 
256 void FieldStringSEditor::cursor_on() {
257  if (canvas != NULL) {
258  display->CaretStyle(BarCaret);
259  }
260 }
261 
262 void FieldStringSEditor::cursor_off() {
263  if (canvas != NULL) {
264  display->CaretStyle(NoCaret);
265  }
266 }
267 
268 void FieldStringSEditor::focus_in() {}
269 void FieldStringSEditor::focus_out() {}
270 
271 void FieldStringSEditor::cut(SelectionManager* s) {
272  // s->put_value(Text() + start_, index_ - start_);
273  int st = Math::min(start_, index_);
274  int i = Math::max(index_, start_);
275  s->put_value(Text() + st, i - st);
276 }
277 
278 void FieldStringSEditor::paste(SelectionManager*) {
279  /* unimplemented */
280 }
281 
282 void FieldStringSEditor::Reconfig() {
283  kit_->push_style();
284  kit_->style(style_);
285  Painter* p = new Painter(output);
286  p->SetColors(kit_->foreground(), kit_->background());
287  p->SetFont(kit_->font());
288  Resource::unref(output);
289  output = p;
290  StringEditor::Reconfig();
291  kit_->pop_style();
292 }
293 
294 class FieldSButton: public ButtonState {
295  public:
296  FieldSButton(FieldSEditor*, FieldSEditorAction*);
297  virtual ~FieldSButton();
298 
299  virtual void Notify();
300 
301  private:
302  FieldSEditor* editor_;
303  FieldSEditorAction* action_;
304 };
305 
306 class FieldSEditorImpl {
307  private:
308  friend class FieldSEditor;
309 
310  WidgetKit* kit_;
311  FieldStringSEditor* editor_;
312  FieldSButton* bs_;
313  String text_;
314  bool cursor_is_on_;
315  IOHandler* blink_handler_;
316  long flash_rate_;
317 
318  void build(FieldSEditor*, const char*, FieldSEditorAction*);
319  void blink_cursor(long, long);
320  void stop_blinking();
321 };
322 
323 declareIOCallback(FieldSEditorImpl)
324 implementIOCallback(FieldSEditorImpl)
325 
326 FieldSEditor::FieldSEditor(const String& sample,
327  WidgetKit* kit,
328  Style* s,
329  FieldSEditorAction* action)
330  : InputHandler(NULL, s) {
331  impl_ = new FieldSEditorImpl;
332  impl_->kit_ = kit;
333  NullTerminatedString ns(sample);
334  impl_->build(this, ns.string(), action);
335 }
336 
338  FieldSEditorImpl* i = impl_;
339  i->stop_blinking();
340  Resource::unref(i->editor_);
341  Resource::unref(i->bs_);
342  delete i->blink_handler_;
343  delete i;
344 }
345 
346 void FieldSEditor::undraw() {
347  FieldSEditorImpl& f = *impl_;
348  f.stop_blinking();
349  InputHandler::undraw();
350 }
351 
352 void FieldSEditor::press(const Event& e) {
353  impl_->editor_->press(e);
354 }
355 
356 void FieldSEditor::drag(const Event& e) {
357  impl_->editor_->drag(e);
358 }
359 void FieldSEditor::release(const Event& e) {
360  impl_->editor_->release(e);
361 }
362 
363 void FieldSEditor::keystroke(const Event& e) {
364  FieldSEditorImpl& f = *impl_;
365  if (f.editor_->keystroke(e)) {
366  select(text()->length());
367  next_focus();
368  }
369 }
370 
372  FieldSEditorImpl& f = *impl_;
373  f.blink_cursor(0, 0);
374  f.editor_->focus_in();
375  return InputHandler::focus_in();
376 }
377 
379  FieldSEditorImpl& f = *impl_;
380  f.stop_blinking();
381  f.editor_->cursor_off();
382  f.editor_->focus_out();
383  InputHandler::focus_out();
384 }
385 
386 void FieldSEditor::field(const char* str) {
387  impl_->editor_->Message(str);
388 }
389 
390 void FieldSEditor::field(const String& s) {
391  NullTerminatedString ns(s);
392  impl_->editor_->Message(ns.string());
393 }
394 
395 void FieldSEditor::select(int pos) {
396  impl_->editor_->Select(pos);
397 }
398 
399 void FieldSEditor::select(int l, int r) {
400  impl_->editor_->Select(l, r);
401 }
402 
403 void FieldSEditor::selection(int& start, int& index) const {
404  impl_->editor_->selection(start, index);
405 }
406 
407 void FieldSEditor::edit() {
408  impl_->editor_->Edit();
409 }
410 
411 void FieldSEditor::edit(const char* str, int left, int right) {
412  impl_->editor_->Edit(str, left, right);
413 }
414 
415 void FieldSEditor::edit(const String& str, int left, int right) {
416  NullTerminatedString ns(str);
417  impl_->editor_->Edit(ns.string(), left, right);
418 }
419 
420 const String* FieldSEditor::text() const {
421  impl_->text_ = String(impl_->editor_->Text());
422  return &impl_->text_;
423 }
424 
425 /** class FieldSEditorImpl **/
426 
427 void FieldSEditorImpl::build(FieldSEditor* e, const char* str, FieldSEditorAction* a) {
428  WidgetKit& kit = *kit_;
429  kit.begin_style("FieldEditor");
430  Style* s = kit.style();
431  bs_ = new FieldSButton(e, a);
432  editor_ = new FieldStringSEditor(bs_, str, kit_, s);
433  Glyph* g = editor_;
434  if (s->value_is_on("beveled")) {
435  g = kit.inset_frame(
436  new Background(LayoutKit::instance()->h_margin(editor_, 2.0), kit.background()));
437  }
438  e->body(g);
439  cursor_is_on_ = false;
440  blink_handler_ = new IOCallback(FieldSEditorImpl)(this, &FieldSEditorImpl::blink_cursor);
441  float sec = 0.5;
442  s->find_attribute("cursorFlashRate", sec);
443  flash_rate_ = long(sec * 1000000);
444  kit.end_style();
445 }
446 
447 void FieldSEditorImpl::blink_cursor(long, long) {
448  if (cursor_is_on_) {
449  editor_->cursor_off();
450  cursor_is_on_ = false;
451  } else {
452  editor_->cursor_on();
453  cursor_is_on_ = true;
454  }
455  if (flash_rate_ > 10) {
456  Dispatcher::instance().startTimer(0, flash_rate_, blink_handler_);
457  }
458 }
459 
460 void FieldSEditorImpl::stop_blinking() {
461  Dispatcher::instance().stopTimer(blink_handler_);
462  editor_->cursor_off();
463  cursor_is_on_ = false;
464 }
465 
466 /** class FieldSButton **/
467 
468 FieldSButton::FieldSButton(FieldSEditor* editor, FieldSEditorAction* action) {
469  editor_ = editor;
470  action_ = action;
471  Resource::ref(action_);
472 }
473 
474 FieldSButton::~FieldSButton() {
475  Resource::unref(action_);
476 }
477 
478 /*
479  * We need to reset the button state's value so that we'll get
480  * notified again. If we call SetValue, then it will call
481  * Notify again! Alas, we must access the protected value member (sigh).
482  */
483 
484 void FieldSButton::Notify() {
485  int v;
486  GetValue(v);
487  value = 0;
488  if (action_ != NULL) {
489  switch (v) {
490  case '\r':
491  action_->accept(editor_);
492  break;
493  case /* ^G */ '\007':
494  case /* Esc */ '\033':
495  action_->cancel(editor_);
496  break;
497  default:
498  break;
499  }
500  }
501 }
502 
503 /** class FieldSEditorAction **/
504 
509 #endif
#define InputHandler
Definition: _defines.h:149
#define Window
Definition: _defines.h:330
#define Painter
Definition: _defines.h:196
#define Background
Definition: _defines.h:41
#define Color
Definition: _defines.h:72
#define FontBoundingBox
Definition: _defines.h:119
#define Canvas
Definition: _defines.h:63
#define Style
Definition: _defines.h:278
#define Coord
Definition: _defines.h:17
#define Hit
Definition: _defines.h:145
#define WidgetKit
Definition: _defines.h:328
#define Printer
Definition: _defines.h:209
#define Event
Definition: _defines.h:105
#define Font
Definition: _defines.h:118
#define ButtonState
Definition: _defines.h:62
#define SelectionManager
Definition: _defines.h:254
#define Text
Definition: _defines.h:294
#define Cursor
Definition: _defines.h:83
#define Glyph
Definition: _defines.h:130
#define StringEditor
Definition: _defines.h:277
Coord right() const
Definition: geometry.h:289
Coord top() const
Definition: geometry.h:291
Coord left() const
Definition: geometry.h:288
Coord bottom() const
Definition: geometry.h:290
virtual void cancel(FieldSEditor *)
virtual ~FieldSEditorAction()
virtual void accept(FieldSEditor *)
FieldSEditorImpl * impl_
Definition: field.h:126
virtual void focus_out()
virtual void release(const Event &)
virtual void edit()
virtual const String * text() const
virtual void selection(int &start, int &index) const
virtual void press(const Event &)
virtual ~FieldSEditor()
virtual void undraw()
virtual void select(int pos)
virtual void keystroke(const Event &)
virtual void drag(const Event &)
virtual InputHandler * focus_in()
FieldSEditor(const String &sample, WidgetKit *, Style *, FieldSEditorAction *=NULL)
virtual void field(const char *)
virtual void ref() const
Definition: resource.cpp:42
virtual void unref() const
Definition: resource.cpp:47
#define v
Definition: md1redef.h:11
#define sec
Definition: md1redef.h:20
#define i
Definition: md1redef.h:19
static int c
Definition: hoc.cpp:169
size_t p
s
Definition: multisend.cpp:521
short index
Definition: cabvars.h:11
static uint32_t value
Definition: scoprand.cpp:25
#define NULL
Definition: spdefs.h:105