Created
January 19, 2015 01:55
-
-
Save spillz/20a5e0c789a5238254be to your computer and use it in GitHub Desktop.
GTK3 Conversion of Proportional Layout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from gi.repository import Gtk | |
| from gi.repository import Gdk | |
| from gi.repository import cairo | |
| from gi.repository import GObject | |
| class ProportionalLayoutChild: | |
| def __init__(self,widget,left,right,top,bottom): | |
| self.widget=widget | |
| self.left=left | |
| self.right=right | |
| self.top=top | |
| self.bottom=bottom | |
| self.eventbox = None | |
| self.hidden = False | |
| class ProportionalLayout(Gtk.Container): | |
| ''' | |
| An extension of Gtk.Container that supports sizing of children and positioning them | |
| in proportional (instead of pixel) terms | |
| ''' | |
| __gtype_name__ = 'ProportionalLayout' | |
| def __init__(self,*children): | |
| super(ProportionalLayout, self).__init__() | |
| self.set_has_window(False) | |
| self.children=[] | |
| for ch in children: | |
| self.add_with_bg(*ch) | |
| def do_get_request_mode(self): | |
| return(Gtk.SizeRequestMode.CONSTANT_SIZE) | |
| def do_get_preferred_height_for_width(self, width): | |
| needed_req = [0,0] | |
| for ch in self.children: | |
| req = ch.widget.get_preferred_height_for_width(width) | |
| try: | |
| req[0] = int(req[0]/(ch.top-ch.bottom)) | |
| except: | |
| pass | |
| try: | |
| req[1] = int(req[0]/(ch.top-ch.bottom)) | |
| except: | |
| pass | |
| for i in range(2): | |
| if needed_req[i]<req[i]: | |
| needed_req[i]=req[i] | |
| return tuple(needed_req) | |
| def do_get_preferred_width_for_height(self, height): | |
| needed_req = [0,0] | |
| for ch in self.children: | |
| req = ch.widget.get_preferred_width_for_height(height) | |
| try: | |
| req[0] = int(req[0]/(ch.right-ch.left)) | |
| except: | |
| pass | |
| try: | |
| req[1] = int(req[1]/(ch.right-ch.left)) | |
| except: | |
| pass | |
| for i in range(2): | |
| if needed_req[i]<req[i]: | |
| needed_req[i]=req[i] | |
| return tuple(needed_req) | |
| def do_get_preferred_width(self): | |
| ''' | |
| request the minimum size such that each child widget can fit within its specified proportions | |
| ''' | |
| needed_req = [0,0] | |
| for ch in self.children: | |
| req = ch.widget.get_preferred_width() | |
| try: | |
| req[0] = int(req[0]/(ch.right-ch.left)) | |
| except: | |
| pass | |
| try: | |
| req[1] = int(req[1]/(ch.right-ch.left)) | |
| except: | |
| pass | |
| for i in range(2): | |
| if needed_req[i]<req[i]: | |
| needed_req[i]=req[i] | |
| return tuple(needed_req) | |
| def do_get_preferred_height(self): | |
| ''' | |
| request the minimum size such that each child widget can fit within its specified proportions | |
| ''' | |
| needed_req = [0,0] | |
| for ch in self.children: | |
| req = ch.widget.get_preferred_width() | |
| try: | |
| req[0] = int(req[0]/(ch.top-ch.bottom)) | |
| except: | |
| pass | |
| try: | |
| req[1] = int(req[0]/(ch.top-ch.bottom)) | |
| except: | |
| pass | |
| for i in range(2): | |
| if needed_req[i]<req[i]: | |
| needed_req[i]=req[i] | |
| return tuple(needed_req) | |
| def do_size_allocate (self, allocation): | |
| n = len(self.children) | |
| al = allocation | |
| for ch in self.children: | |
| widget = ch.eventbox if ch.eventbox else ch.widget | |
| left = ch.left | |
| right = ch.right | |
| if left == right: #centered | |
| w, wn = widget.get_preferred_width() | |
| w = 0 | |
| left = int(al.x + left * al.width - w/2) | |
| elif left is not None and right is not None: | |
| w = int((right - left)*al.width) | |
| w = 0 | |
| left = int(al.x + left * al.width) | |
| elif left is not None: #align right | |
| w, wn = widget.get_preferred_width() | |
| w = 0 | |
| left = int(al.x + left * al.width) | |
| elif right is not None: #align left | |
| w, wn = widget.get_preferred_width() | |
| w = 0 | |
| left = int(al.x + right * al.width - w) | |
| top = ch.top | |
| bottom = ch.bottom | |
| if top == bottom: #centered | |
| h, hn = widget.get_preferred_height() | |
| h = 0 | |
| top = int(al.y + top * al.height - h/2) | |
| elif top is not None and bottom is not None: | |
| h = int((bottom - top)*al.height) | |
| h = 0 | |
| top = int(al.y + top * al.height) | |
| elif top is not None: #align bottom | |
| h, hn = widget.get_preferred_height() | |
| h = 0 | |
| top = int(al.y + top * al.height) | |
| elif bottom is not None: #align top | |
| h, hn = widget.get_preferred_height() | |
| h = 0 | |
| top = int(al.x + bottom *al.height - h) | |
| a=cairo.RectangleInt(left,top,w,h) | |
| widget.size_allocate(a) | |
| def do_remove(self,child): | |
| i=0 | |
| for ch in self.children: | |
| if ch.widget==child or ch.eventbox==child: | |
| if ch.eventbox: | |
| ch.eventbox.remove(ch.widget) | |
| ch.eventbox.unparent() | |
| else: | |
| ch.widget.unparent() | |
| del self.children[i] | |
| return | |
| i+=1 | |
| def add(self, widget, x_left, x_right, y_bottom, y_top): | |
| ch = ProportionalLayoutChild(widget, x_left, x_right, y_bottom, y_top) | |
| widget.set_parent(self) | |
| self.children.append(ch) | |
| self.queue_resize() | |
| def do_forall (self, include_internals, callback): | |
| try: | |
| for ch in self.children: | |
| if ch.eventbox: | |
| callback (ch.eventbox) | |
| else: | |
| callback (ch.widget) | |
| except AttributeError: | |
| print 'AttribError' | |
| GObject.type_register(ProportionalLayout) | |
| if __name__ == '__main__': | |
| proplayout = ProportionalLayout() | |
| proplayout.add(Gtk.Button('bottom-right'),0.5,1,0.5,1) | |
| box = Gtk.HBox() | |
| box.pack_start(Gtk.Button("test"), True, True, 0) | |
| box.pack_start(proplayout, True, True, 0) | |
| window = Gtk.Window () | |
| window.add(box) | |
| window.set_size_request(600,300) | |
| window.connect('destroy', lambda window: Gtk.main_quit ()) | |
| window.show_all() | |
| window.present () | |
| Gtk.main () | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Converted from the original pygtk 2.0 class here: https://github.com/spillz/picty/blob/master/modules/picty/uitools/overlay_widgets.py