ScrolledWindow, DrawingArea, and setting step-increment



Hi! I hope this is the right place to ask this question.

I'm developing a MUD client in Pike, using GTK2 for the UI, and
there's an aspect of scrolling that's bugging me. The display uses
discrete lines of text of a fixed height (or, to be more technically
accurate, a fixed distance from the start of one line to the start of
the next), and I'd really like the scrolling to be done in lines
rather than pixels. Scrolling by "two and a bit lines" is ugly; I'd
rather scroll by exactly one line, or exactly three lines, or
something of the sort.

The full application can be found at https://github.com/Rosuav/Gypsum/
but here's a cut-down demo of what I'm talking about:

-- cut --

array colors=({ }),lines=({ });
GTK2.Adjustment scr;
GTK2.DrawingArea display;
int lineheight;

void scrchange()
{
    scr->set_value(scr->get_property("upper")-scr->get_property("page size"));
    werror("step-increment: %O\n",scr->get_property("step-increment"));
}

int paint(object self,object ev)
{
    int start=ev->y-lineheight,end=ev->y+ev->height+lineheight;
    GTK2.GdkGC gc=GTK2.GdkGC(display);
    int y=(int)scr->get_property("page size");
    foreach (lines,array line)
    {
        if (y>=start && y<=end)
        {
            gc->set_foreground(line[0]);
            display->draw_text(gc,3,y,line[1]);
        }
        y+=lineheight;
    }
}

int main()
{
    GTK2.setup_gtk();
    foreach ("000000 0000FF 00FF00 00FFFF FF0000 FF00FF FFFF00
FFFFFF"/" ",string col)
colors+=({GTK2.GdkColor(@array_sscanf(col,"%2x%2x%2x"))});
    GTK2.Window
mainwindow=GTK2.Window(GTK2.WindowToplevel)->set_title("Gypsum
Mini")->set_default_size(800,500);
    
mainwindow->add(GTK2.ScrolledWindow((["hadjustment":GTK2.Adjustment(),"vadjustment":scr=GTK2.Adjustment()]))
        ->add(display=GTK2.DrawingArea())
    )->show_all();
    display->modify_font(GTK2.PangoFontDescription("Monospace 12"));
    lineheight=display->create_pango_layout("asdf")->index_to_pos(3)->height/1024;
    mainwindow->signal_connect("delete_event",lambda() {exit(0);});
    scr->signal_connect("changed",scrchange);
    display->signal_connect("expose_event",paint);
    for (int i=0;i<1000;++i) lines+=({({random(colors[1..]),"Hello,
world! "+i})});
    display->set_size_request(-1,(int)scr->get_property("page
size")+lineheight*(sizeof(lines)+1));
    display->set_background(colors[0]);
    display->queue_draw();
    return -1;
}

-- cut --

Unfortunately, you probably don't have a Pike interpreter installed,
so this might well not work for you :( It works with the current
stable Windows build from
http://pike.lysator.liu.se/download/pub/pike/latest-stable/ and I've
been developing it using the current build of Pike on Linux. But
hopefully you'll be able to see what's going on despite the language
issues. If it's a problem, I could try porting the above code to
Python - would that help?

What I'd like to do is set the step-increment to be the calculated
lineheight. Unfortunately this doesn't work; the Adjustment
automatically resets its increments based on the height of the display
- as can be seen (if you can run the script) by resizing the window.
Is there a way to force it to use a particular value?

This code is, I believe, using gtk_scrolled_window_add_with_viewport
under the covers. Using an explicit Viewport doesn't seem to change
anything, and I can't see any events going through that would suggest
a point at which I could change the adjustment's increments.

Does anyone have any example code (in any language - I'm at least
passably fluent in Perl, C, C++, and Python, among others, and will be
happy to figure out code in a language I'm not familiar with) that
forces the increments? I've been searching on Google and have come up
with a few bits and bobs, but most work with DrawingArea seems to be
pixel-based, not line-based, so there's no problem with scrolling by
pixels.

Thanks in advance!

Chris Angelico


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]