Skip to content

Commit 4e80ce2

Browse files
author
Tom De Smedt
committed
nodebox.gui Field has adjustable height
1 parent 970fe7a commit 4e80ce2

File tree

4 files changed

+46
-23
lines changed

4 files changed

+46
-23
lines changed

examples/05-path/01-curve.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
# The resulting path can be passed to drawpath() to render it to the canvas.
2727
# Note: just as in the classic NodeBox for Mac OS X, paths can also be constructed
28-
# with beginpath(). The commands below create exactlye the same leaf shape as above:
28+
# with beginpath(). The commands below create exactly the same leaf shape as above:
2929
# beginpath(0, 0)
3030
# curveto(50, 50, 0, 150, 0, 200)
3131
# curveto(0, 150, -50, 50, 0, 0)

examples/10-gui/04-knob.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# It arranges all of its controls horizontally, with their captions on top.
1212
# The Row layout can then be nested in a Rows layout (or vice versa).
1313
# This allows you to build many different interface grids.
14-
panel = Panel("Example", width=200, height=200, fixed=False, modal=False)
14+
panel = Panel("Example", width=300, height=200, fixed=False, modal=False)
1515
panel.append(Rows(
1616
[("text",Field(value="hello world", hint="text", id="field_text")),
1717
( "size", Slider(default=1.0, min=0.0, max=2.0, steps=100, id="slider_size")),

nodebox/gui/controls.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def fontweight(self):
238238
def _pack(self):
239239
# Center the text inside the label.
240240
self._text.x = 0.5 * (self.width - self._text.metrics[0])
241-
self._text.y = 0.5 * (self.height - self._text.metrics[1])
241+
self._text.y = 0.5 * (self.height - self._text.metrics[1])
242242

243243
def draw(self):
244244
self._text.draw()
@@ -542,7 +542,7 @@ def on_mouse_release(self, mouse):
542542

543543
class Editable(Control):
544544

545-
def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap=True, id=None, **kwargs):
545+
def __init__(self, value="", x=0, y=0, width=125, height=20, padding=(0,0), wrap=False, id=None, **kwargs):
546546
""" An editable text box.
547547
When clicked, it has the focus and can receive keyboard events.
548548
With wrap=True, several lines of text will wrap around the width.
@@ -553,7 +553,7 @@ def __init__(self, value="", x=0, y=0, width=125, height=30, padding=(0,0), wrap
553553
"font" : _popdefault(kwargs, "font", theme["fontname"]),
554554
"fontsize" : _popdefault(kwargs, "fontsize", theme["fontsize"]),
555555
"fontweight" : _popdefault(kwargs, "fontweight", theme["fontweight"]),
556-
"lineheight" : _popdefault(kwargs, "lineheight", 1),
556+
"lineheight" : _popdefault(kwargs, "lineheight", wrap and 1.25 or 1.0),
557557
"align" : LEFT
558558
})
559559
kwargs["width"] = width
@@ -690,8 +690,8 @@ def on_key_press(self, keys):
690690
y = keys.code == UP and -1 or +1
691691
n = self._editor.get_line_count()
692692
i = self._editor.get_position_on_line(
693-
max(self._editor.get_line_from_position(i)+y, 0),
694-
self._editor.get_point_from_position(i)[0])
693+
min(max(self._editor.get_line_from_position(i)+y, 0), n-1),
694+
self._editor.get_point_from_position(i)[0])
695695
self._editor.caret.position = i
696696
elif keys.code == TAB and TAB in self.reserved:
697697
# The tab key navigates away from the control.
@@ -732,12 +732,18 @@ def __init__(self, value="", hint="", action=None, x=0, y=0, width=125, padding=
732732
""" A single-line text input field.
733733
The string value can be retrieved with Field.value.
734734
"""
735-
Editable.__init__(self, value, x=x, y=y, width=width, padding=(padding,0), wrap=False, id=id, **kwargs)
735+
Editable.__init__(self, value, x=x, y=y, width=width, padding=[padding]*2, id=id, **kwargs)
736736
img, w = Image(theme["field"]), 10
737737
self.src = {
738-
"face" : crop(img, w, 0, 1, img.height),
739-
"cap1" : crop(img, 0, 0, w, img.height),
740-
"cap2" : crop(img, img.width-w, 0, w, img.height),
738+
"cap1" : crop(img, 0, img.height-w, w, w),
739+
"cap2" : crop(img, img.width-w, img.height-w, w, w),
740+
"cap3" : crop(img, 0, 0, w, w),
741+
"cap4" : crop(img, img.width-w, 0, w, w),
742+
"top" : crop(img, w+1, img.height-w, 1, w),
743+
"bottom" : crop(img, w+1, 0, 1, w),
744+
"left" : crop(img, 0, w+1, w, 1),
745+
"right" : crop(img, img.width-w, w+1, w, 1),
746+
"face" : crop(img, w+1, w+1, 1, 1)
741747
}
742748
if action:
743749
# Override the Button.on_action() method from the given function.
@@ -759,11 +765,15 @@ def reset(self):
759765
def _pack(self):
760766
Editable._pack(self)
761767
w = max(self.width, self.src["cap1"].width + self.src["cap2"].width)
768+
h = max(self.height, self.src["cap1"].width + self.src["cap3"].width)
769+
h = max(h, int(self._editor.document.get_style("line_spacing") * 1.5 + self._padding[1] * 2))
762770
self._set_width(w)
763-
self._set_height(self.src["face"].height)
764-
# Position the hint text (if no other text is in the field):
771+
self._set_height(h)
772+
# Position the hint text (if no other text is in the field).
773+
# The hint will not span multiple line if it is wider than the field
774+
# (it was designed to be a short word or phrase).
765775
self[0].x = self._padding[0]
766-
self[0]._set_height(self.height)
776+
self[0].y = self.height - self._padding[1] - self[0]._text.metrics[1] * 1.25
767777
self[0]._pack()
768778

769779
def on_action(self):
@@ -773,11 +783,19 @@ def update(self):
773783
self[0].hidden = self.editing or self.value != ""
774784

775785
def draw(self):
786+
im1, im2, im3 = self.src["cap1"], self.src["cap2"], self.src["top"]
787+
im4, im5, im6 = self.src["cap3"], self.src["cap4"], self.src["bottom"]
788+
im7, im8, im9 = self.src["left"], self.src["right"], self.src["face"]
776789
clr = self.color
777-
im1, im2, im3 = self.src["cap1"], self.src["cap2"], self.src["face"]
778-
image(im1, 0, 0, height=self.height, color=clr)
779-
image(im2, x=self.width-im2.width, height=self.height, color=clr)
780-
image(im3, x=im1.width, width=self.width-im1.width-im2.width, height=self.height, color=clr)
790+
image(im1, 0, self.height-im1.height, color=clr)
791+
image(im2, self.width-im2.width, self.height-im2.height, color=clr)
792+
image(im3, im1.width, self.height-im3.height, width=self.width-im1.width-im2.width, color=clr)
793+
image(im4, 0, 0, color=clr)
794+
image(im5, self.width-im5.width, 0, color=clr)
795+
image(im6, im4.width, 0, width=self.width-im4.width-im5.width, color=clr)
796+
image(im7, 0, im4.height, height=self.height-im1.height-im4.height, color=clr)
797+
image(im8, self.width-im8.width, im4.height, height=self.height-im2.height-im5.height, color=clr)
798+
image(im9, im4.width, im6.height, width=self.width-im7.width-im8.width, height=self.height-im3.height-im6.height, color=clr)
781799
Editable.draw(self)
782800

783801
#=====================================================================================================
@@ -986,7 +1004,7 @@ def close(self):
9861004

9871005
class Dock(Panel):
9881006

989-
def __init__(self, anchor=LEFT, caption="", fixed=True, modal=True, **kwargs):
1007+
def __init__(self, caption="", anchor=LEFT, fixed=True, modal=True, **kwargs):
9901008
""" A panel attached to the edge of the canvas (LEFT or RIGHT), extending the full height.
9911009
With fixed=False, it can be snapped from the edge and dragged as a normal panel.
9921010
"""
@@ -1028,7 +1046,7 @@ def draw(self):
10281046

10291047
class Layout(Layer):
10301048

1031-
def __init__(self, x=0, y=0, **kwargs):
1049+
def __init__(self, controls=[], x=0, y=0, **kwargs):
10321050
""" A group of controls with a specific layout.
10331051
Controls can be added with Layout.append().
10341052
The layout will be applied when Layout.apply() is called.
@@ -1038,6 +1056,7 @@ def __init__(self, x=0, y=0, **kwargs):
10381056
kwargs["height"] = 0
10391057
Layer.__init__(self, x=x, y=y, **kwargs)
10401058
self._controls = {} # Lazy cache of (id, control)-children, see nested().
1059+
self.extend(controls)
10411060

10421061
def insert(self, i, control):
10431062
if isinstance(control, Layout):
@@ -1087,7 +1106,7 @@ class Labeled(Layout):
10871106
def __init__(self, controls=[], x=0, y=0, **kwargs):
10881107
""" A layout where each control has an associated text label.
10891108
"""
1090-
Layout.__init__(self, x=x, y=y, **kwargs)
1109+
Layout.__init__(self, controls=[], x=x, y=y, **kwargs)
10911110
self.controls = []
10921111
self.captions = []
10931112
self.extend(controls)
@@ -1137,11 +1156,12 @@ def apply(self, spacing=10):
11371156
for control in self.controls:
11381157
if isinstance(control, Layout):
11391158
# Child containers in the layout can be wider than the desired width.
1140-
# adjusting mw at the start will controls wider to line out with the total width,
1159+
# adjusting mw at the start will make controls wider to line out with the total width,
11411160
# adjusting it at the end would just ensure that the layout is wide enough.
1142-
mw = max(self._maxwidth, control.width)
1161+
mw = max(mw, control.width)
11431162
w1 = max([caption.width for caption in self.captions])
11441163
w2 = max([control.width for control in self.controls])
1164+
w2 = min(w2, mw)
11451165
dx = 0
11461166
dy = 0
11471167
for caption, control in reversed(zip(self.captions, self.controls)):
@@ -1157,6 +1177,9 @@ def apply(self, spacing=10):
11571177
dy += max(caption.height, control.height, 10) + spacing
11581178
self.width = w1 + w2 + (w1>0 and spacing)
11591179
self.height = dy - spacing
1180+
1181+
#def draw(self):
1182+
# rect(0, 0, self.width, self.height, fill=None, stroke=[1,1,1,1])
11601183

11611184
TOP, CENTER = "top", "center"
11621185

nodebox/gui/theme/field.png

271 Bytes
Loading

0 commit comments

Comments
 (0)