Fl_Tree callback when FL_WHEN_RELEASE - fltk

The documentation for Fl_Tree in FLTK 1.3.4 says:
The callback() is invoked depending on the value of when()
FL_WHEN_RELEASE -- callback invoked when left mouse button is released on an item
FL_WHEN_CHANGED -- callback invoked when left mouse changes selection state
but I can't get the callback called if the mouse is released and I can't see a difference between both. Any ideas?
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Tree.H>
static void cb_(Fl_Tree*, void*)
{
printf ("callback\n");
}
int main()
{
Fl_Double_Window* w = new Fl_Double_Window(325, 325);
Fl_Tree* o = new Fl_Tree(25, 25, 255, 245);
o->callback((Fl_Callback*)cb_);
o->when(FL_WHEN_RELEASE);
o->add("foo/bar");
o->add("foo/baz");
o->end();
w->show();
return Fl::run();
}
this snippets outputs "callback" on every change, even if FL_WHEN_RELEASE is set.

If you have downloaded, the distribution, have a look at test/input.cxx and test/tree.cxx. Both have tests for the different when selections.
WHEN_CHANGED only makes sense on edit boxes, browsers and tables - you can verify the data as it is typed in. This does not happen with WHEN_RELEASE. For all other widgets, there is virtually no difference.
Edit
In order for release to fire every time, there are one of three options
Modify the source FL_Tree.cxx. Look for FL_Tree::select. Change alreadySelected to false.
If you look at the source, in the same routine, further down, it says
#if FLTK_ABI_VERSION >= 10301
If the library is built with FLTK_ABI_VERSION set to 10301, it will call the reselect but there is also a whole load of other stuff it will do when this #define is set since it affects all widgets
Comment out the #if FLTK_ABI_VERISON and corresponding #endif in FL_Tree::select.

Related

GTK Data Capturing

I’m working in C on a project to capture data from a sensor and display it as part of a GUI application on the Raspberry Pi. I am using GTK 3.0, plus Cairo for graphing. I have built an application that works, but I want to make a modification to enable me to change the frequency of data capture.
Within my main code section I have a command like:-
gdk_threads_add_timeout (250, data_capture, widgets);
This all works, the data capture routine is triggered every 250mS, but I want to add functionality to the GUI to enable the user to change the speed. If I try to call this function from anywhere else other than main, it fails.
I have looked for other ways to do it, but I can’t find any examples or explanations of how I can do it.
Ideally what I would like is something like:-
void update_speed(button, widgets)
// Button to change speed has been pressed
read speed from GUI
update frequency
return
int main()
...
setup GUI
set default speed
start main GTK loop
Does anyone have any idea how I could achieve this?
Edit: Additional Code Snippet
(This is not the whole program, but an extract of main)
int main(int argc, char** argv) {
GtkBuilder *builder;
GtkWidget *window;
GError *err = NULL; // holds any error that occurs within GTK
// instantiate structure, allocating memory for it
struct app_widgets *widgets = g_slice_new(struct app_widgets);
// initialise GTK library and pass it in command line parameters
gtk_init(&argc, &argv);
// build the gui
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "../Visual/gui/main_window.glade", &err);
window = GTK_WIDGET(gtk_builder_get_object(builder, "main_application_window"));
// build the structure of widget pointers
widgets->w_spn_dataspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_dataspeed"));
widgets->w_spn_refreshspeed = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spn_refreshspeed"));
widgets->w_adj_dataspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_dataspeed"));
widgets->w_adj_refreshspeed = GTK_ADJUSTMENT(gtk_builder_get_object(builder, "adj_refreshspeed"));
// connect the widgets to the signal handler
gtk_builder_connect_signals(builder, widgets); // note: second parameter points to widgets
g_object_unref(builder);
// Set a timeout running to refresh the screen
gdk_threads_add_timeout(SCREEN_REFRESH_TIMER, (GSourceFunc)screen_timer_exe, (gpointer)widgets);
gdk_threads_add_timeout(DATA_REFRESH_TIMER, (GSourceFunc)data_timer_exe, (gpointer)widgets);
gtk_widget_show(window);
gtk_main();
// free up memory used by widget structure, probably not necessary as OS will
// reclaim memory from application after it exits
g_slice_free(struct app_widgets, widgets);
return (EXIT_SUCCESS);

PixiJS - Not all touchend events triggering (outside of displayObject)

Pixijs (3.0.8) supports multi-touch as shown in their demos, and I've set up start, move and end listeners for touches on my mobile device.
The touches are registered on a square within the canvas which I'll call the interactiveArea, but the touchend events trigger when let go outside of the area as well. This is behavior that works fine with a single mouse cursor.
However, when using more fingers, having touches with the identifiers 0,1 and 2, only the first touchEnd is triggered outside of the area.
So I press and hold 3 fingers inside the interactiveArea and move them all outside of it. Then I let go of 1, and then the others. I won't be notified of touchEnds for event 0 and 2, and I'd have to re-register 3 touches and let go properly just to get a touchend for 2 triggered!
Any tips on how I can detect all touchends, rather than have it stop on the first touchend? I've tried working with a setTimeout hack as well, but that really doesn't suit my use case.
Edit I've made a basic codepen to demonstrate how touchendoutside is only triggered once. https://codepen.io/Thomaswithaar/pen/EygRjM Do visit the pen on mobile, as it is about touches rather than mouse interactivity.
Holding two fingers on the red square and then moving them out and letting go will only trigger one touchendoutside event.
Looking at the PIXI source code, there is indeed a bug in the Interaction Manager. Here is the method that processes touch end events:
InteractionManager.prototype.processTouchEnd = function ( displayObject, hit )
{
if(hit)
{
this.dispatchEvent( displayObject, 'touchend', this.eventData );
if( displayObject._touchDown )
{
displayObject._touchDown = false;
this.dispatchEvent( displayObject, 'tap', this.eventData );
}
}
else
{
if( displayObject._touchDown )
{
displayObject._touchDown = false;
this.dispatchEvent( displayObject, 'touchendoutside', this.eventData );
}
}
};
You can see in the else statement that a touchendoutside event gets dispatched when displayObject._touchDown is true. But after you release your first finger, it sets the flag to false. That is why you only receive that event once.
I've opened an issue here:
https://github.com/pixijs/pixi.js/issues/2662
And provided a fix here:
https://github.com/karmacon/pixi.js/blob/master/src/interaction/InteractionManager.js
This solution removes the flag and uses a counter instead. I haven't tested it yet, so please let me know if it works.

GTK3 GtkLayout with cairo, cannot get update region

I am trying to draw a GtkLayout using cairo. The layout is huge and I need to get the part that is visible in the container window and update that part only. With GTK2 the expose event data was sufficient to do this. I am not successful with GTK3.
In the function to handle "draw" events, I did the following:
GdkWindow *gdkwin; // window to draw
cairo_region_t *cregion; // update regions
cairo_rectangle_int_t crect; // enclosing rectangle
gdkwin = gtk_layout_get_bin_window(GTK_LAYOUT(layout));
cregion = gdk_window_get_update_area(gdkwin);
cairo_region_get_extents(cregion,&crect);
expy1 = crect.y; // top of update area
expy2 = expy1 + crect.height; // bottom of update area
The problem is that cregion has garbage. Either gdk_window_get_update_area() is buggy or I am not using the right drawing window.
Passing the GtkLayout as follows also does not work (this is the function arg for g_signal_connect):
void draw_function(GtkWidget *layout, cairo_t *cr, void *userdata)
Whatever gets passed is not the GtkLayout from g_signal_connect, but something else.
================= UPDATE ====================
I found a way to do what I want without using GtkLayout.
I am using a GtkDrawingArea inside a viewport.
I can scroll to any window within the large graphic layout
and update that window only. Works well once I figured out
the cryptic docs.
scrwing = gtk_scrolled_window_new(0,0);
gtk_container_add(GTK_CONTAINER(vboxx),scrwing);
drwing = gtk_drawing_area_new();
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrwing),drwing);
gtk_scrolled_window_set_policy(SCROLLWIN(scrwing),ALWAYS,ALWAYS);
scrollbar = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrwing));

Draw a line in mfc with help of toolbar

I am trying to make a paint application in MFC using visul basic c++ 6.0 i have already created a window using Create function and also have created a toolbar with a tool line but i am stuck on how to code for the line because the function i know goes like d.lineTo(x,y) and d.Moveto(x2,y2) but it comes under the line function how do i use OnLButtonDown to Trap the co-ordiantes or is there any other way i can draw a line ..? any help will be useful
have a look at the MFC Scribble tutorial :
http://msdn.microsoft.com/en-us/library/aa716527%28v=vs.60%29.aspx)
It will get you started on how to handling mouse click and mouse move and drawing.
M.
Ok, you're going to have to override several member functions to do this. I've outlined an approach below. My example below deals with a single line-drawing operation (from mouse down, to mouse up). An exercise for you, is to make it so that once you've done one, you can then do another at a different place. It's easy, btw!
CWnd::OnLButtonDown(UINT _flags, CPoint _pt);
CWnd::OnLButtonUp(UINT _flags, CPoint _pt);
CWnd::OnMouseMove(UINT _flags, CPoint _pt);
CWnd::OnPaint()
Apologies if some of these function signatures are wrong! Add some members to your window class:
// at the top of your file
#include <vector>
// in your class
typedef std::vector<POINT> PointVector;
PointVector m_Points;
CYourWnd::OnLButtonDown(UINT _flags, CPoint _pt);
{
// NOTE: For more than one set of drawing, this will be different!
m_Points.clear();
m_Points.push_back(POINT(_pt.x, _pt.y));
}
CYourWnd::OnMouseMove(UINT _flags, CPoint _pt);
{
if(_flags & MK_LBUTTON)
{
const POINT& last(m_Points.back());
if(_pt.x != last.x || _pt.y != last.y)
{
m_Points.push_back(POINT(_pt.x, _pt.y));
Invalidate();
}
}
}
CYourWnd::OnPaint()
{
CPaintDC dc(this);
CRect rcClient; GetClientRect(&rc);
FillSolidRect(&rcClient, RGB(255, 255, 255));
if(m_Points.size())
{
dc.MoveTo(m_Points[0].x, m_Points[0].y);
for(PointsVector::size_type p(1);
p < m_Points.size();
++p)
dc.LineTo(m_Points[p].x, m_Points[p].y);
}
}
Obviously, this is crude and gives you a single drawing operation. Once you click the left button down again, it erases what you've done. So, once you have this working:
Make it so you can draw an unlimited amount of lines. You could accomplish this in several ways such as an additional container (to store vectors), or even drawing-operation classes that you can store in a single vector and then execute.
This solution may well flicker. How might you stop this? Perhaps OnEraseBkgnd holds the clue...
How about more colours?
All signs point towards creating some drawing-classes that encapsulate this for you, but I hope this has got you started.

How to avoid CListCtrl items to be partially visible?

I have a resizeable CListCtrl and I want to avoid any item being displayed partially, ever.
For example:
I want Item 9 to not be displayed in this case. Is there a flag or method for this? How would you go about solving this issue?
I tried the following and it was no good:
void CMyCListCtrl::OnEndScrolling()
{
int iCount = this->GetCountPerPage();
EnsureVisible(iCount - 1, FALSE);
}
after catching
...
ON_NOTIFY( LVN_ENDSCROLL, IDC_LIST1, OnEndScroll )
...
void CWheelTestDlg::OnEndScroll(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLVSCROLL pnmLVScroll = (LPNMLVSCROLL) pNMHDR;
m_MyListCtrl.OnEndScrolling();
*pResult = 0;
}
In the CListCtrl parent dialog. (which I don't want to do, I want to do everything in my CListCtrl derived class only, if possible).
All I accomplish is showing item 9 completely, but item 10 is partially visible below it. If I have 30 items I don't want to scroll the list to show item 30, I want to show up to item 8 with no partially visible item below it.
CListCtrl doesn't appear to support Integral Height.
Here's a solution that accomplishes what you desire by forcefully changing the control height [with commented conditions] (http://www.codeproject.com/Messages/418084/Socket-accept-call.aspx):
/////////////////////////////////////////////////////////////////////////////////
// This assumes a REPORT-style CListCtrl.
//
// Resize the control. This works correctly only if scrolling is disabled. If
// there is scrolling, then setting to the size from ApproximateViewRect() will
// always give scroll bars showing. Which is irritating.
//
// We need to adjust the vertical size from what ApproximateViewRect() returns
// by one row minus border width
//////////////////////////////////////////////////////////////////////////////////
CSize sz = m_list.ApproximateViewRect(); // always adds room for a new row
CRect itRect; // Get the height of a single row (there had better *be* a row!)
m_list.GetItemRect(0, &itRect, LVIR_BOUNDS);
int vOffset = itRect.Height() - 3; // leave a little 'cuz it looks better
m_list.SetWindowPos(NULL, 0, 0, sz.cx, sz.cy - vOffset,
SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
I have the similar problem in wince, and find a solution accidentally. No direct solution in internet, so i decide to re-position scroll bar after receive some message, and the only message i can used in wince is WM_LBUTTONDOWN, other messages such as OnEndScroll are not called, maybe something wrong in my code.
Whatever, i use Timer(ON_WM_TIMER) to re-position scroll bar when receive WM_LBUTTONDOWN message, then find that list control doesn't scroll automatically! then i remain a empty OnTimer function and remove everything else. It works, and i guess list control use Timer to scroll partial row.
Hope useful to you.

Resources