Skip to content

Commit

Permalink
nodebox.gui layout fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom De Smedt committed Apr 24, 2012
1 parent 4e80ce2 commit e9f685c
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 18 deletions.
91 changes: 91 additions & 0 deletions examples/10-gui/05-layout.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Add the upper directory (where the nodebox module is) to the search path.
import os, sys; sys.path.insert(0, os.path.join("..",".."))

from nodebox.graphics import *
from nodebox.gui import *

# Comparison between Rows and Row containers.
# Both are subclasses of Layout.

# Panel 1
# Controls in a Rows layout are drawn below each other.
# Rows.width defines the width of all controls (individual width is ignored).
# Note how the second Field has a height and wrap=True,
# which makes it a multi-line field with text wrapping.
panel1 = Panel("Panel 1", x=30, y=350)
panel1.append(
Rows([
Field(value="", hint="subject"),
Field(value="", hint="message", height=70, id="field_msg1", wrap=True),
Button("Send"),
], width=200)
)
panel1.pack()

# Panel 2
# Controls in a Row layout are drawn next to each other.
# Row.width defines the width of all controls (individual width is ignored).
# This means that each column has the same width.
# Note the align=TOP, which vertically aligns each column at the top (default is CENTER).
panel2 = Panel("Panel 2", x=30, y=200)
panel2.append(
Row([
Field(value="", hint="message", height=70, id="field_msg2", wrap=True),
Button("Send", width=400),
], width=200, align=TOP)
)
panel2.pack()

# Panel 3
# If you need columns of a different width, put a Layout in a column,
# in other words a Row or Rows nested inside a Row or Rows.
# Then put your controls in the nested layout,
# the layout's width will override the column width setting.
panel3 = Panel("Panel 3", x=30, y=30)
panel3.append(
Row([ # Field will be 200 wide, the Row column width setting.
Field(value="", hint="message", height=70, id="field_msg2", wrap=True),
("Actions:", Rows([
Button("Send"), # However, buttons will be 100 wide,
Button("Save") # because their Rows parent says so.
], width=100))
], width=200, align=TOP)
)
panel3.pack()

# Panel 4
# Without layouts, you are free to draw controls wherever you want in a panel.
# Panel.pack() will make sure that the panel fits snuggly around the controls.
# In this case, we place a button on the panel, with a field above it (hence y=40).
# The field has its own dimensions (width=300 and height=50).
panel4 = Panel("Panel 4", x=400, y=30)
panel4.extend([
Field(value="", hint="message", y=40, width=300, height=50, id="field_msg3", wrap=True, reserved=[]),
Button("Send")
])
panel4.pack()

# Note the reserved=[] with the field.
# By default, fields have ENTER and TAB keys reserved:
# enter fires Field.on_action(), tab moves away from the field.
# By clearing the reserved list we can type enter and tab inside the field.

# Panel 5
# If you don't pack the panel, you have to set its width and height manually,
# as well as the position of all controls:
panel5 = Panel("Panel 5", x=500, y=200, width=200, height=150)
panel5.extend([
Field(value="", hint="message", x=10, y=60, width=180, height=50, id="field_msg3", wrap=True),
Button("Send", x=10, y=20, width=180)
])

def draw(canvas):
canvas.clear()

canvas.append(panel1)
canvas.append(panel2)
canvas.append(panel3)
canvas.append(panel4)
canvas.append(panel5)
canvas.size = 800, 600
canvas.run(draw)
34 changes: 16 additions & 18 deletions nodebox/gui/controls.py
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ def draw(self):
image(im7, 0, im4.height, height=self.height-im1.height-im4.height, color=clr)
image(im8, self.width-im8.width, im4.height, height=self.height-im2.height-im5.height, color=clr)
image(im9, im4.width, im6.height, width=self.width-im7.width-im8.width, height=self.height-im3.height-im6.height, color=clr)

def on_mouse_enter(self, mouse):
mouse.cursor = DEFAULT

Expand Down Expand Up @@ -1090,14 +1090,15 @@ def __getattr__(self, k):
def apply(self, spacing=0):
""" Adjusts the position and size of the controls to match the layout.
"""
pass
self.width = max(control.width for control in self)
self.height = max(control.height for control in self)

def __repr__(self):
return "Layout(type=%s)" % repr(self.__class__.__name__.lower())

# Debug mode:
#def draw(self):
# rect(0, 0, self.width, self.height, fill=None, stroke=(1,1,1,0.5), strokestyle="dotted")
# rect(0, 0, self.width, self.height, fill=None, stroke=(0,0.5,1,1))

#--- Layout: Labeled ----------------------------------------------------------------------------------

Expand Down Expand Up @@ -1159,28 +1160,25 @@ def apply(self, spacing=10):
# adjusting mw at the start will make controls wider to line out with the total width,
# adjusting it at the end would just ensure that the layout is wide enough.
mw = max(mw, control.width)
w1 = max([caption.width for caption in self.captions])
w2 = max([control.width for control in self.controls])
w1 = max(caption.width for caption in self.captions)
w2 = max(control.width for control in self.controls)
w2 = min(w2, mw)
dx = 0
dy = 0
for caption, control in reversed(zip(self.captions, self.controls)):
caption.x = dx + w1 - caption.width # halign right.
control.x = dx + w1 + (w1>0 and spacing)
caption.y = dy + 0.5 * (control.height - caption.height) # valign center.
control.y = dy
if isinstance(control, Layout) and control.height > caption.height * 2:
caption.y = dy + control.height - caption.height # valign top.
if isinstance(control, (Label, Button, Slider, Field)):
control._set_width(mw)
control._pack()
caption.x = dx + w1 - caption.width # halign right.
control.x = dx + w1 + (w1>0 and spacing)
caption.y = dy + 0.5 * (control.height - caption.height) # valign center.
control.y = dy
dy += max(caption.height, control.height, 10) + spacing
self.width = w1 + w2 + (w1>0 and spacing)
self.width = w1 + max(w2, mw) + (w1>0 and spacing)
self.height = dy - spacing

#def draw(self):
# rect(0, 0, self.width, self.height, fill=None, stroke=[1,1,1,1])

TOP, CENTER = "top", "center"

class Row(Labeled):
Expand All @@ -1201,18 +1199,18 @@ def apply(self, spacing=10):
"""
mw = self._maxwidth
da = self._align==TOP and 1.0 or 0.5
h1 = max([control.height for control in self.controls])
h2 = max([caption.height for caption in self.captions])
h1 = max(control.height for control in self.controls)
h2 = max(caption.height for caption in self.captions)
dx = 0
dy = 0
for caption, control in zip(self.captions, self.controls):
if isinstance(control, (Label, Button, Slider, Field)):
control._set_width(mw)
control._pack()
caption.x = dx + 0.5 * max(control.width - caption.width, 0) # halign center
control.x = dx + 0.5 * max(caption.width - control.width, 0) # halign center
caption.y = dy + h1 + (h2>0 and spacing)
control.y = dy + da * (h1 - control.height) # valign center
if isinstance(control, (Label, Button, Slider, Field)):
control._set_width(mw)
control._pack()
dx += max(caption.width, control.width, 10) + spacing
self.width = dx - spacing
self.height = h1 + h2 + (h2>0 and spacing)

0 comments on commit e9f685c

Please sign in to comment.