Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <string.h>
#include "Plot.H"
#include "sfont.h"
#include "shmem.h"
int Plot_add_drawer( Fl_Plot *plot,
void (*func)( Fl_Plot *, void *obj, void *arg ),
void *obj, void *arg, char *name, int id ) {
plot->add_drawer( func, obj, arg, name, id );
}
int Plot_inpick( Fl_Plot *plot ) { return plot->inpick(); }
void Plot_setpick( Fl_Plot *, void (*pickcb)(Fl_Plot *, int hits, int ents, GLuint *buf) );
Fl_Plot::Fl_Plot(int x, int y, int w, int h, const char *label = 0)
: Fl_Gl_Window(x,y,w,h,label) {
init();
end();
}
int Fl_Plot::add_drawer( void (*func)( Fl_Plot *, void *obj, void *arg ),
void *obj, void *arg, const char *name, int id )
{
if(id < 0) id = next_id();
int dno = withid( id );
if(dno < 0) {
if(ndrawers_ >= maxdrawers_) {
maxdrawers_ = ndrawers_*2 + 15;
int room = maxdrawers_ * sizeof(struct drawer);
drawers_ = (struct drawer *)
(drawers_==NULL ? malloc(room) : realloc(drawers_, room));
}
dno = ndrawers_++;
}
struct drawer *dp = &drawers_[dno];
dp->func = func;
dp->obj = obj;
dp->arg = arg;
dp->name = shmstrdup(name);
dp->id = id;
notify();
redraw();
return id;
}
void Fl_Plot::notify() {
if(notify_ != NULL)
(*notify_)( this, notifyarg_ );
}
int Fl_Plot::withid( int id ) const { // Which drawer[] slot is id in?
for(int dno = 0; dno < ndrawers_; dno++)
if(drawers_[dno].id == id)
return dno;
return -1;
}
int Fl_Plot::next_id() const {
int id;
for(id = 1; withid(id) >= 0; id++)
;
return id;
}
void draw_axis( float v0, float v1, float ybase, float ytick, float htext, char *just ) {
glColor3f( 1,1,1 );
glBegin( GL_LINES );
glVertex2f( 0,ybase );
glVertex2f( 1,ybase );
glVertex2f( 0,ybase );
glVertex2f( 0,ytick );
glVertex2f( 1,ybase );
glVertex2f( 1,ytick );
glEnd();
char lbl[16];
sprintf(lbl, "%.2g", v0);
Point at = { 0, ytick, 0 };
sfStrDrawTJ( lbl, htext, &at, NULL, just );
sprintf(lbl, "%.2g", v1);
at.x[0] = 1;
sfStrDrawTJ( lbl, htext, &at, NULL, just );
}
void Fl_Plot::draw() {
/* draw scene */
if(!valid() || damage() || inpick()) {
/* Assume reshaped */
valid(1);
glViewport( 0, 0, w(), h() );
}
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
glClearDepth( 1.0 );
glColorMask( 1, 1, 1, 1 );
glClearColor( bgcolor_.x[0], bgcolor_.x[1], bgcolor_.x[2], 0 );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDisable( GL_DEPTH_TEST );
glDisable( GL_LIGHTING );
glDisable( GL_TEXTURE_2D );
glDisable( GL_COLOR_MATERIAL );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -.15, 1.05, -.15, 1.05, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glScalef( xmax_ == xmin_ ? 1 : 1/(xmax_-xmin_),
ymax_ == ymin_ ? 1 : 1/(ymax_-ymin_), 1 );
glTranslatef( -xmin_, -ymin_, 0 );
for(int i = 0; i < ndrawers_; i++) {
struct drawer *dp = &drawers_[i];
if(dp->func != NULL)
(*dp->func)( this, dp->obj, dp->arg );
}
glPopMatrix();
/* Draw axes */
draw_axis( xmin_, xmax_, -.01, -.04, .1, "n" );
glPushMatrix();
glRotatef( 90, 0,0,1 );
draw_axis( ymin_, ymax_, .01, .04, .1, "s" );
glPopMatrix();
if(children() > 0)
Fl_Gl_Window::draw();
}
int Fl_Plot::handle(int ev) {
if(eventhook) {
/* Allow clients to pre-screen our events without subclassing */
switch((*eventhook)(this, ev)) {
case 1: return 1; /* pre-screener handled it */
case -1: return 0; /* pre-screener commands us to ignore it too */
default: break; /* Else just process event normally below */
}
}
if(Fl_Gl_Window::handle(ev))
return 1;
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
switch(ev) {
case FL_FOCUS: hasfocus_ = 1; return 1; // Yes, we want FL_KEYBOARD events
case FL_UNFOCUS: hasfocus_ = 0; return 1;
case FL_PUSH:
{ // Besides navigating, grab keyboard focus if we're clicked-on
if(!hasfocus_) take_focus();
}
case FL_DRAG:
case FL_RELEASE:
if(pickcb_ != NULL) {
dpickx_ = Fl::event_x();
dpicky_ = h() - Fl::event_y();
if(ev == FL_PUSH) {
do_pick( dpickx_, dpicky_ );
pickneeded_ = 0;
} else {
if(!pickneeded_) {
pickneeded_ = 1;
Fl::add_idle( Fl_Plot::idlepick, (void *)this );
}
}
return 1;
}
/* Maybe do right-button pick? */
return 0;
case FL_ENTER:
take_focus();
return 1;
case FL_KEYBOARD:
if(Fl::event_text() == NULL || Fl::event_text()[0] == '\0')
return 0;
int c = Fl::event_text()[0];
switch(c) {
case 'p':
case 'P':
do_pick( Fl::event_x_root() - x_root(),
y_root() + h() - Fl::event_y_root() );
break;
case '\033': exit(0); /* ESC */
default: c = 0;
}
/* Maybe check Fl::event_key(FL_HOME), etc.? */
return c==0 ? 0 : 1;
}
return 0;
}
void Fl_Plot::xrange( float xmin, float xmax ) { xmin_ = xmin; xmax_ = xmax; redraw(); }
void Fl_Plot::yrange( float ymin, float ymax ) { ymin_ = ymin; ymax_ = ymax; redraw(); }
void Fl_Plot::picksize( float width, float height ) { }
void Fl_Plot::pickbuffer( int words, GLuint *buf ) { }
void Fl_Plot::picker( void (*pickcb)(Fl_Plot *, int, int, GLuint *, void *arg), void *arg ) { }
int Fl_Plot::pickresults( int *wordsp, GLuint **bufp ) { } /* returns num hits, too */
int Fl_Plot::do_pick( float pickx, float picky ) { } /* Calls back function given by picker() */
int Fl_Plot::snapshot( int x, int y, int w, int h, void *packedrgb ) { }
// Take snapshot into caller-supplied buffer, w*h*3 bytes long
void Fl_Plot::idlepick( void *vthis ) {
Fl_Plot *me = (Fl_Plot *)vthis;
if(me->pickneeded_) {
me->do_pick( me->dpickx_, me->dpicky_ );
me->pickneeded_ = 0;
Fl::remove_idle( Fl_Plot::idlepick, vthis );
}
}