Tool-Tip timing problem

View: New views
11 Messages — Rating Filter:   Alert me  

Tool-Tip timing problem

by Roland Plüss-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This is some strange behavior which bugs me right now. I'm using tool
tips in my app. Now I have a special loop running like this:

while( app->runWhileEvents() == TRUE ){
     windowMain->OnFrameUpdate();
}

This is since I have to do periodic updating of the screen. Now if this
is in place tool tips do no more show up or only after hovering for over
5 seconds over a control. How is the tool tip implemented? What could
mess up the timing?


--
Yours sincerely
Plüss Roland


------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: Tool-Tip timing problem

by Jeroen van der Zijp :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thursday 26 March 2009, Roland Plüss wrote:

> This is some strange behavior which bugs me right now. I'm using tool
> tips in my app. Now I have a special loop running like this:
>
> while( app->runWhileEvents() == TRUE ){
>      windowMain->OnFrameUpdate();
> }
>
> This is since I have to do periodic updating of the screen. Now if this
> is in place tool tips do no more show up or only after hovering for over
> 5 seconds over a control. How is the tool tip implemented? What could
> mess up the timing?

The FXToolTip is done using "on idle" processing, i.e. its done just before
the main thread would otherwise fall asleep in the select() system call.

The "on idle" processing kicks in when there are no events, and no timers;
however, since you're using runWhileEvents() the event loop returns instead
of calling idle processing.

My suggestion: put the onFrameUpdate() into a idle processing callback
[basically, call app->addChore() to run it each time you need it to run].

This way, you could use a normal event loop, and the system will perform
your OnFrameUpdate() as part of the regular chore processing.

Note:- if OnFrameUpdate() takes a very long time, the regular chores may
be a bit less frequently executed.  But at least they'll still run.

[If OnFrameUpdate() takes a very long time, you could also try to kick
it off from a timer; this allows you some more control over how frequently
this function is called....].



Hope this helps,

                        - Jeroen





------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

tooltips stop popping up during FXList updates

by jasonheb - Skype™ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Is there a way to get tooltips to appear in a FXList that is loading
with setItem/insertItem?





------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: tooltips stop popping up during FXList updates

by Jeroen van der Zijp :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tuesday 31 March 2009, Jason Heblack wrote:
> Is there a way to get tooltips to appear in a FXList that is loading
> with setItem/insertItem?

If a FXToolTip has been created, it should automatically show the full title of the
text of each item if you hover the mouse over that item.

The tooltip system however also sends a SEL_QUERY_TIP to the target of the FXList
widget; if you intercept this, you can supply a custom tip, as follows:

  FXMAPFUNC(SEL_QUERY_TIP,MyTarget::ID_LIST,MyTarget::onQueryTip)


and then:

        // We were asked about tip text
        long MyTarget::onQueryTip(FXObject* sender,FXSelector,void* ptr){
          FXString tip="TipTopTip";
          sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&tip);
          return 1;
          }


This would show "TipTopTip" anywhere in the list. You can use getCursorPosition()
and getItemAt(x,y) to display an item-dependent custom tooltip.


Hope this helps,

                        - Jeroen


------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: tooltips stop popping up during FXList updates

by jasonheb - Skype™ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The example here shows a case of broken tooltips. There is only one
widget here that would be affected by tooltips. Is this example fixable
by changing a base class?

Steps to reproduce:
1. run the attached cpp file or run from copying and pasting
2. hover mouse over list items

Actual results:
Tooltips appear quickly but then immediately disappear when an item is
either put into the list or an existing list item text is reset.

Expected results:
The tooltips would remain until the mouse pointer leaves a list item.


#include <fx.h>

class ListItemModel {
public:
    FXString m_text, *m_tip;

    ListItemModel(FXString text, FXString *tip) {
        m_text = text;
        m_tip = tip;
    }
};

class GUIList : public FX::FXList {

    FXDECLARE(GUIList)
public:
    GUIList() {
    }
    GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint opts,
FXint x, FXint y, FXint w, FXint h);
    long onQueryTip(FXObject* sender, FXSelector sel, void* ptr);
};

GUIList::GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint
opts, FXint x, FXint y, FXint w, FXint h) : FXList(p, tgt, sel, opts, x,
y, w, h) {
    ;
}
FXDEFMAP(GUIList) GUIListMap[] = {
    FXMAPFUNC(SEL_QUERY_TIP, 0, GUIList::onQueryTip)
};

FXIMPLEMENT(GUIList, FXList, GUIListMap, ARRAYNUMBER(GUIListMap))

class Window : public FX::FXMainWindow {

    FXDECLARE(Window)
protected:
    Window() {
        ;
    }
public:
    static GUIList *s_list;
    static FXColor s_black;

    enum {
        ID_SET = FXMainWindow::ID_LAST,
        ID_INSERT
    };
    Window(FXApp* a);
    long set(FXObject* obj, FXSelector sel, void* ptr);
    long insert(FXObject* obj, FXSelector sel, void* ptr);

    virtual ~Window() {
        ;
    }

    virtual void create() {
        FXMainWindow::create();
        show(PLACEMENT_SCREEN);
    }
};

FXDEFMAP(Window) WindowMap[] = {
    FXMAPFUNC(SEL_IO_READ, Window::ID_SET, Window::set),
    FXMAPFUNC(SEL_IO_READ, Window::ID_INSERT, Window::insert)
};

FXIMPLEMENT(Window, FX::FXMainWindow, WindowMap, ARRAYNUMBER(WindowMap))

Window::Window(FXApp* a) : FXMainWindow(a, "example", NULL, NULL,
DECOR_TITLE | DECOR_MINIMIZE | DECOR_CLOSE | LAYOUT_FILL_X |
LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 800, 600) {
    s_list = new GUIList(this, this, ID_SET, FX::LIST_BROWSESELECT |
LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 200, 0);
    s_list->setScrollStyle(VSCROLLER_ALWAYS | HSCROLLER_NEVER);
    s_list->verticalScrollBar()->setHiliteColor(s_black);
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    new FXToolTip(getApp(), TOOLTIP_PERMANENT);
}

long Window::set(FXObject* obj, FXSelector sel, void* ptr) {
    FXString *text = *((FXString**) ptr);
    s_list->setItemText((s_list->getNumItems() - 1), *text);
    delete text;
    return 1;
}

long Window::insert(FXObject* obj, FXSelector sel, void* ptr) {
    ListItemModel *model = *((ListItemModel**) ptr);
    s_list->insertItem((s_list->getNumItems()), model->m_text, NULL,
model->m_tip);
    delete model;
    return 1;
}

Window *g_window;
FXColor Window::s_black = FXRGB(0, 0, 0);
GUIList* Window::s_list = NULL;

long GUIList::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
    FXint idx = g_window->s_list->getCursorItem();
    if (idx < 0)
        return 0;
    FXString *tip = ((FXString *) g_window->s_list->getItemData(idx));
    sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)
tip);
    return 1;
}

class Worker : public FX::FXThread {
public:

    Worker() {
        ;
    }
    FXint run();
};

FXint Worker::run() {
    FXMessageChannel load(g_window->getApp());
    FXString *string;
    ListItemModel *model;
    for (FXint i = 1; i <= 100; i++) {
        string = new FXString(FXString("setItem - ") +
FXString(FXString::value(i) + " of 100"));
        load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_SET),
&string, sizeof (*string));
        FXThread::sleep(100000000);
    }
    for (FXint i = 1; i <= 10000; i++) {
        model = new ListItemModel(FXString(FXString::value(i) + " of
1000"), new FXString(FXString::value(FX::FXThread::time()) + FXString("
nanoseconds since Epoch ")));
        load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_INSERT),
&model, sizeof (*model));
        model = 0;
        FXThread::sleep(100000000);
    }
}

int main(int argc, char *argv[]) {
    FXApp application("example", "example");
    application.init(argc, argv);
    g_window = new Window(&application);
    application.create();
    application.setToolTipPause(0);
    (new Worker)->start();
    return application.run();
}



[example.cpp]

#include <fx.h>

class ListItemModel {
public:
    FXString m_text, *m_tip;

    ListItemModel(FXString text, FXString *tip) {
        m_text = text;
        m_tip = tip;
    }
};

class GUIList : public FX::FXList {

    FXDECLARE(GUIList)
public:
    GUIList() {
    }
    GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h);
    long onQueryTip(FXObject* sender, FXSelector sel, void* ptr);
};

GUIList::GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h) : FXList(p, tgt, sel, opts, x, y, w, h) {
    ;
}
FXDEFMAP(GUIList) GUIListMap[] = {
    FXMAPFUNC(SEL_QUERY_TIP, 0, GUIList::onQueryTip)
};

FXIMPLEMENT(GUIList, FXList, GUIListMap, ARRAYNUMBER(GUIListMap))

class Window : public FX::FXMainWindow {

    FXDECLARE(Window)
protected:
    Window() {
        ;
    }
public:
    static GUIList *s_list;
    static FXColor s_black;

    enum {
        ID_SET = FXMainWindow::ID_LAST,
        ID_INSERT
    };
    Window(FXApp* a);
    long set(FXObject* obj, FXSelector sel, void* ptr);
    long insert(FXObject* obj, FXSelector sel, void* ptr);

    virtual ~Window() {
        ;
    }

    virtual void create() {
        FXMainWindow::create();
        show(PLACEMENT_SCREEN);
    }
};

FXDEFMAP(Window) WindowMap[] = {
    FXMAPFUNC(SEL_IO_READ, Window::ID_SET, Window::set),
    FXMAPFUNC(SEL_IO_READ, Window::ID_INSERT, Window::insert)
};

FXIMPLEMENT(Window, FX::FXMainWindow, WindowMap, ARRAYNUMBER(WindowMap))

Window::Window(FXApp* a) : FXMainWindow(a, "example", NULL, NULL, DECOR_TITLE | DECOR_MINIMIZE | DECOR_CLOSE | LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 800, 600) {
    s_list = new GUIList(this, this, ID_SET, FX::LIST_BROWSESELECT | LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 200, 0);
    s_list->setScrollStyle(VSCROLLER_ALWAYS | HSCROLLER_NEVER);
    s_list->verticalScrollBar()->setHiliteColor(s_black);
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    s_list->appendItem("test", NULL, new FXString("test"));
    new FXToolTip(getApp(), TOOLTIP_PERMANENT);
}

long Window::set(FXObject* obj, FXSelector sel, void* ptr) {
    FXString *text = *((FXString**) ptr);
    s_list->setItemText((s_list->getNumItems() - 1), *text);
    delete text;
    return 1;
}

long Window::insert(FXObject* obj, FXSelector sel, void* ptr) {
    ListItemModel *model = *((ListItemModel**) ptr);
    s_list->insertItem((s_list->getNumItems()), model->m_text, NULL, model->m_tip);
    delete model;
    return 1;
}

Window *g_window;
FXColor Window::s_black = FXRGB(0, 0, 0);
GUIList* Window::s_list = NULL;

long GUIList::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
    FXint idx = g_window->s_list->getCursorItem();
    if (idx < 0)
        return 0;
    FXString *tip = ((FXString *) g_window->s_list->getItemData(idx));
    sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*) tip);
    return 1;
}

class Worker : public FX::FXThread {
public:

    Worker() {
        ;
    }
    FXint run();
};

FXint Worker::run() {
    FXMessageChannel load(g_window->getApp());
    FXString *string;
    ListItemModel *model;
    for (FXint i = 1; i <= 100; i++) {
        string = new FXString(FXString("setItem - ") + FXString(FXString::value(i) + " of 100"));
        load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_SET), &string, sizeof (*string));
        FXThread::sleep(100000000);
    }
    for (FXint i = 1; i <= 10000; i++) {
        model = new ListItemModel(FXString(FXString::value(i) + " of 1000"), new FXString(FXString::value(FX::FXThread::time()) + FXString(" nanoseconds since Epoch ")));
        load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_INSERT), &model, sizeof (*model));
        model = 0;
        FXThread::sleep(100000000);
    }
}

int main(int argc, char *argv[]) {
    FXApp application("example", "example");
    application.init(argc, argv);
    g_window = new Window(&application);
    application.create();
    application.setToolTipPause(0);
    (new Worker)->start();
    return application.run();
}




------------------------------------------------------------------------------

_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: tooltips stop popping up during FXList updates

by Jeroen van der Zijp :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wednesday 01 April 2009, Jason Heblack wrote:

> The example here shows a case of broken tooltips. There is only one
> widget here that would be affected by tooltips. Is this example fixable
> by changing a base class?
>
> Steps to reproduce:
> 1. run the attached cpp file or run from copying and pasting
> 2. hover mouse over list items
>
> Actual results:
> Tooltips appear quickly but then immediately disappear when an item is
> either put into the list or an existing list item text is reset.
>
> Expected results:
> The tooltips would remain until the mouse pointer leaves a list item.
>
>
> #include <fx.h>
>
> class ListItemModel {
> public:
>     FXString m_text, *m_tip;
>
>     ListItemModel(FXString text, FXString *tip) {
>         m_text = text;
>         m_tip = tip;
>     }
> };
>
> class GUIList : public FX::FXList {
>
>     FXDECLARE(GUIList)
> public:
>     GUIList() {
>     }
>     GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint opts,
> FXint x, FXint y, FXint w, FXint h);
>     long onQueryTip(FXObject* sender, FXSelector sel, void* ptr);
> };
>
> GUIList::GUIList(FXComposite *p, FXObject* tgt, FXSelector sel, FXuint
> opts, FXint x, FXint y, FXint w, FXint h) : FXList(p, tgt, sel, opts, x,
> y, w, h) {
>     ;
> }
> FXDEFMAP(GUIList) GUIListMap[] = {
>     FXMAPFUNC(SEL_QUERY_TIP, 0, GUIList::onQueryTip)
> };
>
> FXIMPLEMENT(GUIList, FXList, GUIListMap, ARRAYNUMBER(GUIListMap))
>
> class Window : public FX::FXMainWindow {
>
>     FXDECLARE(Window)
> protected:
>     Window() {
>         ;
>     }
> public:
>     static GUIList *s_list;
>     static FXColor s_black;
>
>     enum {
>         ID_SET = FXMainWindow::ID_LAST,
>         ID_INSERT
>     };
>     Window(FXApp* a);
>     long set(FXObject* obj, FXSelector sel, void* ptr);
>     long insert(FXObject* obj, FXSelector sel, void* ptr);
>
>     virtual ~Window() {
>         ;
>     }
>
>     virtual void create() {
>         FXMainWindow::create();
>         show(PLACEMENT_SCREEN);
>     }
> };
>
> FXDEFMAP(Window) WindowMap[] = {
>     FXMAPFUNC(SEL_IO_READ, Window::ID_SET, Window::set),
>     FXMAPFUNC(SEL_IO_READ, Window::ID_INSERT, Window::insert)
> };
>
> FXIMPLEMENT(Window, FX::FXMainWindow, WindowMap, ARRAYNUMBER(WindowMap))
>
> Window::Window(FXApp* a) : FXMainWindow(a, "example", NULL, NULL,
> DECOR_TITLE | DECOR_MINIMIZE | DECOR_CLOSE | LAYOUT_FILL_X |
> LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 800, 600) {
>     s_list = new GUIList(this, this, ID_SET, FX::LIST_BROWSESELECT |
> LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 200, 0);
>     s_list->setScrollStyle(VSCROLLER_ALWAYS | HSCROLLER_NEVER);
>     s_list->verticalScrollBar()->setHiliteColor(s_black);
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     s_list->appendItem("test", NULL, new FXString("test"));
>     new FXToolTip(getApp(), TOOLTIP_PERMANENT);
> }
>
> long Window::set(FXObject* obj, FXSelector sel, void* ptr) {
>     FXString *text = *((FXString**) ptr);
>     s_list->setItemText((s_list->getNumItems() - 1), *text);
>     delete text;
>     return 1;
> }
>
> long Window::insert(FXObject* obj, FXSelector sel, void* ptr) {
>     ListItemModel *model = *((ListItemModel**) ptr);
>     s_list->insertItem((s_list->getNumItems()), model->m_text, NULL,
> model->m_tip);
>     delete model;
>     return 1;
> }
>
> Window *g_window;
> FXColor Window::s_black = FXRGB(0, 0, 0);
> GUIList* Window::s_list = NULL;
>
> long GUIList::onQueryTip(FXObject* sender, FXSelector sel, void* ptr) {
>     FXint idx = g_window->s_list->getCursorItem();
>     if (idx < 0)
>         return 0;
>     FXString *tip = ((FXString *) g_window->s_list->getItemData(idx));
>     sender->handle(this, FXSEL(SEL_COMMAND, ID_SETSTRINGVALUE), (void*)
> tip);
>     return 1;
> }
>
> class Worker : public FX::FXThread {
> public:
>
>     Worker() {
>         ;
>     }
>     FXint run();
> };
>
> FXint Worker::run() {
>     FXMessageChannel load(g_window->getApp());
>     FXString *string;
>     ListItemModel *model;
>     for (FXint i = 1; i <= 100; i++) {
>         string = new FXString(FXString("setItem - ") +
> FXString(FXString::value(i) + " of 100"));
>         load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_SET),
> &string, sizeof (*string));
>         FXThread::sleep(100000000);
>     }
>     for (FXint i = 1; i <= 10000; i++) {
>         model = new ListItemModel(FXString(FXString::value(i) + " of
> 1000"), new FXString(FXString::value(FX::FXThread::time()) + FXString("
> nanoseconds since Epoch ")));
>         load.message(g_window, FXSEL(SEL_IO_READ, Window::ID_INSERT),
> &model, sizeof (*model));
>         model = 0;
>         FXThread::sleep(100000000);
>     }
> }
>
> int main(int argc, char *argv[]) {
>     FXApp application("example", "example");
>     application.init(argc, argv);
>     g_window = new Window(&application);
>     application.create();
>     application.setToolTipPause(0);
>     (new Worker)->start();
>     return application.run();
> }

I think I found your problem.

When you add new items into the FXList, the cursor-item is reset to -1 in the
subsequent recalc().  It needs to do that because when an item is added we
recompute the content size and possibly scroll the list, and as a result no
longer know which item is under the cursor.

I believe the getCursorItem() is, by the way, quite a useless function [I think
I've used it only once in all of my FOX applications], and moreover its not
reliable.

Instead, I'm computing the tooltip based on getCursorPosition() and getItemAt()
directly, at the time that the tooltip is posted.  This simplifies the code
and at the same time makes stuff more reliable in your case.

To make custom tooltips easier, perhaps its not a bad idea to have an overloadable
virtual inside FXListItem; this way subclassed FXLists can easily provide custom
tooltips.  The current SEL_QUERY_TIP will still be there as well, of course.


        Regards,

                                - Jeroen

P.S. Looking at your code, a small suggestion: more the initialization of
FXMessageChannel outside of Worker::run() since the thread operates asynchronously
with the main GUI thread.  FXMessageChannel calls FXApp::addInput() which should
not be called from another thread; this might cause stuff to be left in inconsistent
state, or possibly even crash things.



------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

mouse pointer has to move in the FXList before the chores are seen

by jasonheb - Skype™ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The example shows a case of broken chores. The mouse has to be moved to
get the chores to load items into the list.

Steps to reproduce:
1. run the attached cpp file (UTF-8)
2. run mouse pointer over the FXList

Actual results:
The FXList is filled with list items when the mouse is moved over the
list. If the mouse pointer is not moved over the FXList then nothing
happens.

Expected results:
The FXList would be filled with items without having to move the mouse.




[example.cpp]

#include <fx.h>

class Window : public FX::FXMainWindow {

    FXDECLARE(Window)
protected:
    Window() {
        ;
    }
public:
    FXList *m_list;
    enum {
        ID_CHORE = FXMainWindow::ID_LAST
    };
    Window(FXApp* a);
    long chore(FXObject* obj, FXSelector sel, void* ptr);

    virtual ~Window() {
        ;
    }

    virtual void create() {
        FXMainWindow::create();
        show(PLACEMENT_SCREEN);
    }
};

FXDEFMAP(Window) WindowMap[] = {
    FXMAPFUNC(SEL_CHORE, Window::ID_CHORE, Window::chore)
};

FXIMPLEMENT(Window, FX::FXMainWindow, WindowMap, ARRAYNUMBER(WindowMap))

Window::Window(FXApp* a) : FXMainWindow(a, "example", NULL, NULL, DECOR_TITLE | DECOR_MINIMIZE | DECOR_CLOSE | LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 800, 600) {
    m_list = new FXList(this, this, ID_CHORE, FX::LIST_BROWSESELECT | LAYOUT_FILL_Y | LAYOUT_FIX_WIDTH, 0, 0, 200, 0);
    m_list->setScrollStyle(VSCROLLER_ALWAYS | HSCROLLER_NEVER);

}

long Window::chore(FXObject* obj, FXSelector sel, void* ptr) {    
    FXString *string = *((FXString**) ptr);    
    m_list->insertItem((m_list->getNumItems()), *string);
    return 1;
}
Window *g_window;

class Worker : public FX::FXThread {
public:

    Worker() {
        ;
    }
    FXint run();
};

FXint Worker::run() {
    FXString *string;
    for (FXint i = 1; i <= 10000; i++) {
        string = new FXString(FXString::value(i) + " of 1000");
        while (g_window->getApp()->hasChore(g_window, Window::ID_CHORE)) {
            FXThread::yield();
        }
        g_window->getApp()->addChore(g_window, Window::ID_CHORE,&string);
        FXThread::sleep(100000000);
    }
}

int main(int argc, char *argv[]) {
    FXApp application("example", "example");
    application.init(argc, argv);
    g_window = new Window(&application);
    application.create();
    application.setToolTipPause(0);
    (new Worker)->start();
    return application.run();
}




------------------------------------------------------------------------------

_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: mouse pointer has to move in the FXList before the chores are seen

by Jeroen van der Zijp :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thursday 02 April 2009, Jason Heblack wrote:

> The example shows a case of broken chores. The mouse has to be moved to
> get the chores to load items into the list.
>
> Steps to reproduce:
> 1. run the attached cpp file (UTF-8)
> 2. run mouse pointer over the FXList
>
> Actual results:
> The FXList is filled with list items when the mouse is moved over the
> list. If the mouse pointer is not moved over the FXList then nothing
> happens.
>
> Expected results:
> The FXList would be filled with items without having to move the mouse.


Yes,

This is a "works as designed" thing.  To invoke things from the worker
thread to be executed in the main GUI thread, you will need to use FXMessageChannel.

EVENT SOURCES
=============

When the main GUI thread falls asleep in select(), it only wakes up when external
events happen that it is set up to watch.  These events can be: GUI events from
the X11 server or GDI, sockets and pipes you've added via addInput(), or signals
added with addSignal().  If none of these events are raised, the select() expires
and we execute any timers that are due.

Its important to realize that the main GUI thread will NOT be woken up by any other
means except those mentioned above!


MESSAGE CHANNEL IS AN EVENT SOURCE
==================================

FXMessageChannel is a convenience class which [behind the scenes] calls addInput()
so that an event source is registered with FXApp.  We use this to communicate
between a worker thread and the GUI thread; it allows us to send a message from
a worker thread, with the handler executing in the context of the main GUI thread.

FXMessageChannel was created as a separate object, so as to not burden single-threaded
applications with the need to have an extra event source (in this case, a pipe) around
all the time.


CHORES
======

Chores are only executed just before select() would be called, i.e. we have run
out of events to process and are about to block.  This makes chores pretty cheap
because they are only executed when nothing else would be going on anyway, at
least in our own application.


BOTH GUI AND WORKER THREAD CAN MANIPULATE DATA
==============================================

FOX API's are NOT thread safe (there are simply too many of them), but it has facilities
to allow worker threads and GUI to safely manipulate common data.

One of these is appMutex, accessible via app->mutex().  This mutex is locked whenever
the main GUI thread is executing ANY handler, and only released while the GUI thread is
sleeping.

This allows worker threads to SAFELY manipulate data structures which are
also manipulated by GUI messages, PROVIDED the worker thread first acquires
the appMutex.

Of course, you can [and should] perform more fine-grained locking if possible
so as to not block the GUI thread for extended periods of time.


========================================================================

Now, in your case, the correct way to set a chore from a worker thread is
to use FXMessageChannel.  The worker thread uses the FXMessageChannel::message()
API to cause a message to be passed from the worker to the main GUI thread.

The main GUI thread will be woken up, and dispatch to the proper handler,
which can then either set the chore you want or [perhaps better] invoke
the desired function directly.

Your previous version earlier this week was actually more correct....


A bit lengthy, but I hope it helps,

                                                - Jeroen








------------------------------------------------------------------------------
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

deserialization optimization in the main gui thread

by jasonheb - Skype™ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The code below from main gui thread (fox-1.7.17) measures the
deserialization time for an aggregate object. If there are more worker
threads in the background then the total time found is greater. Why
would the amount of worker threads in the background influence the time
measured in the main gui thread? When the worker threads are around, the
total time is about 500ms. When the workers have exited, the total time
is about 50ms or about 10 times less.

FXlong start,end;
FXfloat total;
start=FX::FXThread::time();              
fileIn.open(*s_stored[s_selected], FX::FXStreamLoad);
fileIn >> s_active[s_selected];
fileIn.close();
end=FX::FXThread::time();
total=(end-start)/1000000;
cout << "milliseconds: " << total << endl;

There is also always free memory reported as being available. At the
start it is about 84432 free. At the end it is about 16636 free.

Is round robin scheduling being applied to the main gui thread in
addition to the workers? The workers policy were all set to round robin.

Inside the deserialization load methods, all that is being loaded are
bools, ints, and strings or an image or an object that has those
members.

store >> m_url;  
store >> m_selected;
m_image = new FXJPGImage(getApp(), NULL);    
m_image->loadPixels(store);  




------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: deserialization optimization in the main gui thread

by Jeroen van der Zijp :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tuesday 07 April 2009, Jason Heblack wrote:

> The code below from main gui thread (fox-1.7.17) measures the
> deserialization time for an aggregate object. If there are more worker
> threads in the background then the total time found is greater. Why
> would the amount of worker threads in the background influence the time
> measured in the main gui thread? When the worker threads are around, the
> total time is about 500ms. When the workers have exited, the total time
> is about 50ms or about 10 times less.
>
> FXlong start,end;
> FXfloat total;
> start=FX::FXThread::time();              
> fileIn.open(*s_stored[s_selected], FX::FXStreamLoad);
> fileIn >> s_active[s_selected];
> fileIn.close();
> end=FX::FXThread::time();
> total=(end-start)/1000000;
> cout << "milliseconds: " << total << endl;
>
> There is also always free memory reported as being available. At the
> start it is about 84432 free. At the end it is about 16636 free.
>
> Is round robin scheduling being applied to the main gui thread in
> addition to the workers? The workers policy were all set to round robin.
>
> Inside the deserialization load methods, all that is being loaded are
> bools, ints, and strings or an image or an object that has those
> members.
>
> store >> m_url;  
> store >> m_selected;
> m_image = new FXJPGImage(getApp(), NULL);    
> m_image->loadPixels(store);  

Silly question: do you run this on a multi-core box?  

OK, assuming you answer the above in the affirmative, of course; otherwise
it'd be too easy ;-)

My suspicion is cache-thrashing, where the other threads cause cachelines
to be evicted and thus main memory gets hit more often than otherwise would
be the case.

You probably need to test this hypothesis with some cache-profiling tool...


                - Jeroen






--
+----------------------------------------------------------------------------+
| Copyright (C) 20:50 04/ 7/2009 Jeroen van der Zijp.   All Rights Reserved. |
+----------------------------------------------------------------------------+

------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Foxgui-users mailing list
Foxgui-users@...
https://lists.sourceforge.net/lists/listinfo/foxgui-users

Re: deserialization optimization in the main gui thread

by jasonheb - Skype™ :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


>Silly question: do you run this on a multi-core box?  
>
>OK, assuming you answer the above in the affirmative, of course; otherwise
>it'd be too easy ;-)
>
>My suspicion is cache-thrashing, where the other threads cause cachelines
>to be evicted and thus main memory gets hit more often than otherwise would
>be the case.
>
>You probably need to test this hypothesis with some cache-profiling tool...
>
>
> - Jeroen

Jeroen,

No. I use ccache and distcc on abandoned single-cpu computers taken from a successful business during an upgrade. I had bought an AMD 800mz single CPU for 4K one time except each of these free computers is faster than that. SunStudio12.1 is slower than distcc for single CPUs though.

Jason





--
+----------------------------------------------------------------------------+
| Copyright (C) 20:50 04/ 7/2009 Jeroen van der Zijp.   All Rights Reserved. |
+----------------------------------------------------------------------------+

------------------------------------------------------------------------------
This SF.net email is sponsored by:
High Quality Requirements in a Collaborative Environment.
Download a free trial of Rational Requirements Composer Now!
http://p.sf.net/sfu/www-ibm-com
_______________________________________________
Foxgui-users mailing list
Foxgui-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/foxgui-users