How to disable horizontal scrollbar in Fl_Table_Row? [and Fl_Text_Display]

192 vues
Accéder directement au premier message non lu

Duncan Gibson

non lue,
3 janv. 2017, 04:06:1903/01/2017
à fltkg...@googlegroups.com
Happy New Year, FLTK fans :-)

I'm working with a complex data file format (ISO-10303 Part21 if
that helps) that basically consists of records of the form

#number = RECORD_TYPE(n,n.n,'text',#number,(#number,#number))

where the attribute fields can be integers, reals, single-quoted
strings, #number references to other records, and comma-separated
lists of any of these surrounded by parentheses, as shown above.

The file format is very hard to navigate, especially once you get
up to lists with hundreds of items, so I decided to write a tool
to navigate these records, using FLTK naturally.

The problem is that simply displaying a #number in a labelled box
doesn't really help much, so I've taken to using tables with some
summary information. For a single #number record, pointing to a
date/time for example, I have:

+=====+==============================+
| #Id | Date / Time |
+-----+------------------------------+
| #21 | 2017-01-02 / 09:20:25.1 |
+=====+==============================+

Clicking on the row brings up a dialog with complete details if
more information is required.

The problem I have is for lists of #number records. I only have
limited vertical space, so what I want is to display 3 rows and
have the vertical scrollbar triggered automatically. The tables
are already wide enough to show the record summaries with plenty
of space to spare, and therefore what I want to achieve is:

+=====+==============================+
| #Id | Date / Time |^|
+-----+----------------------------+-+
| #21 | 2017-01-02 / 09:20:25.1 |#|
+-----+----------------------------+ +
| #25 | 2017-04-11 / 09:32:02.5 | |
+-+---+----------------------------+-+
| #37 | 2018-11-23 / 17:01:53.4 |V|
+=+===+============================+=+

The vertical scrollbar to be shown automatically, as expected.
However, triggering the vertical scrollbar cuts the horizontal
display area, so the horizontal scrollbar is triggered as well,
and this takes up one of the precious rows:

+=====+==============================+
| #Id | Date / Time |^|
+-----+----------------------------+-+
| #21 | 2017-01-02 / 09:20:25.1 |#|
+-----+----------------------------+ +
| #25 | 2017-01-02 / 09:32:02.5 |V|
+-+---+----------------------------+-+
|<|################### |>| |
+=+===+============================+=+

I could reduce the width of the second column but that will
leave a grey area when the vertical scrollbar is not shown.

So my question: is there a simple way to disable the display of
the horizontal scrollbar, or do I have to derive my own Table
and implement/override the scrollbar behaviour?

Cheers
Duncan

PS. I have a similar issue with some Fl_Text_Display boxes
of limited height showing lists of plain old text strings.
The box is more than wide enough for the strings, so I don't
need the horizontal scroll bar which eats into the height.

This message and any attachments are intended for the use of the addressee or addressees only.
The unauthorised disclosure, use, dissemination or copying (either in whole or in part) of its
content is not permitted.
If you received this message in error, please notify the sender and delete it from your system.
Emails can be altered and their integrity cannot be guaranteed by the sender.

Please consider the environment before printing this email.


Greg Ercolano

non lue,
3 janv. 2017, 13:46:4003/01/2017
à fltkg...@googlegroups.com
On 01/03/17 01:06, Duncan Gibson wrote:
> The vertical scrollbar to be shown automatically, as expected.
> However, triggering the vertical scrollbar cuts the horizontal
> display area, so the horizontal scrollbar is triggered as well,
> and this takes up one of the precious rows:
>
> +=====+==============================+
> | #Id | Date / Time |^|
> +-----+----------------------------+-+
> | #21 | 2017-01-02 / 09:20:25.1 |#|
> +-----+----------------------------+ +
> | #25 | 2017-01-02 / 09:32:02.5 |V|
> +-+---+----------------------------+-+
> |<|################### |>| |
> +=+===+============================+=+
>
> I could reduce the width of the second column but that will
> leave a grey area when the vertical scrollbar is not shown.
>
> So my question: is there a simple way to disable the display of
> the horizontal scrollbar, or do I have to derive my own Table
> and implement/override the scrollbar behaviour?

The horizontal scrollbar should only be triggered if a column
goes beyond the screen, so if you can always keep that right
column sized to precisely fit the inner edge of the widget,
the horizontal scrollbar won't appear.

Unfortunately you can't just hide() the Fl_Table::hscroll;
hiding it causes the scrollbar not to appear, but the table
still leaves space for it as if it were there.

I need to check that, as I can't think why it shouldn't realize
the scrollbar is disabled, and not leave room for it.

Still, if that worked, you'd probably still have the problem of
your data being clipped when the vertical scrollbar appears,
which wouldn't be good either.

The better thing to do would be to either resize the table larger
when the vertical scrollbar appears to leave room for it, or keep
the table size fixed and just leave room for the vertical scrollbar,
resizing the right-most column to exactly fit to the edge of the window.

I'd start by implementing your method that adds new rows to the table,
doing checks there after the row is added to see if the table's
size needs the vertical scrollbar, and if so, trigger the above behavior.

If the user can also change the size of the window, then override
resize() too, so that the above logic can be called.

Greg Ercolano

non lue,
3 janv. 2017, 14:20:0303/01/2017
à fltkg...@googlegroups.com
On 01/03/17 10:46, Greg Ercolano wrote:
> On 01/03/17 01:06, Duncan Gibson wrote:
>> The vertical scrollbar to be shown automatically, as expected.
>> However, triggering the vertical scrollbar cuts the horizontal
>> display area, so the horizontal scrollbar is triggered as well,
>> and this takes up one of the precious rows:
>>
>> +=====+==============================+
>> | #Id | Date / Time |^|
>> +-----+----------------------------+-+
>> | #21 | 2017-01-02 / 09:20:25.1 |#|
>> +-----+----------------------------+ +
>> | #25 | 2017-01-02 / 09:32:02.5 |V|
>> +-+---+----------------------------+-+
>> |<|################### |>| |
>> +=+===+============================+=+
>>
>> I could reduce the width of the second column but that will
>> leave a grey area when the vertical scrollbar is not shown.
>>
>> So my question: is there a simple way to disable the display of
>> the horizontal scrollbar, or do I have to derive my own Table
>> and implement/override the scrollbar behaviour?
>
> [..]
> I'd start by implementing your method that adds new rows to the table,
> doing checks there after the row is added to see if the table's
> size needs the vertical scrollbar, and if so, trigger the above behavior.
>
> If the user can also change the size of the window, then override
> resize() too, so that the above logic can be called.


Here's an example that should look a lot like what you described.

The horizontal scrollbar shouldn't appear when the window is resized
or rows added/removed, esp. when the vert scroll appears/disappears.

This is just a modified version of the fltk examples/simple-table.cxx
code. The real work is done by the FixColumnSize() method, just a few
lines of added code:


#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Table.H>
#include <FL/fl_draw.H>

// Demonstrate resizing right column to fit window to avoid horiz scrollbar appearance
// erco 01/03/17

// Derive a class from Fl_Table
class MyTable : public Fl_Table {

// Draw the row/col headings
// Make this a dark thin upbox with the text inside.
//
void DrawHeader(const char *s, int X, int Y, int W, int H) {
fl_push_clip(X,Y,W,H);
fl_draw_box(FL_THIN_UP_BOX, X,Y,W,H, row_header_color());
fl_color(FL_BLACK);
fl_draw(s, X,Y,W,H, FL_ALIGN_LEFT);
fl_pop_clip();
}
// Draw the cell data
// Dark gray text on white background with subtle border
//
void DrawData(const char *s, int X, int Y, int W, int H) {
fl_push_clip(X,Y,W,H);
// Draw cell bg
fl_color(FL_WHITE); fl_rectf(X,Y,W,H);
// Draw cell data
fl_color(FL_GRAY0); fl_draw(s, X,Y,W,H, FL_ALIGN_LEFT);
// Draw box border
fl_color(color()); fl_rect(X,Y,W,H);
fl_pop_clip();
}
// Handle drawing table's cells
// Fl_Table calls this function to draw each visible cell in the table.
// It's up to us to use FLTK's drawing functions to draw the cells the way we want.
//
void draw_cell(TableContext context, int ROW=0, int COL=0, int X=0, int Y=0, int W=0, int H=0) {
static char s[40];
switch ( context ) {
case CONTEXT_STARTPAGE: // before page is drawn..
fl_font(FL_HELVETICA, 16); // set the font for our drawing operations
return;
case CONTEXT_COL_HEADER: // Draw column headers
switch(COL) {
case 0: DrawHeader(" #Id",X,Y,W,H); break;
case 1: DrawHeader(" Date / Time",X,Y,W,H); break;
}
return;
case CONTEXT_ROW_HEADER: // Draw row headers
return;
case CONTEXT_CELL: // Draw data in cells
switch(COL) {
case 0: sprintf(s, " #%d", ROW); DrawData(s,X,Y,W,H); break;
case 1: sprintf(s, " 2017-01-02 / 09:20:25.%d", ROW); DrawData(s,X,Y,W,H); break;
}
return;
default:
return;
}
}
public:
// Constructor
// Make our data array, and initialize the table options.
//
MyTable(int X, int Y, int W, int H, const char *L=0) : Fl_Table(X,Y,W,H,L) {
// Rows
rows(10); // how many rows
row_header(0); // disable row headers (along left)
row_height_all(20); // default height of rows
row_resize(0); // disable interactive row resizing
// Cols
cols(2); // how many columns
col_header(1); // enable column headers (along top)
col_width(0, 50); // fixed width for left column
col_width(1, 300); // fixed width for right column (changed later by FixColumnSize()..)
col_resize(0); // disable interactive column resizing
end(); // end the Fl_Table group
FixColumnSize(); // apply our auto-column-sizing behavior
}
~MyTable() { }

// Fix the right column's size to precisely match width of window
void FixColumnSize() {
int X,Y,W,H;
find_cell(CONTEXT_CELL,0,1,X,Y,W,H); // get xywh of right column cell in first row
int off = (X+W) - (tox+tow); // we just need X pos and width. Compute offset from table's outer size
int oldw = col_width(1); // save old col width
col_width(1, oldw - off); // set new column width based on offset for perfect fit
}

// Handle window resizing
void resize(int X,int Y,int W,int H) {
Fl_Table::resize(X,Y,W,H);
FixColumnSize(); // after letting window resize, fix our right most column
}
};

// Add more rows
void More_CB(Fl_Widget *w, void *d) {
MyTable *table = (MyTable*)d;
table->rows(table->rows()+1);
table->FixColumnSize();
}

// Remove rows
void Less_CB(Fl_Widget *w, void *d) {
MyTable *table = (MyTable*)d;
if ( table->rows() > 1 ) table->rows(table->rows()-1);
table->FixColumnSize();
}

int main(int argc, char **argv) {
Fl_Double_Window *win = new Fl_Double_Window(500, 400, "Simple Table");
MyTable *table = new MyTable(10,10,win->w()-20,340);
Fl_Button more(10, 360,100,25,"+ Row"); more.callback(More_CB, (void*)table);
Fl_Button less(220,360,100,25,"- Row"); less.callback(Less_CB, (void*)table);
win->end();
win->resizable(table);
win->show(argc,argv);
return(Fl::run());
}

Duncan Gibson

non lue,
4 janv. 2017, 03:56:3204/01/2017
à fltkg...@googlegroups.com
Greg wrote:
> This is just a modified version of the fltk
> examples/simple-table.cxx code. The real work is done by the
> FixColumnSize() method, just a few lines of added code:
> [code elided]

Thanks Greg, lateral thinking like this would have taken me ages.

When you add/remove rows in the More and Less callbacks, you
also call FixColumnSize(), which might be slow for a table with
hundreds of rows, almost all of which will be hidden.

Is there any implementation reason why I couldn't instead have:

// virtual
void MyTable::draw() {
FixColumnSize();
Fl_Table::draw();
}

Cheers
D.

Duncan Gibson

non lue,
5 janv. 2017, 03:14:0005/01/2017
à fltkg...@googlegroups.com
I wrote:
> Is there any implementation reason why I couldn't instead have:
>
> // virtual
> void MyTable::draw() {
> FixColumnSize();
> Fl_Table::draw();
> }

I added this into my table base class last night, had to add

if (rows() == 0) return;

to FixColumnSize() and then it worked like a charm across all
of the tables with more than 3 rows that I looked at.

Thanks
Répondre à tous
Répondre à l'auteur
Transférer
0 nouveau message