Dragging an fl_arc into position

I have modified some code from the internet:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//fltk-config --compile freedraw3.cpp
#include <FL/Fl.h>
#include <Fl/Fl_Window.h>
#include "FL/Fl_Double_Window.H"
#include <Fl/fl_draw.h>

bool dragsbool = true;
bool dragged = false;
int xnote;
int ynote;
int xold;
int yold;

struct point {
    point(){
        x=0;
        y=0;
    }
    int x;
    int y;
};

class DrawX : public Fl_Widget {
public:
    DrawX(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) {
    }
    void draw() {
    }
};

class canvas : public Fl_Window {
public: canvas(int x,int y,int w,int h,const char *lab=0) : Fl_Window(x,y,w,h,lab){
    index=0;
    end();
}
    
    int handle(int event){
        if(event==FL_PUSH){
            return 1;
        }
        if(event==FL_DRAG){
            points[index].x=Fl::event_x();
            points[index].y=Fl::event_y();
            if(dragsbool == true){
            dragged = true;
            index = 0;
            redraw();
            }
            if(dragsbool == false){
            dragged = true;
            index = 10;
            redraw();
            }
            dragsbool = false;
        }//drag
    }//handle
    
    void draw(void){
        Fl_Window::draw();
        fl_color(FL_BLACK);
        int x1 = 0,       y1 = 12;
        int x2 = w(), y2 = 12;
        fl_line(x1, y1, x2, y2);
        //fl_line(x1, y2, x2, y1);
        if(dragged == false){
            xnote = 150;
            ynote = 150;
            xold = 150;
            yold = 150;
        } else {
            xnote = xold;
            ynote = yold;
            int w = 15;
            int h = 10;
            double a1 = 0;
            double a2 = 360;
            if(index == 10){
                int xnote = points[0].x;
                int ynote = points[0].y;
                if((xnote < 5 && ynote < 9) ||
                   (xnote < 5 && ynote > 12) ||
                   (xnote > 20 && ynote < 9) ||
                   (xnote > 20 && ynote > 12)) {
                    fl_arc(xnote, ynote, w, h, a1, a2);
                    dragsbool = true;
                    xold = xnote;
                    yold = ynote;
                }
                else {
                    fl_arc(xold, yold, w, h, a1, a2);
                    dragsbool = true;
                }
            }
            if(index == 0){
                fl_arc(xold, yold, w, h, a1, a2);
                dragsbool = false;
            }
        }
    }//draw
    
    int index;
    point points[100];
};

int main(void){
    canvas c(0,0,300,300);
    DrawX draw_x(0, 0, c.w(), c.h());//
    c.resizable(draw_x);//
    c.show();
    return Fl::run();
}


When dragging the fl_arc, the program is showing its old position until one of the four if-clauses are met (when the mouse points in these areas while dragging). Then the fl_arc is moved into the new position.
My question: how to make the if-clauses handle multiple old and new positions while dragging? For example 5 positions in x-direction without adding more if-clauses.
Last edited on
I am not sure what you are asking in your question. Could you elaborate some more?
One thing I notice is that the ifs from 44-67 all have the same body. You could combine the conditions with ors and have just one if. Like this:
1
2
3
4
5
6
7
8
9
                if((xnote < 5 && ynote < 9) ||
                   (xnote < 5 && ynote > 12) || 
                   (xnote > 20 && ynote < 9) || 
                   (xnote > 20 && ynote > 12)) {
                    fl_arc(xnote, ynote, w, h, a1, a2);
                    dragsbool = true;
                    xold = xnote;
                    yold = ynote;
                }
I have posted the full code of the program above. When you compile and run the program, you will get an draggable ellipse in the canvas when dragging. Near the horizontal line, the canvas has a special behavior: there is only dragging possible under the line, or from half on the line. This is the behavior I wish. Now the question is: how to add more of these areas in which the ellipse is only allowed on specific places?
Imagine you have score-notation and the ellipse is a musical note. Now there are 5 lines underneath each other. The notes can only be drawn between these lines or on the middle of a line. Can you help me with making the if-clause more intelligent, so it has the requested behavior?
Okay I just spent two hours compiling your code. Turns out on my archlinux machine I already had fltk libraries installed. I have never built an app using fltk before, so it took me a while to realize how the library header files had crazy capitalization. Which on the linux machine I am using made it hard to compile them. Anyway I managed to compile it.
I would just add more if conditions. I will try to make an example.
Here is the example I promised:
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
    void draw(void){
        Fl_Window::draw();
        fl_color(FL_BLACK);
        int x1 = 0,       y1 = 12;
        int x2 = w(), y2 = 12;
        fl_line(x1, y1, x2, y2);
        fl_line(x1, 23, x2, 23);
        if(dragged == false){
            xnote = 150;
            ynote = 150;
        } else {
            int w = 15;
            int h = 10;
            double a1 = 0;
            double a2 = 360;
            if(index == 10){
                int xnote = points[0].x;
                int ynote = points[0].y;
                if(ynote < 9 || ynote > 80) {
                    fl_arc(xnote, ynote, w, h, a1, a2);
                }
                else {
                    fl_arc(xnote, (ynote)/15 * 15+13, w, h, a1, a2);
                }
                dragsbool = true;
            }
            else if(index == 0){
                //fl_arc(xnote, ynote, w, h, a1, a2);
                dragsbool = false;
            }
        }
    }//draw 

So the trick is while in a certain y region to 'snap' to smaller areas. Integer division is a good little trick to force certain sequences of numbers to be smaller. Or in other words to chop up the number line into equal sections. Think of it as a staircase type of equation.
Last edited on
Topic archived. No new replies allowed.