|
Post by vovchik on Jan 1, 2018 12:10:12 GMT 1
Dear Joe, Thanks for that template. Here is the same thing, but I added a taskbar icon and a button image. Looks pretty good and is simple to use. With kind regards, vovchik
|
|
|
Post by bigbass on Jan 1, 2018 19:40:00 GMT 1
Hey vovchik I really like where you took the simple event demo a polished demo and that is what you do best I really enjoy how you added three important parts of code 1.) The SVG and embedding the images 2.) How to add cairo The artist touch of combining together everything and still keeping the code reduced for a working demo snippet before it is put in a more complex working complete game maybe rename the demo better vov-cairo-svg.bac I am happy with just my small part of getting those classes working Joe clever the way you got that working very creative P.S but_a.image(IMAGE_RGB(RSVG2BUF(card$), dim.width, dim.height, depth)) I see how you will be able to resize also with this idea win->icon(IMAGE_RGB(RSVG2BUF(REPLACE$(but_svg$, \ "X_COLOR", "darkorange")), dim.width, dim.height, depth)) if you switch the order in the header from this card$ = "<svg width='71' height='96' viewBox='0 0 71 96' " \ " preserveAspectRatio='none'> " \ "<image x='0' y='0' width='71' height='96' " \
to this it would be easier to put the header in an array and easier to replace values later look at what values would change if it was an template array card$ = "<svg width='71' height='96' viewBox='0 0 71 96' " \ "<image x='0' y='0' width='71' height='96' " \ " preserveAspectRatio='none'> " \
just the 71 ,96 change so a snippet that writes the header then adds the image code to make it possible to resize images like a zoom factor
|
|
|
Post by vovchik on Jan 1, 2018 21:51:15 GMT 1
Dear Joe,
The header order here doesn't really apply to the entire SVG, since the only operative numbers that we want to change here are the first instances of "width='' and height=''. If the dimensions within the base64 bit are changed, we will get rubbish, and the same holds for the viewBox, particularly with embedded bitmaps. So we should search for "<svg width='xx' height='xx'" in order to change dimensions and leave the other numbers as they are. And you are right, this is be the most elegant way to rescale SVGs. With normal bitmaps (jpg, png, bmp, gif),
DEF FN IMG_RGB_SCALE(w, x, y) = w->copy(x, y)
we can let FLTK do the scaling for us. There are some constants we can use to determine how the rescaling is done (i.e. quality), but I have to look those up.
With kind regards, vovchik
|
|
|
Post by bigbass on Jan 10, 2018 17:27:52 GMT 1
just a simple demo using buttons as children we could shuffle through images as buttons modified the simple-wizard and added the callbacks found an odd problem with the syntax won't compile with the pointer attached to Fl_Widget* SUB back_cb(Fl_Widget* , void* ) but if I place a space between them all is fine Fl_Widget * SUB back_cb(Fl_Widget * , void* ) it compiles in c++ fine PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Window.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <FL/Fl_Wizard.H> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
'---Simple 'wizard' using fltk's new Fl_Wizard widget '--- modified to use buttons as children and have callbacks
DECLARE G_win TYPE Fl_Window* DECLARE G_wiz TYPE Fl_Wizard*
'=============================== SUB back_cb(Fl_Widget * , void* ) '=============================== G_wiz->prev() END SUB
'=============================== SUB next_cb(Fl_Widget * , void* ) '=============================== G_wiz->next() END SUB
'=============================== SUB done_cb(Fl_Widget * , void* ) '=============================== exit(0) END SUB
'=============================== SUB but1_cb(Fl_Widget * , void* ) '=============================== PRINT "but1:" END SUB
'=============================== SUB but2_cb(Fl_Widget * , void* ) '=============================== PRINT "but2:" END SUB
'=============================== SUB but3_cb(Fl_Widget * , void* ) '=============================== PRINT "but3:" END SUB
DECLARE GROUP TYPE Fl_Group*
DECLARE next TYPE Fl_Button* DECLARE done TYPE Fl_Button* DECLARE back TYPE Fl_Button*
DECLARE B1 TYPE Fl_Button* DECLARE B2 TYPE Fl_Button* DECLARE B3 TYPE Fl_Button*
G_win = new Fl_Window(400,300,"Example Wizard2") G_wiz = new Fl_Wizard(0,0,400,300)
'--- Wizard: page 1 GROUP = new Fl_Group(0,0,400,300) next = new Fl_Button(290,265,100,25,"Next @->") next->callback(next_cb) B1 = new Fl_Button(10,30,400-20,300-80," button card 1") B1->callback(but1_cb) B1->color(FL_BLUE) B1->labelsize(20) B1->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B1->value(1) GROUP->end() '--- Wizard: page 2 GROUP = new Fl_Group(0,0,400,300) next = new Fl_Button(290,265,100,25,"Next @->") next->callback(next_cb) back = new Fl_Button(180,265,100,25,"@<- Back") back->callback(back_cb) B2 = new Fl_Button(10,30,400-20,300-80," button card 2") B2->callback(but2_cb) B2->color(FL_GREEN) B2->labelsize(20) B2->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B2->value(2) GROUP->end() '--- Wizard: page 3 GROUP = new Fl_Group(0,0,400,300) done = new Fl_Button(290,265,100,25,"Finish") done->callback(done_cb) back = new Fl_Button(180,265,100,25,"@<- Back") back->callback(back_cb) B3 = new Fl_Button(10,30,400-20,300-80," button card 3") B3->callback(but3_cb) B3->color(FL_YELLOW) B3->labelsize(20) B3->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B3->value(3) GROUP->end() G_wiz->end() G_win->end() G_win->show(argc, argv) Fl::run()
|
|
|
Post by bigbass on Jan 12, 2018 7:09:22 GMT 1
drag n drop ported from official demo so that we have the minimum widget Things get complex quickly when adding special events tried to stay simple for the sake of just focusing on the demo code port '--- ported draggable-group.cxx from offical demo to BaCon by bigbass '--- and converted code to use the arrow operator -> '--- and a little eye candy theme
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Box.H> PRAGMA INCLUDE <stdio.h> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS }
USECPLUS
/** \class DraggableGroup \brief Class with draggable children, derived from Fl_Group.
Use this class if you want the user to be able to drag the children of a group inside the borders of the group. DraggableGroup widgets can be nested, but only direct children of the DraggableGroup widget can be dragged.
Design decisions: - Widgets can be dragged with the right mouse button. This was chosen to avoid conflicts with other mouse button events such as clicking a button. - The dragged widget is raised to the top within its group for better visual feedback while dragging by making it the last child of the group. - The order of widgets is restored when the mouse button is released. This can result in hiding the widget behind another widget, but this was chosen to keep the order given by the programmer. If this is not desired it can be changed easily. */ class DraggableGroup : public Fl_Group {
protected: int xoff, yoff; // start offsets while dragging int drag_index; // index of dragged child Fl_Widget *drag_widget; // dragged child widget
public: DraggableGroup(int X, int Y, int W, int H, const char *L = 0) : Fl_Group(X, Y, W, H, L) , xoff(0) , yoff(0) , drag_index(0) , drag_widget(0) { box(FL_UP_BOX); }
/** Raise the dragged widget to the top (last child) of its group.
This ensures that the widget is always visible while it is dragged. The original index is saved in 'drag_index' and restored when the mouse button is released.
\internal Since we allow only direct children of the DraggableGroup widget to be dragged the argument 'q' is always a child of 'this'. Note: add(q) first removes the widget from its parent group ('this') and then adds it again as its last child. This is the same as insert(*q, children()). */ void top_level(Fl_Widget *q) { drag_index = find(q); // save the widget's current index add(q); // raise to top (make it the last child) }
/** Handle FL_PUSH, FL_DRAG, and FL_RELEASE events.
All other events are handled in Fl_Group::handle(). Dragged widgets are limited inside the borders of their parent group. */ virtual int handle(int e) {
switch (e) {
case FL_PUSH: { if (Fl::event_button() == FL_RIGHT_MOUSE) { if (Fl::belowmouse()->parent() == this) { drag_widget = Fl::belowmouse();
// save pointer offsets relative to drag_widget's x/y position xoff = Fl::event_x() - drag_widget->x(); yoff = Fl::event_y() - drag_widget->y();
top_level(drag_widget); // raise to top for visible feedback redraw(); return 1; } } break; }
case FL_DRAG: { if (!drag_widget) break;
int nX = Fl::event_x() - xoff; // new x coordinate int nY = Fl::event_y() - yoff; // new y coordinate
int bbx = Fl::box_dx(box()); // left and right border width int bby = Fl::box_dy(box()); // top and bottom border width
// keep the widget inside its parent's borders
if (nX < x() + bbx) { nX = x() + bbx; } else if (nX + drag_widget->w() > x() + w() - bbx) { nX = x() + w() - drag_widget->w() - bbx; }
if (nY < y() + bby) { nY = y() + bby; } else if (nY + drag_widget->h() > y() + h() - bby) { nY = y() + h() - drag_widget->h() - bby; }
drag_widget->position(nX, nY); // set the new position redraw(); return 1; }
case FL_RELEASE: { if (drag_widget && Fl::event_button() == FL_RIGHT_MOUSE) {
// Optional: restore the original widget order in the group. // Remove the next statement (or comment it out) if not desired. insert(*drag_widget, drag_index);
init_sizes(); // save widget positions for later resizing drag_widget = 0; redraw(); if (parent()) parent()->redraw(); return 1; } break; }
default: break; } // switch(e)
return Fl_Group::handle(e); } };
ENDCPLUS END USEH
'--- tooltips:
DECLARE tt_drag TYPE char* DECLARE tt_group TYPE char* DECLARE tt_button TYPE char*
tt_drag = "Drag this DraggableGroup and/or its child groups and squares. " \ "Use the right mouse button (MB3) to drag objects."
tt_group = "You can drag this Fl_Group, but not its children (squares)."
tt_button = "You can drag this button with the right mouse button " \ "and you can click it with the left mouse button."
DECLARE win TYPE Fl_Double_Window* DECLARE area TYPE DraggableGroup* DECLARE b1 TYPE Fl_Box* DECLARE b2 TYPE Fl_Box* DECLARE dobj TYPE Fl_Group* DECLARE dobj2 TYPE Fl_Group* DECLARE dobj3 TYPE Fl_Group* DECLARE dobj4 TYPE Fl_Group* DECLARE b3 TYPE Fl_Box* DECLARE b4 TYPE Fl_Box* DECLARE b5 TYPE Fl_Box* DECLARE b6 TYPE Fl_Box* DECLARE button1 TYPE Fl_Button* DECLARE button2 TYPE Fl_Button* 'DECLARE status TYPE Fl_Box*
win = new Fl_Double_Window (500, 500, "Drag children within their parent group") win->box(FL_GLEAM_ROUND_DOWN_BOX)
area = new DraggableGroup(0, 0, 500, 400, "Use the right mouse button (MB3)\nto drag objects") area->box(FL_GLEAM_UP_BOX)
area->align(FL_ALIGN_INSIDE) area->tooltip(tt_drag)
'-- draggable group inside draggable area dobj= new DraggableGroup(5, 5, 140, 140, "DraggableGroup") dobj->align(FL_ALIGN_INSIDE) dobj->box(FL_GLEAM_ROUND_DOWN_BOX)
b1 = new Fl_Box(25, 25, 20, 20) b1->box(FL_GLEAM_ROUND_DOWN_BOX)
b1->color(FL_RED)
b2 = new Fl_Box(105, 105, 20, 20) b2->box(FL_GLEAM_ROUND_DOWN_BOX)
b2->color(FL_GREEN) dobj->end() dobj->tooltip(tt_drag)
'--- regular group inside draggable area dobj2 = new Fl_Group(5, 280, 110, 110, "Fl_Group") dobj2->box(FL_GLEAM_ROUND_DOWN_BOX) dobj2->align(FL_ALIGN_INSIDE) b3 = new Fl_Box(15, 290, 20, 20) b3->box(FL_GLEAM_ROUND_DOWN_BOX)
b3->color(FL_BLUE) b4 = new Fl_Box(85, 360, 20, 20) b4->box(FL_GLEAM_ROUND_DOWN_BOX) b4->color(FL_YELLOW) dobj2->end() dobj2->tooltip(tt_group)
'--- draggable group inside draggable area dobj3 = new DraggableGroup(245, 5, 150, 150, "DraggableGroup") dobj3->box(FL_GLEAM_ROUND_DOWN_BOX) dobj3->align(FL_ALIGN_INSIDE) dobj3->tooltip(tt_drag)
'--- nested draggable group dobj4 = new DraggableGroup (250, 10, 50, 50) dobj4->box(FL_GLEAM_ROUND_DOWN_BOX)
b5 = new Fl_Box(255, 15, 15, 15) b5->box(FL_GLEAM_ROUND_DOWN_BOX)
b5->color(FL_BLACK) b6 = new Fl_Box(275, 30, 15, 15) b6->box(FL_GLEAM_ROUND_DOWN_BOX) b6->color(FL_WHITE) dobj4->end() dobj4->tooltip(tt_drag)
dobj3->end()
button1 = new Fl_Button(200, 350, 180, 40, "Fl_Button inside DraggableGroup") button1->box(FL_GLEAM_ROUND_DOWN_BOX) button1->align(FL_ALIGN_INSIDE | FL_ALIGN_WRAP) button1->tooltip(tt_button)
area->end()
button2 = new Fl_Button(200, 410, 180, 40, "Fl_Button outside DraggableGroup") button2->box(FL_GLEAM_ROUND_DOWN_BOX)
button2->align(FL_ALIGN_INSIDE | FL_ALIGN_WRAP) button2->tooltip("This is a normal button and can't be dragged.") status = new Fl_Box(0, 460, win->w(), 40, "Messages ...") 'status->box(FL_GLEAM_DOWN_BOX) win->end() win->resizable(win) win->show()
Fl::run()
|
|
|
Post by bigbass on Jan 12, 2018 16:48:28 GMT 1
This is how to easily add drag n drop to any of your widget demos I used the wizard demo before and added Fl_Button instead of the Fl_Multiline_Output here are the original source files that were used from the latest dev version the latest fltk demos are not online yet as single files so I uploaded the needed files sourceforge.net/p/baconproto/wiki/fltk-draggable-group/sourceforge.net/p/baconproto/wiki/fltk-wizard/The wizard is a simplified tabs widget this way it is easier to understand the code with less extra clutter to get in your face and sort out Alex pointed out a link to the documentation to the composite widget this is the same Idea but using the wizards groups to make the composite and a lot easier to adapt the code when you already use this idea to make every class in fltk right mouse button starts the move left mouse button gets the callback event BTW before I shoe horned struct to make the c++ class public and get the code to communicate between fltk class and bacon c++ classes are too complex when they have functions inside the class to back port to a RECORD and fltk chose to use c++ and we have to adapt to another way of thinking and take advantage of the simplified way c++ does things and Bacon understands how to handle the struct but it doesn't handle the syntax "class" in the user area thats why the USECPLUS /USEC is needed The code below uses the original fltk class embedded and struct is not needed with this approach PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Window.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <FL/Fl_Wizard.H> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
'***********************************************************************
USEH #define USECPLUS extern "C" { #define ENDCPLUS }
USECPLUS
class DraggableGroup : public Fl_Group {
protected: int xoff, yoff; // start offsets while dragging int drag_index; // index of dragged child Fl_Widget *drag_widget; // dragged child widget
public: DraggableGroup(int X, int Y, int W, int H, const char *L = 0) : Fl_Group(X, Y, W, H, L) , xoff(0) , yoff(0) , drag_index(0) , drag_widget(0) { box(FL_UP_BOX); }
void top_level(Fl_Widget *q) { drag_index = find(q); // save the widget's current index add(q); // raise to top (make it the last child) }
/** Handle FL_PUSH, FL_DRAG, and FL_RELEASE events.
All other events are handled in Fl_Group::handle(). Dragged widgets are limited inside the borders of their parent group. */ virtual int handle(int e) {
switch (e) {
case FL_PUSH: { if (Fl::event_button() == FL_RIGHT_MOUSE) { if (Fl::belowmouse()->parent() == this) { drag_widget = Fl::belowmouse();
// save pointer offsets relative to drag_widget's x/y position xoff = Fl::event_x() - drag_widget->x(); yoff = Fl::event_y() - drag_widget->y();
top_level(drag_widget); // raise to top for visible feedback redraw(); return 1; } } break; }
case FL_DRAG: { if (!drag_widget) break;
int nX = Fl::event_x() - xoff; // new x coordinate int nY = Fl::event_y() - yoff; // new y coordinate
int bbx = Fl::box_dx(box()); // left and right border width int bby = Fl::box_dy(box()); // top and bottom border width
// keep the widget inside its parent's borders
if (nX < x() + bbx) { nX = x() + bbx; } else if (nX + drag_widget->w() > x() + w() - bbx) { nX = x() + w() - drag_widget->w() - bbx; }
if (nY < y() + bby) { nY = y() + bby; } else if (nY + drag_widget->h() > y() + h() - bby) { nY = y() + h() - drag_widget->h() - bby; }
drag_widget->position(nX, nY); // set the new position redraw(); return 1; }
case FL_RELEASE: { if (drag_widget && Fl::event_button() == FL_RIGHT_MOUSE) {
// Optional: restore the original widget order in the group. // Remove the next statement (or comment it out) if not desired. insert(*drag_widget, drag_index);
init_sizes(); // save widget positions for later resizing drag_widget = 0; redraw(); if (parent()) parent()->redraw(); return 1; } break; }
default: break; } // switch(e)
return Fl_Group::handle(e); } };
ENDCPLUS END USEH '***********************************************************************
'---Simple 'wizard' using fltk's new Fl_Wizard widget '--- modified to use buttons as children and have callbacks
DECLARE G_win TYPE Fl_Window* DECLARE G_wiz TYPE Fl_Wizard*
'=============================== SUB back_cb(Fl_Widget * , void* ) '=============================== G_wiz->prev() END SUB
'=============================== SUB next_cb(Fl_Widget * , void* ) '=============================== G_wiz->next() END SUB
'=============================== SUB done_cb(Fl_Widget * , void* ) '=============================== exit(0) END SUB
'=============================== SUB but1_cb(Fl_Widget * , void* ) '=============================== PRINT "but1:" END SUB
'=============================== SUB but2_cb(Fl_Widget * , void* ) '=============================== PRINT "but2:" END SUB
'=============================== SUB but3_cb(Fl_Widget * , void* ) '=============================== PRINT "but3:" END SUB
DECLARE GROUP TYPE Fl_Group*
DECLARE next TYPE Fl_Button* DECLARE done TYPE Fl_Button* DECLARE back TYPE Fl_Button*
DECLARE B1 TYPE Fl_Button* DECLARE B2 TYPE Fl_Button* DECLARE B3 TYPE Fl_Button*
'DECLARE GROUP TYPE DraggableGroup*
G_win = new Fl_Window(400,300,"Example Wizard2") G_wiz = new Fl_Wizard(0,0,400,300)
'--- Wizard: page 1 '---the draggable main area is set here but called GROUP GROUP = new DraggableGroup(0,0,400,300) next = new Fl_Button(290,265,100,25,"Next @->") next->callback(next_cb) '-- draggable Button inside draggable area B1 = new Fl_Button(10,30,400-200,300-180," button card 1") B1->callback(but1_cb) B1->color(FL_BLUE) B1->labelsize(20) B1->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B1->value(1) GROUP->end() '--- Wizard: page 2 GROUP = new DraggableGroup(0,0,400,300) next = new Fl_Button(290,265,100,25,"Next @->") next->callback(next_cb) back = new Fl_Button(180,265,100,25,"@<- Back") back->callback(back_cb) B2 = new Fl_Button(10,30,400-200,300-180," button card 2") B2->callback(but2_cb) B2->color(FL_GREEN) B2->labelsize(20) B2->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B2->value(2) GROUP->end() '--- Wizard: page 3 GROUP = new DraggableGroup(0,0,400,300) done = new Fl_Button(290,265,100,25,"Finish") done->callback(done_cb) back = new Fl_Button(180,265,100,25,"@<- Back") back->callback(back_cb) B3 = new Fl_Button(10,30,400-200,300-180," button card 3") B3->callback(but3_cb) B3->color(FL_YELLOW) B3->labelsize(20) B3->align(FL_ALIGN_TOP|FL_ALIGN_LEFT) B3->value(3) GROUP->end() G_wiz->end() G_win->end() G_win->show(argc, argv) Fl::run()
|
|
|
Post by bigbass on Jan 13, 2018 19:49:48 GMT 1
here is drag n drop simplified how to get the color in the USEC part of the code drag_widget->color(FL_YELLOW); drag_widget->label("RIGHT BUT");
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Box.H> PRAGMA INCLUDE <FL/names.h> PRAGMA INCLUDE <FL/Enumerations.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <stdio.h> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
'===================================== SUB but_a_cb(Fl_Widget* w, void* p) '=====================================
IF Fl::event_button( ) == 1 THEN w->color(FL_RED) w->label("LEFT BUT") PRINT " The LEFT mouse button "
ELIF Fl::event_button( ) == 2 THEN w->color(FL_GREEN) w->label("MID BUT") PRINT " The MIDDLE mouse button"
ELIF Fl::event_button( ) == 3 THEN 'w->color(FL_YELLOW) 'w->label("RIGHT BUT") PRINT " The RIGHT mouse button"
ENDIF END SUB
USEH #define USECPLUS extern "C" { #define ENDCPLUS }
USECPLUS
class DraggableGroup : public Fl_Group {
protected: int xoff, yoff; // start offsets while dragging int drag_index; // index of dragged child Fl_Widget *drag_widget; // dragged child widget
public: DraggableGroup(int X, int Y, int W, int H, const char *L = 0) : Fl_Group(X, Y, W, H, L) , xoff(0) , yoff(0) , drag_index(0) , drag_widget(0) { box(FL_UP_BOX); }
void top_level(Fl_Widget *q) { drag_index = find(q); // save the widget's current index add(q); // raise to top (make it the last child) }
/** Handle FL_PUSH, FL_DRAG, and FL_RELEASE events.
All other events are handled in Fl_Group::handle(). Dragged widgets are limited inside the borders of their parent group. */ virtual int handle(int e) {
switch (e) {
case FL_PUSH: { if (Fl::event_button() == FL_RIGHT_MOUSE) { if (Fl::belowmouse()->parent() == this) { drag_widget = Fl::belowmouse();
// save pointer offsets relative to drag_widget's x/y position xoff = Fl::event_x() - drag_widget->x(); yoff = Fl::event_y() - drag_widget->y();
top_level(drag_widget); // raise to top for visible feedback redraw(); return 1; } } break; }
case FL_DRAG: { if (!drag_widget) break;
int nX = Fl::event_x() - xoff; // new x coordinate int nY = Fl::event_y() - yoff; // new y coordinate
int bbx = Fl::box_dx(box()); // left and right border width int bby = Fl::box_dy(box()); // top and bottom border width
// keep the widget inside its parent's borders
if (nX < x() + bbx) { nX = x() + bbx; } else if (nX + drag_widget->w() > x() + w() - bbx) { nX = x() + w() - drag_widget->w() - bbx; }
if (nY < y() + bby) { nY = y() + bby; } else if (nY + drag_widget->h() > y() + h() - bby) { nY = y() + h() - drag_widget->h() - bby; }
drag_widget->position(nX, nY); // set the new position drag_widget->color(FL_YELLOW); drag_widget->label("RIGHT BUT");
redraw(); return 1; }
case FL_RELEASE: { if (drag_widget && Fl::event_button() == FL_RIGHT_MOUSE) {
// Optional: restore the original widget order in the group. // Remove the next statement (or comment it out) if not desired. insert(*drag_widget, drag_index);
init_sizes(); // save widget positions for later resizing drag_widget = 0; redraw(); if (parent()) parent()->redraw(); return 1; } break; }
default: break; } // switch(e)
return Fl_Group::handle(e); } };
ENDCPLUS END USEH
DECLARE win TYPE Fl_Window* DECLARE MyButton TYPE Fl_Button* DECLARE but_a TYPE Fl_Button* DECLARE area TYPE DraggableGroup*
win = new Fl_Window(320,350, "right mouse button to drag objects") win->begin() area = new DraggableGroup(0, 0, 320,350) area->box(FL_GLEAM_UP_BOX)
but_a = new Fl_Button(10,10,100,125,"A") but_a->callback(but_a_cb) win->end() win->show() Fl::run()
|
|
|
Post by vovchik on Jan 13, 2018 20:31:04 GMT 1
Dear Joe, Thanks for the code. It looks nice and simple, and the code is self-contained. I will try to use that now in my card game. With kind regards, vovchik
|
|
|
Post by bigbass on Jan 16, 2018 19:47:50 GMT 1
Here is a port that does events with Fl::repeat_timeout and draw Had to modify the call back to get it to work source link seriss.com/people/erco/fltk/#CustomBarGraph'--- DEMONSTRATE HOW TO DRAW A TRIGGER SHAPED BAR GRAPH
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <math.h> PRAGMA INCLUDE <stdlib.h> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
'--- TRIGGER SHAPED BAR GRAPH CLASS
USEH #define USECPLUS extern "C" { #define ENDCPLUS }
USECPLUS
class MyBarGraph : public Fl_Group { int _value; // 0 - 100 public: MyBarGraph(int X, int Y, int W, int H, const char*L=0) : Fl_Group(X,Y,W,H,L) { _value = 0; } void value(int val) { _value = val; redraw(); } void draw() { Fl_Group::draw(); // TRIGGER GRAPHIC DRAWING CODE fl_color(42); int w = 1; for ( int t=0; t<_value; t+=2) { // Color the graph if ( t > 50 ) fl_color(FL_GREEN); if ( t > 80 ) fl_color(FL_YELLOW); if ( t > 85 ) fl_color(FL_RED); float f2 = ( abs(t-50) / 100.0 ); // f = .5 ~ 0 ~ .5 int xoff = (int)( f2 * f2 * 100 + .5); w += 1; int x1 = x() + 10 + xoff; int x2 = x() + 10 + w + xoff; int y1 = y() + h() - 10 - t; fl_line(x1, y1, x2, y1); } } };
ENDCPLUS END USEH
f = 6.28/4
SUB Timer_CB(void *)
f = f + .1 v = ( sin(f) + 1.0 ) * .5 v = v * 100 disp->value((int)(v + .5)) PRINT f win->redraw() IF f > 100.00 THEN f = 0 ENDIF PRINT f
Fl::repeat_timeout(0.03, Timer_CB) END SUB
'--- TEST THE ABOVE CLASS '--- Send a 0 .. 100 sine wave to the class using a timer. DECLARE disp TYPE MyBarGraph* DECLARE win TYPE Fl_Double_Window*
win = new Fl_Double_Window(240,240) disp = new MyBarGraph(20,20,240-40,240-40) disp->box(FL_BORDER_BOX) Fl::add_timeout(1.0, Timer_CB) disp->value(100) win->show() Fl::run()
|
|
|
Post by vovchik on Jan 16, 2018 20:33:25 GMT 1
Dear Joe,
Thanks. You are actually drawing things. It would be nice to get that c++ thing into a DRAW() command. We can, without really compiling fltk with cairo, use my cairo routines to create a cairo surface and draw on that using cario methods. I demonstrated that (sort of) with some rotated text, which is drawn to a temporary cairo surface, the surface is transformed into an fltk image and then displayed. It works, too. CAIRO_DRAW() would also be uesful.
With kind regards, vovchik
|
|
|
Post by bigbass on Jan 17, 2018 16:50:37 GMT 1
Hey vovchik Here is a simple demo that we will make the DRAW() from and everything resizes too I used the group so we can add some movement later Joe
'---DEMONSTRATE HOW TO DRAW AN 'X' and a box IN FLTK '--- modified to use GROUP and have a canvas and arrow operators '--- and somewhat of a baconized syntax to get the idea
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <math.h> PRAGMA INCLUDE <stdlib.h> PRAGMA INCLUDE <iostream> PRAGMA LDFLAGS -lfltk -lfltk_images -L. -lbacon++ PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS }
USECPLUS
'--- SIMPLE WIDGET THAT DRAWS AN 'X' and a box class DRAW : public Fl_Group { public:
DRAW(int X, int Y, int W, int H, const char*L=0) : Fl_Group(X,Y,W,H,L) { } void draw() { // DRAW 'X' int x1 = x(), y1 = y(); int x2 = x()+w()-1, y2 = y()+h()-1; //box fl_color(FL_BLUE); fl_rectf(x()-40,y()-40,w()-20,h()-20); fl_color(FL_BLACK); fl_line(x1, y1, x2, y2); fl_color(FL_WHITE); fl_line(x1, y2, x2, y1); } };
ENDCPLUS END USEH
DECLARE *CANVAS TYPE DRAW DECLARE *WINDOW TYPE Fl_Double_Window WINDOW = new Fl_Double_Window (200,200,"Draw X and box") CANVAS = new DRAW(0, 0, WINDOW->w(), WINDOW->h()) WINDOW->resizable(CANVAS) WINDOW->show() Fl::run()
|
|
|
Post by vovchik on Jan 18, 2018 10:38:07 GMT 1
Dear Joe,
Here is the same thing, just drawing plain lines. Now, if we could only create a SUB called LINE and not have to declare each LINE instance as a widget of sorts... Any idea how to do that? We could also do the same, then, for CIRCLE, SQUARE, RECTANGLE and ARC, and have all our drawing primitives.
With kind regards, vovchik
' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
' widget declaration DECLARE win TYPE Fl_Double_Window*
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class FL_LINE : public Fl_Widget { public: FL_LINE(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { fl_color(FL_RED); // width is second argument fl_line_style(0, 3, 0); int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); fl_line(x1, y1, x2, y2); } }; ; ENDCPLUS END USEH win = new Fl_Double_Window (200, 200, "Draw a line") win->color(FL_WHITE) FL_LINE draw_a(10, 10, win->w() - 10, win->h() - 10) FL_LINE draw_b(10, 20, 10, 100) win->resizable(draw_a) win->resizable(draw_b) win->show() Fl::run()
And here is a version with addressable line widgets:
' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class Fl_Line : public Fl_Widget { public: Fl_Line(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { fl_color(FL_RED); // width is second argument fl_line_style(0, 3, 0); int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); fl_line(x1, y1, x2, y2); } }; ; ENDCPLUS END USEH
' widget declarations DECLARE win TYPE Fl_Double_Window* DECLARE draw_a, draw_b TYPE Fl_Line*
' main win = new Fl_Double_Window (200, 200, "Draw a line") win->color(FL_WHITE) draw_a = new Fl_Line(10, 10, win->w() - 10, win->h() - 10) draw_b = new Fl_Line(10, 20, 10, 100) win->resizable(draw_b) win->show() Fl::run()
And here is a prototype LINE SUB, but we don't get multiple instances of a LINE showing with subsequent invocations yet.
' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class Fl_Line : public Fl_Widget { public: Fl_Line(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { fl_color(FL_RED); // width is second argument fl_line_style(0, 3, 0); int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); fl_line(x1, y1, x2, y2); } }; ; ENDCPLUS END USEH
' widget declarations DECLARE win TYPE Fl_Double_Window*
SUB LINE(int lx1, int ly1, int lx2, int ly2) LOCAL myline TYPE Fl_Line* myline = new Fl_Line(lx1, ly1, lx2, ly2) win->resizable(myline) win->show() END SUB
' main win = new Fl_Double_Window (200, 200, "Draw a line") win->color(FL_WHITE) LINE(20, 20, 150, 150) win->show() Fl::run()
And lastly, this is a real KLUDGE for getting style, color and thickness to work - by co-opting attributes in the standard Fl_Widget:
' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class Fl_Line : public Fl_Widget { public: Fl_Line(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { 'Fl_Color col1=color(); fl_color(color()); // width is second argument fl_line_style(labelcolor(), labelsize(), 0); 'unsigned int line_style; int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); fl_line(x1, y1, x2, y2); } }; ; ENDCPLUS END USEH
' widget declarations DECLARE win TYPE Fl_Double_Window*
' ------------------ SUB LINE(int lx1, int ly1, int lx2, int ly2, Fl_Color col, int thick, int style) ' ------------------ LOCAL myline TYPE Fl_Line* myline = new Fl_Line(lx1, ly1, lx2, ly2) myline->color(col) myline->labelsize(thick) myline->labelcolor(style) win->resizable(myline) win->show() END SUB
' main win = new Fl_Double_Window (200, 200, "Draw a line") win->color(FL_WHITE) LINE(20, 20, 150, 150, FL_DARK_GREEN, 18, FL_CAP_ROUND) win->show() Fl::run()
|
|
|
Post by vovchik on Jan 18, 2018 14:07:18 GMT 1
Dear all, And here is a little primitive drawing. Still trying to work things out, but making progress... With kind regards, vovchik ' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Box.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lfltk_images -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class Fl_Line : public Fl_Widget { public: Fl_Line(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { 'Fl_Color col1=color(); fl_color(color()); // width is second argument fl_line_style(labelcolor(), labelsize(), 0); 'unsigned int line_style; int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); 'fl_begin_loop(); fl_line(x1, y1, x2, y2); 'fl_end_loop(); } }; class Fl_Circle : public Fl_Widget { public: Fl_Circle(double X, double Y, double W, double H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { 'Fl_Color col1=color(); fl_color(color()); // width is second argument fl_line_style(labelcolor(), labelsize(), 0); 'unsigned int line_style; double x1 = x(), y1 = y(); double x2 = w(), y2 = h(); 'fl_begin_loop(); fl_circle(x1, y1, x2); //fl_line(x1, y1, x2, y2); 'fl_end_loop(); } }; ; ENDCPLUS END USEH
' widget declarations DECLARE win TYPE Fl_Double_Window* DECLARE box TYPE Fl_Box* DECLARE but TYPE Fl_Button*
' ------------------ SUB LINE(int lx1, int ly1, int lx2, int ly2, Fl_Color col, int thick, int style) ' ------------------ LOCAL myline TYPE Fl_Line* myline = new Fl_Line(lx1, ly1, lx2, ly2) myline->color(col) myline->labelsize(thick) myline->labelcolor(style) win->resizable(box) box->show() END SUB
' ------------------ SUB CIRCLE(double x, double y, double r, Fl_Color col, int thick, int style) ' ------------------ LOCAL mycircle TYPE Fl_Circle* mycircle = new Fl_Circle(x, y, r, 0) mycircle->color(col) mycircle->labelsize(thick) mycircle->labelcolor(style) win->resizable(box) box->show() END SUB
' main Fl::scheme("plastic") win = new Fl_Double_Window (200, 250, "Draw a line") box = new Fl_Box(200, 200, 0, 0) box->color(FL_WHITE) box->box(FL_NO_BOX) but = new Fl_Button(140, 210, 50, 30, "Exit") but->show() LINE(20, 20, 150, 150, FL_DARK_GREEN, 18, FL_CAP_ROUND) LINE(30, 30, 150, 150, FL_DARK_RED, 10, FL_CAP_ROUND) LINE(win->w()/2, 20, win->w()/2, 150, FL_YELLOW, 20, FL_CAP_ROUND) CIRCLE(80, 80, 30, FL_GREEN, 10, 0) CIRCLE(120, 120, 20, FL_RED, 10, 0) win->redraw() win->show() Fl::run() Attachments:
|
|
|
Post by vovchik on Jan 18, 2018 17:01:30 GMT 1
Dear all, I am somewhat puzzled here. If I put the drawing statements into DRAW_CB (below), they do not show. Do not know why. And, the initial screen here shows the circles, but they disappear after a hide/show that is handled by the Hide Button callback. Any ideas?. With kind regards, vovchik UPDATED: Now works fine with Joe's fix. Thanks. ' Demonstrate how to draw a line in fltk
PRAGMA INCLUDE <FL/Fl.H> PRAGMA INCLUDE <FL/x.H> PRAGMA INCLUDE <FL/Fl_Widget.H> PRAGMA INCLUDE <FL/Fl_Button.H> PRAGMA INCLUDE <FL/Fl_Box.H> PRAGMA INCLUDE <FL/Fl_Group.H> PRAGMA INCLUDE <FL/Fl_Double_Window.H> PRAGMA INCLUDE <FL/fl_draw.H> PRAGMA OPTIONS -Wno-deprecated PRAGMA LDFLAGS -lfltk -lbacon++ -s PRAGMA COMPILER g++ PRAGMA OPTIONS -Wno-write-strings -Wno-pointer-arith -fno-strict-aliasing -fpermissive OPTION PARSE FALSE
USEH #define USECPLUS extern "C" { #define ENDCPLUS } USECPLUS class Fl_Line : public Fl_Widget { public: Fl_Line(int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L) { } void draw() { fl_color(color()); // style is first argument, width is second argument fl_line_style(labelcolor(), labelsize(), 0); int x1 = x(), y1 = y(); int x2 = w(), y2 = h(); fl_line(x1, y1, x2, y2); } }; class Fl_Circle : public Fl_Widget { public: Fl_Circle(double X, double Y, double W, const char*L=0) : Fl_Widget(X,Y,W,0,L) { } void draw() { fl_color(color()); // style is first argument, width is second argument fl_line_style(labelcolor(), labelsize(), 0); double x1 = x(), y1 = y(); double x2 = w(); fl_circle(x1, y1, x2); } }; ; ENDCPLUS END USEH
' widget declarations DECLARE win TYPE Fl_Double_Window* DECLARE box, menubar TYPE Fl_Box* DECLARE but0, but1 TYPE Fl_Button* DECLARE canvas TYPE Fl_Group* DECLARE canvas_w, canvas_h TYPE int canvas_w = 300 canvas_h = 300
' ------------------ SUB LINE(int lx1, int ly1, int lx2, int ly2, Fl_Color col, int thick, int style) ' ------------------ LOCAL myline TYPE Fl_Line* myline = new Fl_Line(lx1, ly1, lx2, ly2) myline->color(col) myline->labelsize(thick) myline->labelcolor(style) END SUB
' ------------------ SUB CIRCLE(double x, double y, double r, Fl_Color col, int thick, int style) ' ------------------ LOCAL mycircle TYPE Fl_Circle* mycircle = new Fl_Circle(x, y, r, 0) mycircle->color(col) mycircle->labelsize(thick) mycircle->labelcolor(style) END SUB
' ------------------ SUB QUIT_CB(Fl_Widget* widget, void* data) ' ------------------ PRINT "Exiting..." END END SUB
' ------------------ SUB DRAW_CB(Fl_Widget* widget, void* data) ' ------------------ PRINT "Start DRAW_CB" IF NOT(canvas->visible()) THEN PRINT "Show drawing" canvas->show() but0->copy_label("Hide") win->redraw() ELSE PRINT "Hide drawing" canvas->hide() but0->copy_label("Show") win->redraw() END IF END SUB
' main Fl::scheme("plastic") win = new Fl_Double_Window (canvas_w, canvas_h + 50, "Draw something") box = new Fl_Box(FL_FLAT_BOX, 0, 0, canvas_w, canvas_h, "") box->color(FL_WHITE) menubar = new Fl_Box(FL_GLEAM_UP_BOX, 0, canvas_w, canvas_h, 50, "") menubar->color(FL_DARK_RED) but0 = new Fl_Button(10, (win->h() - 40), 50, 30, "Draw") but0->callback(DRAW_CB, NULL) but0->show() but1 = new Fl_Button((win->w() - 60), (win->h() - 40), 50, 30, "Exit") but1->callback(QUIT_CB, NULL) but1->show() canvas = new Fl_Group(0, 0, canvas_w, canvas_h) CIRCLE(80, 80, 30, FL_GREEN, 10, 0) LINE(20, 20, 150, 150, FL_DARK_GREEN, 18, FL_CAP_ROUND) LINE(30, 30, 150, 150, FL_DARK_RED, 10, FL_CAP_ROUND) LINE(box->w()/2, 20, box->w()/2, 150, FL_YELLOW, 20, FL_CAP_ROUND) CIRCLE(120, 120, 20, FL_RED, 10, 0) win->resizable(canvas) win->redraw() canvas->end() win->show() Fl::run()
|
|
|
Post by Pjot on Jan 18, 2018 19:29:10 GMT 1
Hi vovchik,
Not sure if it makes a difference but you may need to use Fl::flush() as well?
BR Peter
|
|