horizontal cursors in graphs
This commit is contained in:
parent
9fda7e2f96
commit
a3e7610d83
|
|
@ -66,9 +66,6 @@ p{padding: 15px 30px 10px;}
|
|||
<kbd>Waves->Op | Ac | Dc | Tran | Tran | Noise | Sp </kbd>. This command loads the user selected
|
||||
.raw file produced by a ngspice/Xyce simulation.
|
||||
</p>
|
||||
<p class="important">
|
||||
Ensure the <kbd>circuit.raw</kbd> is saved in binary format (no <kbd>set filetype=ascii</kbd> in your testbench)
|
||||
</p>
|
||||
<p>
|
||||
The raw file is usually located in the simulation/netlisting directory
|
||||
<kbd>Simulation ->set netlist dir</kbd>.<br>
|
||||
|
|
@ -80,6 +77,17 @@ p{padding: 15px 30px 10px;}
|
|||
Then, select a node or a net label, press 'Alt-G', the net will be added to the graph. Here after a
|
||||
list of commands you can perform in a graph to modify the viewport. These commands are active when
|
||||
the mouse is Inside the graph (you will notice the mouse pointer changing from an arrow to a <kbd>+</kbd>).
|
||||
</p>
|
||||
<p class="important">
|
||||
if <kbd>set graph_use_ctrl_key 1</kbd> is set in the <kbd>xschemrc</kbd> file all bind keys shown
|
||||
below will need the <kbd>Control</kbd> key pressed to operate on the graphs. This setting can be used
|
||||
to make it more explicit when the user wants to operate on graphs. Without the <kbd>Control</kbd>
|
||||
key pressed the usual functions on schematic are performed instead of graph functions.<br>
|
||||
Example: the key <kbd>a</kbd> will create a symbol if used in a schematic while it shows a cursor
|
||||
if done when the mouse pointer is inside a graph. With the <kbd>set graph_use_ctrl_key 1</kbd> option
|
||||
you will need to press <kbd>Control-a</kbd> with the mouse pointer inside a graph to show a cursor.
|
||||
</p>
|
||||
<p>
|
||||
if the mouse is outside the graph the usual Xschem functions will be available to operate on schematics:
|
||||
</p>
|
||||
<ul>
|
||||
|
|
@ -87,13 +95,14 @@ p{padding: 15px 30px 10px;}
|
|||
<li>Pressing <kbd>f</kbd> with the mouse on the left of the Y axis will do a full Y-axis zoom.</li>
|
||||
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is inside a graph will
|
||||
move the waveforms to the left/right or zoom in/zoom out respectively.</li>
|
||||
<li>Pressing <kbd>Left/Right</kbd> or <kbd>Up/Down</kbd> arrow keys while the mouse is on the left of the Y-axis
|
||||
will move the waveforms or zoom in/zoom out in the Y direction respectively.</li>
|
||||
<li>Pressing <kbd>Left/Right</kbd> arrow keys while the mouse is on the left of the Y-axis
|
||||
will zoom in/zoom out in the Y direction.</li>
|
||||
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is in the center of the graph
|
||||
will move the waves left or right following the pointer X movement.</li>
|
||||
<li>Pressing the <kbd>left</kbd> mouse button while the pointer is on the left of the Y-axis
|
||||
will move the waves high or low following the pointer Y movement.</li>
|
||||
<li> Doing the above with the <kbd>Shift</kbd> key pressed will zoom in/out instead of moving.</li>
|
||||
<li> pressing <kbd>A</kbd> and/or <kbd>B</kbd> will show a horizontal cursor.
|
||||
The difference between the <kbd>A</kbd> and the <kbd>B</kbd> cursor is shown.</li>
|
||||
<li> pressing <kbd>a</kbd> and/or <kbd>b</kbd> will show a vertical cursor.
|
||||
The sweep variable difference between the <kbd>a</kbd> and the <kbd>b</kbd> cursor is shown and
|
||||
the values of all signals at the X position of the <kbd>a</kbd> cursor is shown. </li>
|
||||
|
|
|
|||
179
src/callback.c
179
src/callback.c
|
|
@ -46,7 +46,7 @@ static int waves_selected(int event, KeySym key, int state, int button)
|
|||
else if(event == ButtonPress && button == Button2) skip = 1;
|
||||
else if(event == ButtonPress && button == Button1 && (state & ShiftMask) ) skip = 1;
|
||||
else if(event == ButtonRelease && button == Button2) skip = 1;
|
||||
else if(event == KeyPress && (state & ShiftMask)) skip = 1;
|
||||
/* else if(event == KeyPress && (state & ShiftMask)) skip = 1; */
|
||||
else if(!skip) for(i=0; i< xctx->rects[GRIDLAYER]; ++i) {
|
||||
xRect *r;
|
||||
r = &xctx->rect[GRIDLAYER][i];
|
||||
|
|
@ -68,6 +68,7 @@ static int waves_selected(int event, KeySym key, int state, int button)
|
|||
is_inside = 1;
|
||||
if(draw_xhair) draw_crosshair(1);
|
||||
tclvareval(xctx->top_path, ".drw configure -cursor tcross" , NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!is_inside) {
|
||||
|
|
@ -366,7 +367,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
int save_mouse_at_end = 0, clear_graphpan_at_end = 0;
|
||||
int track_dset = -2; /* used to find dataset of closest wave to mouse if 't' is pressed */
|
||||
xRect *r = NULL;
|
||||
int access_cond = !graph_use_ctrl_key || ( (state & ControlMask) && !(state & ShiftMask) );
|
||||
int access_cond = !graph_use_ctrl_key || (state & ControlMask);
|
||||
|
||||
if(event != -3 && !xctx->raw) return 0;
|
||||
rstate = state; /* rstate does not have ShiftMask bit, so easier to test for KeyPress events */
|
||||
|
|
@ -392,9 +393,27 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
dbg(1, "mouse inside: %d\n", i);
|
||||
setup_graph_data(i, 0, gr);
|
||||
|
||||
/* move hcursor1 */
|
||||
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 512 )) {
|
||||
double c;
|
||||
|
||||
c = G_Y(xctx->mousey);
|
||||
if(gr->logy) c = pow(10, c);
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
|
||||
}
|
||||
|
||||
/* move hcursor2 */
|
||||
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 1024 )) {
|
||||
double c;
|
||||
|
||||
c = G_Y(xctx->mousey);
|
||||
if(gr->logy) c = pow(10, c);
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
|
||||
}
|
||||
|
||||
/* move cursor1 */
|
||||
/* set cursor position from master graph x-axis */
|
||||
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
|
||||
else if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
|
||||
double c;
|
||||
|
||||
c = G_X(xctx->mousex);
|
||||
|
|
@ -448,7 +467,27 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
zoom_m = (xctx->mousex - gr->x1) / gr->w;
|
||||
if(event == ButtonPress && button == Button1) {
|
||||
/* dragging cursors when mouse is very close */
|
||||
if(xctx->graph_flags & 2) {
|
||||
if(xctx->graph_flags & 128) { /* hcursor1 */
|
||||
double cursor;
|
||||
cursor = gr->hcursor1_y;
|
||||
if(gr->logy ) {
|
||||
cursor = mylog10(cursor);
|
||||
}
|
||||
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
|
||||
xctx->graph_flags |= 512; /* Start move hcursor1 */
|
||||
}
|
||||
}
|
||||
if(xctx->graph_flags & 256) { /* hcursor2 */
|
||||
double cursor;
|
||||
cursor = gr->hcursor2_y;
|
||||
if(gr->logy ) {
|
||||
cursor = mylog10(cursor);
|
||||
}
|
||||
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
|
||||
xctx->graph_flags |= 1024; /* Start move hcursor2 */
|
||||
}
|
||||
}
|
||||
if(xctx->graph_flags & 2) { /* cursor1 */
|
||||
double cursor1;
|
||||
if(r->flags & 4) { /* private_cursor */
|
||||
const char *s = get_tok_value(r->prop_ptr, "cursor1_x", 0);
|
||||
|
|
@ -467,7 +506,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
xctx->graph_flags |= 16; /* Start move cursor1 */
|
||||
}
|
||||
}
|
||||
if(xctx->graph_flags & 4) {
|
||||
if(xctx->graph_flags & 4) { /* cursor2 */
|
||||
double cursor2;
|
||||
if(r->flags & 4) { /* private_cursor */
|
||||
const char *s = get_tok_value(r->prop_ptr, "cursor2_x", 0);
|
||||
|
|
@ -518,7 +557,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
}
|
||||
redraw_all_at_end = 1;
|
||||
}
|
||||
|
||||
/* Numerically set cursor position */
|
||||
if(xctx->graph_flags & 4) {
|
||||
double cursor2;
|
||||
if(r->flags & 4) { /* private_cursor */
|
||||
|
|
@ -678,7 +717,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
/* check if user clicked on a wave label -> draw wave in bold */
|
||||
if(event == ButtonPress && button == Button3 &&
|
||||
edit_wave_attributes(2, i, gr)) {
|
||||
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in graph box */
|
||||
draw_graph(i, 1 + 8 + (xctx->graph_flags & (2 | 4 | 128 | 256)), gr, NULL); /* draw data in graph box */
|
||||
return 0;
|
||||
}
|
||||
/* save mouse position when doing pan operations */
|
||||
|
|
@ -800,7 +839,12 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
dbg(1, "%g %g %g %g - %d %d\n", gr->gx1, gr->gy1, gr->gx2, gr->gy2, gr->divx, gr->divy);
|
||||
if( event == KeyPress || event == ButtonPress || event == MotionNotify ) {
|
||||
/* move cursor1 */
|
||||
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16 )) {
|
||||
if(event == MotionNotify && (state & Button1Mask) && (xctx->graph_flags & 16)) {
|
||||
need_redraw = 1;
|
||||
}
|
||||
/* move hcursor1 or hcursor2 */
|
||||
else if(event == MotionNotify && i == xctx->graph_master &&
|
||||
(state & Button1Mask) && (xctx->graph_flags & (512 | 1024) )) {
|
||||
need_redraw = 1;
|
||||
}
|
||||
/* move cursor2 */
|
||||
|
|
@ -811,7 +855,8 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
else need_redraw = 1;
|
||||
}
|
||||
else /* drag waves with mouse */
|
||||
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom) {
|
||||
if(event == MotionNotify && (state & Button1Mask) && !xctx->graph_bottom &&
|
||||
!(xctx->graph_flags & (16 | 32 | 512 | 1024))) {
|
||||
double delta;
|
||||
if(xctx->graph_left) {
|
||||
if(i == xctx->graph_master) {
|
||||
|
|
@ -856,6 +901,36 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
}
|
||||
}
|
||||
}
|
||||
else if(event == ButtonPress && button == Button3) {
|
||||
/* Numerically set hcursor position */
|
||||
if(xctx->graph_flags & 128) {
|
||||
double cursor;
|
||||
cursor = gr->hcursor1_y;
|
||||
if(gr->logy ) {
|
||||
cursor = mylog10(cursor);
|
||||
}
|
||||
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
|
||||
tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor), NULL);
|
||||
cursor = atof_spice(tclresult());
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(cursor)));
|
||||
}
|
||||
need_redraw = 1;
|
||||
}
|
||||
/* Numerically set hcursor position */
|
||||
if(xctx->graph_flags & 256) {
|
||||
double cursor;
|
||||
cursor = gr->hcursor2_y;
|
||||
if(gr->logy ) {
|
||||
cursor = mylog10(cursor);
|
||||
}
|
||||
if(fabs(xctx->mousey - W_Y(cursor)) < 10) {
|
||||
tclvareval("input_line {Pos:} {} ", dtoa_eng(cursor), NULL);
|
||||
cursor = atof_spice(tclresult());
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(cursor)));
|
||||
}
|
||||
need_redraw = 1;
|
||||
}
|
||||
}
|
||||
else if((button == Button5 && !(state & ShiftMask))) {
|
||||
double delta;
|
||||
if(xctx->graph_left) {
|
||||
|
|
@ -890,6 +965,30 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
}
|
||||
}
|
||||
}
|
||||
/* y hcursor1 toggle */
|
||||
else if(key == 'A' && access_cond && i == xctx->graph_master) {
|
||||
xctx->graph_flags ^= 128;
|
||||
need_redraw = 1;
|
||||
if(xctx->graph_flags & 128) {
|
||||
double c = G_Y(xctx->mousey);
|
||||
if(gr->logy) c = pow(10, c);
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", dtoa(c)));
|
||||
} else {
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor1_y", NULL));
|
||||
}
|
||||
}
|
||||
/* y hcursor2 toggle */
|
||||
else if(key == 'B' && access_cond && i == xctx->graph_master) {
|
||||
xctx->graph_flags ^= 256;
|
||||
need_redraw = 1;
|
||||
if(xctx->graph_flags & 256) {
|
||||
double c = G_Y(xctx->mousey);
|
||||
if(gr->logy) c = pow(10, c);
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", dtoa(c)));
|
||||
} else {
|
||||
my_strdup(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "hcursor2_y", NULL));
|
||||
}
|
||||
}
|
||||
else if(key == 't' && access_cond ) {
|
||||
if(track_dset != -2) {
|
||||
/*
|
||||
|
|
@ -1161,7 +1260,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
else if( event == ButtonRelease) {
|
||||
if(button != Button3) {
|
||||
xctx->ui_state &= ~GRAPHPAN;
|
||||
xctx->graph_flags &= ~(16 | 32); /* clear move cursor flags */
|
||||
xctx->graph_flags &= ~(16 | 32 | 512 | 1024); /* clear move cursor flags */
|
||||
}
|
||||
/* zoom area by mouse drag */
|
||||
else if(button == Button3 && (xctx->ui_state & GRAPHPAN) &&
|
||||
|
|
@ -1191,7 +1290,7 @@ static int waves_callback(int event, int mx, int my, KeySym key, int button, int
|
|||
} /* else if( event == ButtonRelease) */
|
||||
if(need_redraw || need_all_redraw) {
|
||||
setup_graph_data(i, 0, gr);
|
||||
draw_graph(i, 1 + 8 + (xctx->graph_flags & 6), gr, NULL); /* draw data in each graph box */
|
||||
draw_graph(i, 1 + 8 + (xctx->graph_flags & (4 | 2 | 128 | 256)), gr, NULL); /* draw data in each graph box */
|
||||
}
|
||||
} /* for(i=0; i< xctx->rects[GRIDLAYER]; i++ */
|
||||
|
||||
|
|
@ -2699,17 +2798,27 @@ int rstate; /* (reduced state, without ShiftMask) */
|
|||
}
|
||||
if(key==XK_Right && state == ControlMask) {
|
||||
int save = xctx->semaphore;
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
if(xctx->semaphore >= 2) break;
|
||||
xctx->semaphore = 0;
|
||||
tcleval("next_tab");
|
||||
xctx->semaphore = save;
|
||||
break;
|
||||
}
|
||||
if(key==XK_Left && state == ControlMask) {
|
||||
int save = xctx->semaphore;
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
if(xctx->semaphore >= 2) break;
|
||||
xctx->semaphore = 0;
|
||||
tcleval("prev_tab");
|
||||
xctx->semaphore = save;
|
||||
break;
|
||||
}
|
||||
if(key==XK_Right && !(state & ControlMask)) /* left */
|
||||
{
|
||||
|
|
@ -3589,20 +3698,32 @@ int rstate; /* (reduced state, without ShiftMask) */
|
|||
|
||||
break;
|
||||
}
|
||||
if(key=='A' && rstate == ControlMask) /* only for graph (toggle hcursor1 if graph_use_ctrl_key set) */
|
||||
{
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(key=='A' && rstate == 0) /* toggle show netlist */
|
||||
{
|
||||
int net_s;
|
||||
net_s = tclgetboolvar("netlist_show");
|
||||
net_s = !net_s;
|
||||
if(net_s) {
|
||||
tcleval("alert_ { enabling show netlist window} {}");
|
||||
tclsetvar("netlist_show","1");
|
||||
}
|
||||
else {
|
||||
tcleval("alert_ { disabling show netlist window } {}");
|
||||
tclsetvar("netlist_show","0");
|
||||
}
|
||||
break;
|
||||
int net_s;
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
net_s = tclgetboolvar("netlist_show");
|
||||
net_s = !net_s;
|
||||
if(net_s) {
|
||||
tcleval("alert_ { enabling show netlist window} {}");
|
||||
tclsetvar("netlist_show","1");
|
||||
}
|
||||
else {
|
||||
tcleval("alert_ { disabling show netlist window } {}");
|
||||
tclsetvar("netlist_show","0");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(key=='>') {
|
||||
if(xctx->semaphore >= 2) break;
|
||||
|
|
@ -3628,8 +3749,20 @@ int rstate; /* (reduced state, without ShiftMask) */
|
|||
}
|
||||
break;
|
||||
}
|
||||
if(key=='B' && rstate == ControlMask) /* only for graph (toggle hcursor2 if graph_use_ctrl_key set) */
|
||||
{
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(key=='B' && rstate == 0) /* edit schematic header/license */
|
||||
{
|
||||
if(waves_selected(event, key, state, button)) {
|
||||
waves_callback(event, mx, my, key, button, aux, state);
|
||||
break;
|
||||
}
|
||||
tcleval("update_schematic_header");
|
||||
}
|
||||
if(key=='b' && rstate==0) /* merge schematic */
|
||||
|
|
|
|||
80
src/draw.c
80
src/draw.c
|
|
@ -2905,7 +2905,18 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
|
|||
gr->digital = 0;
|
||||
gr->rainbow = 0;
|
||||
gr->linewidth_mult = tclgetdoublevar("graph_linewidth_mult");
|
||||
|
||||
xctx->graph_flags &= ~(128 | 256); /* clear hcursor flags */
|
||||
gr->hcursor1_y = gr->hcursor2_y = 0.0;
|
||||
val = get_tok_value(r->prop_ptr,"hcursor1_y", 0);
|
||||
if(val[0]) {
|
||||
gr->hcursor1_y = atof_spice(val);
|
||||
xctx->graph_flags |= 128;
|
||||
}
|
||||
val = get_tok_value(r->prop_ptr,"hcursor2_y", 0);
|
||||
if(val[0]) {
|
||||
gr->hcursor2_y = atof_spice(val);
|
||||
xctx->graph_flags |= 256;
|
||||
}
|
||||
if(!skip) {
|
||||
gr->gx1 = 0;
|
||||
gr->gx2 = 1e-6;
|
||||
|
|
@ -3016,9 +3027,9 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
|
|||
gr->gh = gr->gy2 - gr->gy1;
|
||||
/* set margins */
|
||||
tmp = gr->rw * 0.14;
|
||||
gr->marginx = tmp < 30 ? 30 : tmp;
|
||||
gr->marginx = tmp < 50 ? 50 : tmp;
|
||||
tmp = gr->rh * 0.14;
|
||||
gr->marginy = tmp < 35 ? 35 : tmp;
|
||||
gr->marginy = tmp < 40 ? 40 : tmp;
|
||||
|
||||
/* calculate graph bounding box (container - margin)
|
||||
* This is the box where plot is done */
|
||||
|
|
@ -3031,7 +3042,7 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
|
|||
gr->h = gr->y2 - gr->y1;
|
||||
|
||||
/* label text size calculations */
|
||||
gr->txtsizelab = gr->marginy * 0.007;
|
||||
gr->txtsizelab = gr->marginy * 0.006;
|
||||
/*
|
||||
* tmp = gr->w * 0.00044;
|
||||
* if(tmp < gr->txtsizelab) gr->txtsizelab = tmp;
|
||||
|
|
@ -3042,8 +3053,8 @@ void setup_graph_data(int i, int skip, Graph_ctx *gr)
|
|||
gr->digtxtsizelab = 0.001200 * fabs( gr->h / gr->posh * gr->gh );
|
||||
|
||||
/* x axis, y axis text sizes */
|
||||
gr->txtsizey = gr->h / gr->divy * 0.009;
|
||||
tmp = gr->marginx * 0.005;
|
||||
gr->txtsizey = gr->h / gr->divy * 0.0095;
|
||||
tmp = gr->marginx * 0.003;
|
||||
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
|
||||
tmp = gr->marginy * 0.02;
|
||||
if(tmp < gr->txtsizey) gr->txtsizey = tmp;
|
||||
|
|
@ -3136,7 +3147,7 @@ static void draw_cursor_difference(double c1, double c2, Graph_ctx *gr)
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_hcursor(double active_cursory, double other_cursory, int cursor_color, Graph_ctx *gr)
|
||||
static void draw_hcursor(double active_cursory, int cursor_color, Graph_ctx *gr)
|
||||
{
|
||||
double yy, pos = active_cursory;
|
||||
double tx1, ty1, tx2, ty2, dtmp;
|
||||
|
|
@ -3145,10 +3156,11 @@ static void draw_hcursor(double active_cursory, double other_cursory, int cursor
|
|||
double txtsize = gr->txtsizey;
|
||||
double th;
|
||||
|
||||
if(gr->digital) return;
|
||||
if(gr->logy) pos = mylog10(pos);
|
||||
yy = W_Y(pos);
|
||||
if(yy >= gr->y1 && yy <= gr->y2) {
|
||||
drawline(cursor_color, NOW, gr->rx1, yy, gr->rx2, yy, 1, NULL);
|
||||
drawline(cursor_color, NOW, gr->rx1 + 10, yy, gr->rx2 - 10, yy, 1, NULL);
|
||||
if(gr->unity != 1.0)
|
||||
my_snprintf(tmpstr, S(tmpstr), " %.5g%c ", gr->unity * active_cursory , gr->unity_suffix);
|
||||
else
|
||||
|
|
@ -3164,7 +3176,41 @@ static void draw_hcursor(double active_cursory, double other_cursory, int cursor
|
|||
|
||||
static void draw_hcursor_difference(double c1, double c2, Graph_ctx *gr)
|
||||
{
|
||||
/* <<<<< */
|
||||
int tmp;
|
||||
char tmpstr[100];
|
||||
double txtsize = gr->txtsizey;
|
||||
double tx1, ty1, tx2, ty2;
|
||||
double cc1 = gr->logy ? mylog10(c1) : c1;
|
||||
double cc2 = gr->logy ? mylog10(c2) : c2;
|
||||
double aa = W_Y(cc1);
|
||||
double a = CLIP(aa, gr->y1, gr->y2);
|
||||
double bb = W_Y(cc2);
|
||||
double b = CLIP(bb, gr->y1, gr->y2);
|
||||
double diff = fabs(b - a);
|
||||
double diffh;
|
||||
double yy = ( a + b ) * 0.5;
|
||||
double xx = gr->rx1 + 5;
|
||||
double dtmp;
|
||||
double xline;
|
||||
|
||||
if(gr->digital) return;
|
||||
diffh = fabs(c2 - c1);
|
||||
if(gr->unity != 1.0)
|
||||
my_snprintf(tmpstr, S(tmpstr), " %.4g%c ", gr->unity * diffh , gr->unity_suffix);
|
||||
else
|
||||
my_snprintf(tmpstr, S(tmpstr), " %s ", dtoa_eng(diffh));
|
||||
text_bbox(tmpstr, txtsize, txtsize, 0, 0, 0, 1, xx, yy, &tx1, &ty1, &tx2, &ty2, &tmp, &dtmp);
|
||||
if( 2 * (ty2 - ty1) < diff ) {
|
||||
filledrect(0, NOW, tx1, ty1, tx2, ty2, 3, -1, -1);
|
||||
draw_string(3, NOW, tmpstr, 0, 0, 0, 1, xx, yy, txtsize, txtsize);
|
||||
if( a > b) {
|
||||
dtmp = a; a = b; b = dtmp;
|
||||
}
|
||||
xline = tx1 + 10;
|
||||
if( ty1 - a > 4.0) drawline(3, NOW, xline, a + 2, xline, ty1 - 2, 1, NULL);
|
||||
if( b - ty2 > 4.0) drawline(3, NOW, xline, ty2 + 2, xline, b - 2, 1, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* sweep variables on x-axis, node labels */
|
||||
|
|
@ -3747,7 +3793,7 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
|
|||
#if 0
|
||||
dbg(0, "draw_graph(): window: %d %d %d %d\n", xctx->areax1, xctx->areay1, xctx->areax2, xctx->areay2);
|
||||
dbg(0, "draw_graph(): graph: %g %g %g %g\n", gr->sx1, gr->sy1, gr->sx2, gr->sy2);
|
||||
dbg(0, "draw_graph(): i = %d, flags = %d\n", i, flags);
|
||||
dbg(0, "draw_graph(): i = %d, flags = %d graph_flags=%d\n", i, flags, xctx->graph_flags);
|
||||
#endif
|
||||
|
||||
/* draw stuff */
|
||||
|
|
@ -4074,12 +4120,12 @@ void draw_graph(int i, const int flags, Graph_ctx *gr, void *ct)
|
|||
if((flags & 4)) draw_cursor(cursor2, cursor1, 3, gr);
|
||||
/* difference between cursors */
|
||||
if((flags & 2) && (flags & 4)) draw_cursor_difference(cursor1, cursor2, gr);
|
||||
/* hcursor1 */
|
||||
if(flags & 128) draw_hcursor(9.012345, 15.0, 15, gr);
|
||||
/* hcursor2 */
|
||||
if(flags & 256) draw_hcursor(15.0, 9.012345, 16, gr);
|
||||
/* difference between hcursors */
|
||||
if((flags & 128) && (flags & 256)) draw_hcursor_difference(9.012345, 15.00, gr);
|
||||
if((flags & 128) && (flags & 256)) draw_hcursor_difference(gr->hcursor1_y, gr->hcursor2_y, gr);
|
||||
/* hcursor1 */
|
||||
if(flags & 128) draw_hcursor(gr->hcursor1_y, 15, gr);
|
||||
/* hcursor2 */
|
||||
if(flags & 256) draw_hcursor(gr->hcursor2_y, 19, gr);
|
||||
}
|
||||
if(flags & 1) { /* copy save buffer to screen */
|
||||
if(!xctx->draw_window) {
|
||||
|
|
@ -4130,8 +4176,10 @@ static void draw_graph_all(int flags)
|
|||
if(xctx->enable_layer[GRIDLAYER]) for(i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
|
||||
xRect *r = &xctx->rect[GRIDLAYER][i];
|
||||
if(r->flags & 1) {
|
||||
int flags2;
|
||||
setup_graph_data(i, 0, &xctx->graph_struct);
|
||||
draw_graph(i, flags, &xctx->graph_struct, NULL); /* draw data in each graph box */
|
||||
flags2 = flags | (xctx->graph_flags & (128 | 256)); /* include drawing hcursors if enabled */
|
||||
draw_graph(i, flags2, &xctx->graph_struct, NULL); /* draw data in each graph box */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -877,14 +877,16 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
|
|||
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
|
||||
if(argc > 2) {
|
||||
int i = atoi(argv[2]);
|
||||
setup_graph_data(i, 0, &xctx->graph_struct);
|
||||
if(argc > 3) {
|
||||
flags = atoi(argv[3]);
|
||||
} else {
|
||||
/* 2: draw cursor 1
|
||||
* 4: draw cursor 2 */
|
||||
flags = 1 + 8 + (xctx->graph_flags & (2 + 4));
|
||||
* 4: draw cursor 2
|
||||
* 128: draw hcursor 1
|
||||
* 256: draw hcursor 2 */
|
||||
flags = 1 + 8 + (xctx->graph_flags & (2 + 4 + 128 + 256));
|
||||
}
|
||||
setup_graph_data(i, 0, &xctx->graph_struct);
|
||||
draw_graph(i, flags, &xctx->graph_struct, NULL);
|
||||
}
|
||||
Tcl_ResetResult(interp);
|
||||
|
|
|
|||
|
|
@ -888,6 +888,7 @@ typedef struct {
|
|||
int logx, logy;
|
||||
int rainbow; /* draw multiple datasets with incrementing colors */
|
||||
double linewidth_mult; /* multiply factor for waveforms line width */
|
||||
double hcursor1_y, hcursor2_y; /* hcursor positions */
|
||||
} Graph_ctx;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
Loading…
Reference in New Issue