[FLTK 1.3.5] Making a draggable item

35 views
Skip to first unread message

Catalin Poida

unread,
Sep 10, 2020, 5:35:39 AM9/10/20
to fltk.general

Hi,
I want to make an item draggable between windows.
What I am trying to make is to be able to click&drag an item from one window/TL_Window to another.

So far, I could only think about creating a window with shape and the image of the item and pass the event to it when the item is clicked.
But still encountered a few problems:
 - using an png image with transparent background, how can apply the shape accordingly?
 - cannot pass correctly the event of PUSH and DRAG. If I scale the  draggable  item to 100x100 it works, but if I scale it to 40x40,  it doesn't work (need an additional click on the draggable item). I am wondering if I did something wrong or I forgot something


Was there an easier solution for creating a draggable item between windows? If not, are there any easy solutions to those problems?

Thank you,
Catatlin

Catalin Poida

unread,
Sep 10, 2020, 5:43:27 AM9/10/20
to fltk.general
Regarding how I passed the event:

'''''''''''''''''''''''''
int QuickAccessItem::handle(int event) {

    if (event == FL_PUSH) {
        startDragging_ = true;
        DraggableItem::instance()->position(window()->x_root() + x(), window()->y_root() + y());
        DraggableItem::instance()->setImage(imagePath_);
        DraggableItem::instance()->handle(FL_PUSH);
        DraggableItem::instance()->show();

        // we need to return used in order to display the window above the current
        // otherwise it will display it under
        return 1;
    }

    if (startDragging_) {
        // now pass the the handle and declare that it is not our business anymore
        startDragging_ = false;
        DraggableItem::instance()->handle(event);
        return 0;
    }

    return Fl_Box::handle(event);
}
'''''''''''''''''''''

Manolo

unread,
Sep 10, 2020, 9:35:54 AM9/10/20
to fltk.general
Use Fl_Window::shape(const Fl_Image*) to set the shape of your window.
If you use a PNG image, the doc of that function indicates:
"With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part that is not fully transparent."
Thus, fully transparent parts of the png will be out of the window's shape.
Please, notice that if you use FLTK 1.3.5 you'll have to set your ABI level to 1.3.3 or above.

Also, I would have put the creation of the shaped window when the donor widget receives the FL_DRAG
event rather than FL_PUSH.

Class Fl_Image_Surface can be useful to create the image of the shaped window because it can
produce an image from a widget and its visual display.


Catalin Poida

unread,
Sep 11, 2020, 6:10:18 PM9/11/20
to fltk.general
Hi Manolo,
Thank you for your suggestions.

I've managed to fix the problem regarding passing the event to the window. I've tried with FL_DRAG and other methods, but something was not right with what I've did. But in the end I've managed to make it work.

I've saw the shapewindow example, so it went easy the first part. The problem is that, as far as I understood, I need to draw with WHITE the shape of the image while setting the shape. But I cannot find how I can edit the image to convert the transparent part to white and the rest in black. Any ideas on this?
I do not understand:
"""
"With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part that is not fully transparent."
Thus, fully transparent parts of the png will be out of the window's shape.
""""
I think I understand the logic, but I can't get it right. I have something like (similar to shapewindow example) :

==================================
    auto *surf = new Fl_Image_Surface(w, h);
    Fl_Surface_Device* current = Fl_Surface_Device::surface();
    surf->set_current();
//    fl_color(FL_BLACK);
//    fl_rectf(-1, -1, w+2, h+2);
//    fl_color(FL_WHITE);
//    fl_pie(2,2,w-4,h-4,0,360);
    auto *img = new Fl_PNG_Image("item.png");
    auto *imgV2 = new Fl_RGB_Image(new Fl_Pixmap(img->copy(w, h)->data()), FL_BLACK);
    imgV2->draw(0,0);

    Fl_Window::shape(surf->image());
    delete surf;
    current->set_current();
    add(dragBox_);
    Fl_Group::end();
    Fl_Window::resizable();
==================================
The image still gets distorted and the shape is not right. What am I doing wrong? From what I understood, I need to draw with black the hole window to hide it, and the draw with white the shape I want to display.

Any ideas?

Manolo

unread,
Sep 13, 2020, 1:47:16 PM9/13/20
to fltk.general
If you use Fl_Image_Surface to prepare the shape of your window, you'll obtain a depth 3 a.k.a. RGB
image with member function Fl_Image_Surface::image().
Thus the rule you have to follow is :
   With an Fl_RGB_Image of depth 1 (gray-scale) or 3 (RGB), the shaped window covers the non-black image part.
In other words, every non black pixel in the resulting image is inside the shape, every black pixel is outside the shape.
Consider, please, examples/shapedwindow.cxx which obeys this rule.

If you use something producing an image with transparency, e.g., pixmap or PNG, to control the
shape of the window, then you have to consider that rule:
   With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part that is not fully transparent.
There, the fully transparent area of the image is outside the window shape, and everything else is inside.

FLTK uses an RGB color model when drawing (except when drawing depth-4 or depth-2 images). That's why the result
of Fl_Image_Surface::image() is an RGB, not an RGBA, image.

Manolo

unread,
Sep 13, 2020, 1:50:37 PM9/13/20
to fltk.general
And also, don't forget that non-rectangular windows require compilation of the FLTK library
with FLTK_ABI_VERSION >= 10303
Without this, all your efforts will produce no effect.

The better choice in my view is: use FLTK 1.4


Catalin Poida

unread,
Sep 13, 2020, 6:11:57 PM9/13/20
to fltk.general
Hi Manolo,

Many thanks for the info. It helped solve the problem.
Reply all
Reply to author
Forward
0 new messages