summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--redo/controls.go27
-rw-r--r--redo/controls_darwin.go37
-rw-r--r--redo/controls_darwin.m24
-rw-r--r--redo/controls_unix.go53
-rw-r--r--redo/controls_windows.go40
-rw-r--r--redo/objc_darwin.h1
-rw-r--r--redo/sizing_unix.go13
-rw-r--r--redo/zz_test.go3
8 files changed, 174 insertions, 24 deletions
diff --git a/redo/controls.go b/redo/controls.go
index f047e7f..ef97ed1 100644
--- a/redo/controls.go
+++ b/redo/controls.go
@@ -38,7 +38,7 @@ type Checkbox interface {
// TODO change to OnToggled() or OnChecked()?
OnClicked(func())
- // Text and SetText are Requests that get and set the Checkbox's label text.
+ // Text and SetText get and set the Checkbox's label text.
Text() string
SetText(text string)
@@ -73,3 +73,28 @@ func NewTextField() TextField {
func NewPasswordField() TextField {
return newPasswordField()
}
+
+
+// Label is a Control that shows a static line of text.
+// Label shows one line of text; any text that does not fit is truncated.
+// A Label can either have smart vertical alignment relative to the control to its right or just be vertically aligned to the top (standalone).
+type Label interface {
+ Control
+
+ // Text and SetText get and set the Label's text.
+ Text() string
+ SetText(text string)
+}
+
+// NewLabel creates a new Label with the given text.
+// The Label will smartly vertically position itself relative to the control to its immediate right.
+// TODO Grids on GTK+ will not respect this unless SetFilling()
+func NewLabel(text string) Label {
+ return newLabel(text)
+}
+
+// NewStandaloneLabel creates a new Label with the given text.
+// The Label will be vertically positioned at the top of its allocated space.
+func NewStandaloneLabel(text string) Label {
+ return newStandaloneLabel(text)
+}
diff --git a/redo/controls_darwin.go b/redo/controls_darwin.go
index a4e6c29..d6968fc 100644
--- a/redo/controls_darwin.go
+++ b/redo/controls_darwin.go
@@ -101,16 +101,18 @@ type textField struct {
*widgetbase
}
-func newTextField() *textField {
+func finishNewTextField(id C.id) *textField {
return &textField{
- widgetbase: newWidget(C.newTextField()),
+ widgetbase: newWidget(id),
}
}
+func newTextField() *textField {
+ return finishNewTextField(C.newTextField())
+}
+
func newPasswordField() *textField {
- return &textField{
- widgetbase: newWidget(C.newPasswordField()),
- }
+ return finishNewTextField(C.newPasswordField())
}
func (t *textField) Text() string {
@@ -122,3 +124,28 @@ func (t *textField) SetText(text string) {
defer C.free(unsafe.Pointer(ctext))
C.textFieldSetText(t.id, ctext)
}
+
+// cheap trick
+type label struct {
+ *textField
+ standalone bool
+}
+
+func finishNewLabel(text string, standalone bool) *label {
+ l := &label{
+ textField: finishNewTextField(C.newLabel()),
+ standalone: standalone,
+ }
+ l.SetText(text)
+ return l
+}
+
+func newLabel(text string) Label {
+ return finishNewLabel(text, false)
+}
+
+func newStandaloneLabel(text string) Label {
+ return finishNewLabel(text, true)
+}
+
+// TODO label commitResize
diff --git a/redo/controls_darwin.m b/redo/controls_darwin.m
index 23d15e2..c482e5e 100644
--- a/redo/controls_darwin.m
+++ b/redo/controls_darwin.m
@@ -101,17 +101,20 @@ void checkboxSetChecked(id c, BOOL checked)
[toNSButton(c) setState:state];
}
-static id finishNewTextField(NSTextField *t)
+static id finishNewTextField(NSTextField *t, BOOL bordered)
{
- // same for text fields and password fields
+ // same for text fields, password fields, and labels
setStandardControlFont((id) t);
- // TODO border (Interface Builder setting is confusing)
+ // TODO text field/password field border (Interface Builder setting is confusing)
+ if (!bordered)
+ [t setBordered:NO];
// smart quotes and other autocorrect features are handled by the window; see newWindow() in window_darwin.m for details
// Interface Builder does this to make the text box behave properly
// this disables both word wrap AND ellipsizing in one fell swoop
// however, we need to send it to the control's cell, not to the control directly
[[t cell] setLineBreakMode:NSLineBreakByClipping];
// Interface Builder also sets this to allow horizontal scrolling
+ // it also sets this for labels, despite those not being scrollable
[[t cell] setScrollable:YES];
return (id) t;
}
@@ -121,7 +124,7 @@ id newTextField(void)
NSTextField *t;
t = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
- return finishNewTextField(t);
+ return finishNewTextField(t, YES);
}
id newPasswordField(void)
@@ -129,7 +132,7 @@ id newPasswordField(void)
NSSecureTextField *t;
t = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
- return finishNewTextField(toNSTextField(t));
+ return finishNewTextField(toNSTextField(t), YES);
}
const char *textFieldText(id t)
@@ -141,3 +144,14 @@ void textFieldSetText(id t, char *text)
{
[toNSTextField(t) setStringValue:[NSString stringWithUTF8String:text]];
}
+
+id newLabel(void)
+{
+ NSTextField *l;
+
+ l = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)];
+ [l setEditable:NO];
+ [l setSelectable:NO];
+ [l setDrawsBackground:NO];
+ return finishNewTextField(l, NO);
+}
diff --git a/redo/controls_unix.go b/redo/controls_unix.go
index 0761fa1..8e13767 100644
--- a/redo/controls_unix.go
+++ b/redo/controls_unix.go
@@ -13,6 +13,9 @@ import (
// extern void checkboxToggled(GtkToggleButton *, gpointer);
import "C"
+// TODOs:
+// - standalone label on its own: should it be centered or not?
+
type widgetbase struct {
widget *C.GtkWidget
}
@@ -153,3 +156,53 @@ func (t *textField) SetText(text string) {
defer freegstr(ctext)
C.gtk_entry_set_text(t.entry, ctext)
}
+
+type label struct {
+ *widgetbase
+ misc *C.GtkMisc
+ label *C.GtkLabel
+ standalone bool
+}
+
+func finishNewLabel(text string, standalone bool) *label {
+ ctext := togstr(text)
+ defer freegstr(ctext)
+ widget := C.gtk_label_new(ctext)
+ return &label{
+ widgetbase: newWidget(widget),
+ misc: (*C.GtkMisc)(unsafe.Pointer(widget)),
+ label: (*C.GtkLabel)(unsafe.Pointer(widget)),
+ standalone: standalone,
+ }
+}
+
+func newLabel(text string) Label {
+ return finishNewLabel(text, false)
+}
+
+func newStandaloneLabel(text string) Label {
+ return finishNewLabel(text, true)
+}
+
+func (l *label) Text() string {
+ return fromgstr(C.gtk_label_get_text(l.label))
+}
+
+func (l *label) SetText(text string) {
+ ctext := togstr(text)
+ defer freegstr(ctext)
+ C.gtk_label_set_text(l.label, ctext)
+}
+
+func (l *label) commitResize(c *allocation, d *sizing) {
+ if !l.standalone && c.neighbor != nil {
+ c.neighbor.getAuxResizeInfo(d)
+ if d.shouldVAlignTop {
+ // TODO should it be center-aligned to the first line or not
+ C.gtk_misc_set_alignment(l.misc, 0, 0)
+ } else {
+ C.gtk_misc_set_alignment(l.misc, 0, 0.5)
+ }
+ }
+ l.widgetbase.commitResize(c, d)
+}
diff --git a/redo/controls_windows.go b/redo/controls_windows.go
index 882c15d..b9c69ed 100644
--- a/redo/controls_windows.go
+++ b/redo/controls_windows.go
@@ -157,3 +157,43 @@ func (t *textField) Text() string {
func (t *textField) SetText(text string) {
t.settext(text)
}
+
+type label struct {
+ *widgetbase
+ standalone bool
+}
+
+var labelclass = toUTF16("STATIC")
+
+func finishNewLabel(text string, standalone bool) *label {
+ w := newWidget(labelclass,
+ // SS_NOPREFIX avoids accelerator translation; SS_LEFTNOWORDWRAP clips text past the end
+ // controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi)
+ C.SS_NOPREFIX | C.SS_LEFTNOWORDWRAP,
+ 0)
+ C.setWindowText(w.hwnd, toUTF16(text))
+ C.controlSetControlFont(w.hwnd)
+ l := &label{
+ widgetbase: w,
+ standalone: standalone,
+ }
+ return l
+}
+
+func newLabel(text string) Label {
+ return finishNewLabel(text, false)
+}
+
+func newStandaloneLabel(text string) Label {
+ return finishNewLabel(text, true)
+}
+
+func (l *label) Text() string {
+ return l.text()
+}
+
+func (l *label) SetText(text string) {
+ l.settext(text)
+}
+
+// TODO label commitResize
diff --git a/redo/objc_darwin.h b/redo/objc_darwin.h
index 3a4cc6f..299c9b5 100644
--- a/redo/objc_darwin.h
+++ b/redo/objc_darwin.h
@@ -46,6 +46,7 @@ extern id newTextField(void);
extern id newPasswordField(void);
extern const char *textFieldText(id);
extern void textFieldSetText(id, char *);
+extern id newLabel(void);
/* sizing_darwin.m */
extern void moveControl(id, intptr_t, intptr_t, intptr_t, intptr_t);
diff --git a/redo/sizing_unix.go b/redo/sizing_unix.go
index d94bc01..abca80d 100644
--- a/redo/sizing_unix.go
+++ b/redo/sizing_unix.go
@@ -50,19 +50,6 @@ func (w *widgetbase) allocate(x int, y int, width int, height int, d *sizing) []
}
func (w *widgetbase) commitResize(c *allocation, d *sizing) {
-// TODO
-/*
- if s.ctype == c_label && !s.alternate && c.neighbor != nil {
- c.neighbor.getAuxResizeInfo(d)
- if d.shouldVAlignTop {
- // TODO should it be center-aligned to the first line or not
- gtk_misc_set_alignment(s.widget, 0, 0)
- } else {
- gtk_misc_set_alignment(s.widget, 0, 0.5)
- }
- }
-*/
-
// as we resize on size-allocate, we have to also use size-allocate on our children
// this is fine anyway; in fact, this allows us to move without knowing what the container is!
// this is what GtkBox does anyway
diff --git a/redo/zz_test.go b/redo/zz_test.go
index f6791a0..d20eabf 100644
--- a/redo/zz_test.go
+++ b/redo/zz_test.go
@@ -28,6 +28,7 @@ var ddata = []dtype{
type testwin struct {
t Tab
w Window
+ l Label
table Table
b Button
c Checkbox
@@ -47,6 +48,8 @@ func (tw *testwin) make(done chan struct{}) {
done <- struct{}{}
return true
})
+ tw.l = NewStandaloneLabel("hello")
+ tw.t.Append("Label", tw.l)
tw.table = NewTable(reflect.TypeOf(ddata[0]))
tw.table.Lock()
dq := tw.table.Data().(*[]dtype)