void analog_test(void){ joystick_set_new_center(); JOY_pos_t joy_pos; SLI_pos_t sli_pos; while(1){ sli_pos = slider_position(); printf_P(PSTR("Slider position: (Left:%d, Right:%d)\n"), sli_pos.L, sli_pos.R); printf_P(PSTR("Slider buttons: (%s, %s)\n"), (slider_left_button() ? "LEFT" : "Left"), (slider_right_button() ? "RIGHT" : "Right") ); joy_pos = joystick_position(); printf_P(PSTR("pos_x: %4d | pos_y: %4d\n"), joy_pos.x, joy_pos.y); printf_P(PSTR("Joy dirn: %d\n"), joystick_direction()); printf_P(PSTR("Joy button: %d\n\n\n"), joystick_button()); _delay_ms(1000); } }
int Fl_Slider::handle(int event, int x, int y, int w, int h) { switch (event) { case FL_FOCUS: case FL_UNFOCUS: redraw(FL_DAMAGE_ALL); return 1; case FL_PUSH: redraw(FL_DAMAGE_HIGHLIGHT); handle_push(); case FL_DRAG: { // figure out the space the slider moves in and where the event is: int mx; if (horizontal()) { w = w-box()->dw(); mx = Fl::event_x()-x-box()->dx(); } else { w = h-box()->dh(); mx = Fl::event_y()-y-box()->dy(); } if (w <= slider_size_) return 1; static int offcenter; int X = slider_position(value(), w); if (event == FL_PUSH) { offcenter = mx-X; // we are done if they clicked on the slider: if (offcenter >= (slider_size() ? 0 : -8) && offcenter <= slider_size_) return 1; if (Fl::event_button() > 1) { // Move the near end of the slider to the cursor. This is good // for scrollbars. offcenter = (offcenter < 0) ? 0 : slider_size_; } else { // Center the slider under the cursor, what most toolkits do offcenter = slider_size_/2; } } double v; RETRY: X = mx-offcenter; if (X < 0) { X = 0; offcenter = mx; if (offcenter < 0) offcenter = 0; } else if (X > (w-slider_size_)) { X = w-slider_size_; offcenter = mx-X; if (offcenter > slider_size_) offcenter = slider_size_; } v = position_value(X, w); handle_drag(v); // make sure a click outside the sliderbar moves it: if (event == FL_PUSH && value() == previous_value()) { offcenter = slider_size_/2; event = FL_DRAG; goto RETRY; } return 1; } case FL_RELEASE: handle_release(); redraw(FL_DAMAGE_HIGHLIGHT); return 1; case FL_KEY: // Only arrows in the correct direction are used. This allows the // opposite arrows to be used to navigate between a set of parellel // sliders. switch (Fl::event_key()) { case FL_Up: case FL_Down: if (horizontal()) return 0; break; case FL_Left: case FL_Right: if (!horizontal()) return 0; } default: return Fl_Valuator::handle(event); } }
bool Fl_Slider::draw(int ix, int iy, int iw, int ih, Fl_Flags flags, bool slot) { // for back compatability, use type flag to set slider size: if (type()&FILL) slider_size(0); // if user directly set selected_color we use it: if (style()->selection_color) flags.set(FL_SELECTED); // figure out where the slider should be: int sx = ix, sy = iy, sw = iw, sh = ih; int sp; if (horizontal()) { sx = sp = ix+slider_position(value(),iw); sw = slider_size_; if (!sw) // fill slider { sw = sx-ix; sx = ix; } } else { sy = sp = iy+slider_position(value(),ih); sh = slider_size_; if (!sh) sh = iy+ih-sy; // fill slider } if (damage()&FL_DAMAGE_ALL) { fl_push_clip(0, 0, w(), h()); // draw the slider draw_glyph(0, sx, sy, sw, sh, flags); // clip out the area of the slider fl_clip_out(sx, sy, sw, sh); } else if (sp != old_position) { // update a moving slider: // draw slider in new position draw_glyph(0, sx, sy, sw, sh, flags); // clip to the region the old slider was in: if (horizontal()) { if (slider_size_) fl_push_clip(old_position, sy, sw, sh); else fl_push_clip(ix, iy, old_position, ih); } else { if (slider_size_) fl_push_clip(sx, old_position, sw, sh); else fl_push_clip(ix, old_position, iw, iy+ih-old_position); } // don't erase new slider fl_clip_out(sx, sy, sw, sh); } else { // update for the highlight turning on/off if (damage() & FL_DAMAGE_HIGHLIGHT) draw_glyph(0, sx, sy, sw, sh, flags); // otherwise no changes return false; } old_position = sp; // we draw a slot if it seems the box has no border: if (slot) { const int slot_size_ = 6; int slx, sly, slw, slh; int dx = (slider_size_-slot_size_)/2; if (dx < 0) dx = 0; if (horizontal()) { slx = dx; slw = iw-2*dx; slx += ix; sly = iy+(ih-slot_size_+1)/2; slh = slot_size_; } else { sly = dx; slh = ih-2*dx; sly += iy; slx = ix+(iw-slot_size_+1)/2; slw = slot_size_; } button_box()->draw(slx, sly, slw, slh, FL_BLACK, flags&FL_INACTIVE|FL_VALUE); fl_clip_out(slx, sly, slw, slh); } return true; }
// Draw tick marks. These lines cross the passed rectangle perpendicular to // the slider direction. In the direction parallel to the slider direction // the box should have the same size as the area the slider moves in. void Fl_Slider::draw_ticks(int x, int y, int w, int h, int min_spacing) { int x1, y1, x2, y2, dx, dy; if (horizontal()) { x1 = x2 = x+(slider_size_-1)/2; dx = 1; y1 = y; y2 = y + h; dy = 0; } else { x1 = x; x2 = x+w; dx = 0; y1 = y2 = y+(slider_size_-1)/2; dy = 1; w = h; } if (w <= 0) return; double A = minimum(); double B = maximum(); if (A > B) {A = B; B = minimum();} // Figure out approximate size of min_spacing at zero: double derivative; if (!log()) { derivative = (B-A)/w; } else if (A > 0) { // log slider derivative = A/w*20; } else { // squared slider, derivative at edge is zero, use value at 1 pixel derivative = B/(w*w)*30; if (A < 0) derivative *= 4; } // fix for fill sliders if (min_spacing < 1) min_spacing = 10; derivative *= min_spacing; if (derivative < step()) derivative = step(); // Find closest multiple of 10 larger than spacing: int num = 1; while (num < derivative) num *= 10; int denom = 10; while (num >= derivative*denom) denom *= 10; denom /= 10; for (int n = 0; ; n++) { // every ten they get further apart for log slider: if (log() && n > 10) {n = 2; num *= 10;} double v = double(num*n)/denom; if (v > fabs(A) && v > fabs(B)) break; int small = n%5 ? 2 : 0; if (v >= A && v <= B) { int t = slider_position(v, w); fl_line(x1+dx*t+dy*small, y1+dy*t+dx*small, x2+dx*t, y2+dy*t); if (n%10 == 0) { char buffer[20]; sprintf(buffer,"%g",v); char* p = buffer; while (p[0]=='0' && p[1]) p++; fl_font(text_font(), text_size()); fl_draw(p, x1+dx*t+1, y1+dy*t+fl_size()-fl_descent()); } } if (v && -v >= A && -v <= B) { int t = slider_position(-v, w); fl_line(x1+dx*t+dy*small, y1+dy*t+dx*small, x2+dx*t, y2+dy*t); if (n%10 == 0) { char buffer[20]; sprintf(buffer+1,"%g",v); char* p = buffer+1; while (p[0]=='0' && p[1]) p++; p--; p[0] = '-'; fl_font(text_font(), text_size()); fl_draw(p, x1+dx*t+1, y1+dy*t+fl_size()-fl_descent()); } } } }
int Fl_Scrollbar::handle(int event) { // area of scrollbar: int X=0; int Y=0; int W=w(); int H=h(); box()->inset(X,Y,W,H); // adjust slider area to be inside the arrow buttons: if (vertical()) { if (H >= 3*W) {Y += W; H -= 2*W;} } else { if (W >= 3*H) {X += H; W -= 2*H;} } // which widget part is highlighted? int mx = Fl::event_x(); int my = Fl::event_y(); int which_part; if (!Fl::event_inside(0, 0, w(), h())) which_part = NOTHING; else if (vertical()) { if (my < Y) which_part = UP_ARROW; else if (my >= Y+H) which_part = DOWN_ARROW; else { int slidery = slider_position(value(), H); if (my < Y+slidery) which_part = ABOVE_SLIDER; else if (my >= Y+slidery+slider_size()) which_part = BELOW_SLIDER; else which_part = SLIDER; } } // horizontal else { if (mx < X) which_part = UP_ARROW; else if (mx >= X+W) which_part = DOWN_ARROW; else { int sliderx = slider_position(value(), W); if (mx < X+sliderx) which_part = ABOVE_SLIDER; else if (mx >= X+sliderx+slider_size()) which_part = BELOW_SLIDER; else which_part = SLIDER; } } switch (event) { case FL_FOCUS: return 0; case FL_ENTER: case FL_MOVE: if (!highlight_color()) return 1; if (which_part != which_highlight) { which_highlight = which_part; redraw(FL_DAMAGE_HIGHLIGHT); } return 1; case FL_LEAVE: if (which_highlight) { which_highlight = 0; redraw(FL_DAMAGE_HIGHLIGHT); } return 1; case FL_PUSH: // Clicking on the slider or middle or right click on the trough // gives us normal slider behavior: if (which_part == SLIDER || Fl::event_button() > 1 && which_part > DOWN_ARROW) { which_pushed = SLIDER; return Fl_Slider::handle(event, X,Y,W,H); } handle_push(); goto J1; case FL_DRAG: if (which_pushed==SLIDER) return Fl_Slider::handle(event, X,Y,W,H); if (which_part == SLIDER) which_part = NOTHING; // it is okay to switch between arrows and nothing, but no other // changes are allowed: if (!which_pushed && which_part <= DOWN_ARROW) ; else if (!which_part && which_pushed <= DOWN_ARROW) ; else which_part = which_pushed; J1: if (which_part != which_pushed) { Fl::remove_timeout(timeout_cb, this); which_highlight = which_pushed = which_part; redraw(FL_DAMAGE_HIGHLIGHT); if (which_part) { Fl::add_timeout(INITIALREPEAT, timeout_cb, this); increment_cb(); } } return 1; case FL_RELEASE: if (which_pushed == SLIDER) { Fl_Slider::handle(event, X,Y,W,H); } else if (which_pushed) { Fl::remove_timeout(timeout_cb, this); handle_release(); redraw(FL_DAMAGE_HIGHLIGHT); } which_pushed = NOTHING; return 1; case FL_MOUSEWHEEL: { float n = (vertical() ? Fl::event_dy() : Fl::event_dx()) * Fl_Style::wheel_scroll_lines * linesize(); if (fabsf(n) > pagesize()) n = (n<0)?-pagesize():pagesize(); handle_drag(value()+n); return 1; } case FL_KEY: if (vertical()) switch(Fl::event_key()) { case FL_Home: handle_drag(maximum()); return 1; case FL_End: handle_drag(minimum()); return 1; case FL_Page_Up: handle_drag(value()-pagesize()); return 1; case FL_Page_Down: handle_drag(value()+pagesize()); return 1; } // else fall through... default: return Fl_Slider::handle(event); } }