jdataview questions

Roby Steinmetzer's icon

Hi,

Concerning jdataview:

Based on the info in dbviewer I managed to build an object with the dataview stuff
but without the use of a database.

This was not really an easy task due to the cryptic comments in jdataview.h
and the fact that a lot of functions are not exported.

But I can now insert columns and rows with data and even edit the cells and grab the edited data.
Great.

Still some questions remain:

Is there a way to define a type (float, int, text, ...) for a column and thus restrict the input to this type
or do I have to handle this myself?
How is it done in the inspectors?

I thought maybe the values in the following enum could be helpful
but there's no info on what t_jcolumn field would want them?

enum {
    JCOLUMN_TEXT_ONESYMBOL = 1,
    JCOLUMN_TEXT_COMMASEPARATED = 2,
    JCOLUMN_TEXT_ICON = 4,
    JCOLUMN_TEXT_HASBUTTON = 8,
    JCOLUMN_TEXT_FILECHOOSEBUTTON = 16,
    JCOLUMN_TEXT_VIEWBUTTON = 32,
    JCOLUMN_TEXT_EDITBUTTON = 64,
    JCOLUMN_TEXT_TIME = 128,
    JCOLUMN_TEXT_FLOAT = 256,
    JCOLUMN_TEXT_INT = 512,
    JCOLUMN_TEXT_CANTEDIT = 1024,
    JCOLUMN_TEXT_FONTSIZE = 2048,
    // 4096 is JCOLUMN_DISABLED -- do not use
    JCOLUMN_TEXT_FILTERED = 8192
};

Other question:
At specific times I send myself the "getcelltext" message to my object in order to get the dataviewer to display the data:

Here is the method called by this message:

void mydataviewer_getcelltext(t_mydataviewer *x, t_symbol *colname, long index, char *text, long maxlen)
{
    char v[maxlen];
    t_atom *at;
    int column_index;
    t_jdataview *dv = (t_jdataview*)x->d_dataview;
    int numcols = dv->d_numcols;
    t_max_err err = hashtab_lookup(x->d_columns, colname, (t_object**)&column_index);
    if (!err)
    {
        int i = ((index-1) * numcols) + (int)column_index;

        at = x->data+i;
        if(at->a_type == 1)
            snprintf_zero(v, maxlen, "%ld", at->a_w.w_long);
        else if(at->a_type == 2)
            snprintf_zero(v, maxlen, "%f", at->a_w.w_float);
        else if(at->a_type == 3)
            snprintf_zero(v, maxlen, "%s", at->a_w.w_sym->s_name);

        strncpy_zero(text, v, maxlen);
    }
}

This works fine and the data gets displayed correctly but I get the following error in the Max window:
"missing arguments for message "getcelltext" ".
what would these arguments look like?

Any hints would be helpful.

Thanks so far,
Sherlock Roby

Timothy Place's icon

Hi Roby,

To answer the last question, there are two different methods you could use. For "getcelltext", here is the prototype we use in the file browser:

void filebrowser_getcelltext(t_filebrowser *x, t_symbol *colname, t_rowref rr, char *text, long maxlen)

If you are using numeric data and want to be able to sort the columns, then you'll want to use "getcellvalue", as in this prototype:

void filebrowser_getcellvalue(t_filebrowser *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv)

For your first question, you can define a "rowcomponent" message for your object to receive. Then, when you are setting up your columns, you tell whichever column it is to send you that message, i.e.

jcolumn_setrowcomponentmsg(col, gensym("rowcomponent"));

The rowcomponent method you define will then look something like the following, which is taken from the file browser's metadata editor window.

void metadataeditor_rowcomponent(t_metadataeditor *x, t_symbol *colname, t_rowref rr, long *comptype, long *options)
{
    *comptype = JCOLUMN_COMPONENT_TEXTEDITOR;
}

HTH

Roby Steinmetzer's icon

Hi Tim,

Thanks for the explanations, it makes things clearer.
So the options argument in the rowcomponent method is the interesting part.
I played a little around with the enums and I can see some potential.

One quick question:
If I set the options to JCOLUMN_TEXT_CANTEDIT I obviously can't edit the columns cell items.
However, what if I would like to be able to edit the cells except he first 2 ones?
I suppose this is possible as it works like that in the File Preferences window.

Thanks for any help so far, more questions will come...
Roby

Timothy Place's icon

Hi Roby,

You can do a test for in the rowcomponent method to see what the column name (colname in my example) is. Then based on that you set the comptype to whatever you want for that row (defined by the rowref) and column.

Cheers

Roby Steinmetzer's icon

Thanks Tim,
After thinking about it I guess I should have found this myself ;-)

Alas concerning the next question...

Let's say I need a column with float values.
So I set up my column with something like:

*comptype = JCOLUMN_COMPONENT_TEXTEDITOR;*options = JCOLUMN_TEXT_FLOAT;

I define a message msg for

void jcolumn_setvaluemsg(t_object *col, t_symbol *msg, t_symbol *beginmsg, t_symbol *endmsg);

This message msg calls a method

void mydataviewer_cellchanged(t_mydataviewer *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv)

whenever I scroll with the mouse in the cell defined by colname and rr.
The changed new value is in t_atom *argv , I can see it with

post("%f", argv->a_w.w_float);

But I can't see the visual update of the value in the cell.

However I get this visual update in the cell if I modify the value with [doubleclick in the cell -> type some value -> enter].
This seems to be handled by

void mydataviewer_getcelltext(t_mydataviewer *x, t_symbol *colname, long index, char *text, long maxlen)

where I pass the modified value (received by mydataviewer_cellchanged) to char *text.

When I change the value by mouse scrolling, the method

void mydataviewer_getcellvalue(t_mydataviewer *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv)

gets called.
I would have thought that passing the value to t_atom *argv would make it to be displayed, but that's not the case.

So obviously I'm doing something wrong...

Thanks for any hints,
Roby

Timothy Place's icon

In your rowcomponent method, you are correct to do something like:

*comptype = JCOLUMN_COMPONENT_TEXTEDITOR;
*options = JCOLUMN_TEXT_FLOAT;

You are also correct to watch for the value to change in a setvaluemsg.

Just to make sure -- In that setvaluemsg method, are you assigning the new value to whatever data-storage it is that you are using to back the dataview? It should be that you store the value in setvaluemsg, and then when getcellvalue or getcelltext are called, they will recall this value and update the display.

If I'm not making sense please let me know...

best,
Tim

Roby Steinmetzer's icon

Hm, what do you mean by "store the value in setvaluemsg" ?

Here's what I'm doing:

In my column setup method:jcolumn_setvaluemsg((t_object*)jcol, gensym("cellchanged"), gensym("msg2"), gensym("msg3"));

In main:class_addmethod(c, (method)mydataviewer_cellchanged, "cellchanged", A_CANT, 0);

Now when I modify the data in the dataview the method mydataviewer_cellchanged gets called
and the new value is in argv.
I fetch it from there and store it in an atom array x->data inside my object as I don't use a database.

void mydataviewer_cellchanged(t_mydataviewer *x, t_symbol *colname, t_rowref rr, long *argc, t_atom *argv)
{
    long column_index;
    long numcols = x->howmanycolumns;
    t_max_err err = hashtab_lookup(x->d_columns, colname, (t_object**)&column_index);
    long pos = (((long)rr-1) * numcols) + (long)column_index;

    if (argv->a_type == 2)
            SETFLOAT(x->data+pos, argv->a_w.w_float);
}

Roby

Timothy Place's icon

Okay -- assuming your pointers are all correct, then it sounds like you are doing the correct thing. So I'm not sure what's going on, as that should work...

Roby Steinmetzer's icon

Thanks for confirming, Tim.
I'm going to investigate.

have a nice day,
Roby

Roby Steinmetzer's icon

I finally found some time to look into this.

In order for the float text cells to visually update the display while mousing I had to add the following code to the mydataviewer_cellchanged method:
jdataview_redrawcell((t_object*)dv, colname, rr);

Works fine now,
Roby