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
#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, char *title ) {
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 );
if(title) {
at.x[0] = .5;
at.x[1] = ytick + (ytick-ybase);
sfStrDrawTJ( title, htext, &at, NULL, "c" );
}
}
void Fl_Plot::draw() {
/* draw scene */
if(!valid() || damage() || inpick()) {
/* Assume reshaped */
valid(1);
glViewport( 0, 0, w(), h() );
}
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( x1_ == x0_ ? 1 : 1/(x1_-x0_),
y1_ == y0_ ? 1 : 1/(y1_-y0_), 1 );
glTranslatef( -x0_, -y0_, 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 */
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;
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
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 x0, float x1 ) { x0_ = x0; x1_ = x1; notify(); redraw(); }
void Fl_Plot::yrange( float y0, float y1 ) { y0_ = y0; y1_ = y1; notify(); redraw(); }
void Fl_Plot::xtitle( const char *str ) {
if(xtitle_) Free(xtitle_);
xtitle_ = str ? shmstrdup(str) : NULL;
notify();
redraw();
}
void Fl_Plot::ytitle( const char *str ) {
if(ytitle_) Free(ytitle_);
ytitle_ = str ? shmstrdup(str) : NULL;
notify();
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 );
}
}