Added Label and implemented it on all platforms.
This commit is contained in:
parent
8d7f0c9a62
commit
f4bb7360d4
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue