sleepynate
sleepynate

Reputation: 8036

Center fixed-size GtkDrawingArea widget inside of parent widget

I've got a glade layout going, and in it I have a fixed-size GtkDrawingArea. The current relevant part of the hierarchy is:

GtkWindow > GtkVBox > GtkHPaned > GtkViewport > GtkAlignment > GtkFixed > GtkDrawingArea

Currently, the GtkFixed widget draws at the top-left corner of the GtkViewport.

However, I'd really like it if the GtkFixed (and thus its only child, the GtkDrawingArea) were centered within GtkViewport (except, of course, when the widget is compressed to the point where it doesn't fit its contents and the scrollbars appear).

What's the best way to accomplish this? (I'm using pygtk to do actual application logic, but this should be a general gtk question)

Here is a representative code sample:

import gtk

class Controller:

    def on_window1_destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        self.builder = gtk.Builder()
        self.builder.add_from_file("sample.glade")
        self.window = self.builder.get_object("window1")
        self.builder.connect_signals(self)

    def on_drawingarea1_expose_event(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_source_rgb(0,0,0)
        cr.paint()
        return True

if __name__ == "__main__":
    client = Controller()
    client.window.show()
    gtk.main()

And a sample glade file with the same issue:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <signal name="destroy" handler="on_window1_destroy"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <child>
          <object class="GtkHPaned" id="hpaned1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <child>
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="label" translatable="yes">label</property>
              </object>
              <packing>
                <property name="resize">False</property>
                <property name="shrink">True</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow" id="scrolledwindow1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="hscrollbar_policy">automatic</property>
                <property name="vscrollbar_policy">automatic</property>
                <child>
                  <object class="GtkAlignment" id="alignment1">
                    <property name="visible">True</property>
                    <child>
                      <object class="GtkFixed" id="fixed1">
                        <property name="width_request">300</property>
                        <property name="height_request">300</property>
                        <property name="visible">True</property>
                        <child>
                          <object class="GtkDrawingArea" id="drawingarea1">
                            <property name="width_request">300</property>
                            <property name="height_request">300</property>
                            <property name="visible">True</property>
                            <signal name="expose_event" handler="on_drawingarea1_expose_event"/>
                          </object>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="resize">True</property>
                <property name="shrink">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="position">0</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

And lastly... a sample image of the issue... Screeshot @ imgur

Upvotes: 2

Views: 1617

Answers (2)

Havoc P
Havoc P

Reputation: 8467

In GTK 2.x add a GtkAlignment as the parent of whatever you want to center and align 0.5 (disable fill).

In 3.x, there are xalign and yalign properties on all widgets, set to CENTER.

Update: from the sample glade file, the issue is that fill isn't disabled; I was too lazy to look up what the properties were called earlier, in GtkAlignment this is xscale=0.0 yscale=0.0, which means don't expand the child to fill available space. The default xscale=1.0 yscale=1.0 means the child will fill the available space and thus centering does not do anything.

In the sample Glade file I also had to do "add parent -> viewport" to add a viewport between the scrolled window and the alignment. You should have a warning on the console about this.

Upvotes: 7

markuz
markuz

Reputation: 919

Fixed will use all space available, what you need here is to catch the resize event on one of the parents, either the viewport or the Fixed, my guess is that Viewport will work better, then, get the size of the Fixed, and move it's child according tho the size of the child and the size of the fixed.

You can do this either with the Viewport, getting child widgets, or from the DrawingArea, getting parents.

Upvotes: 0

Related Questions