Exemple #1
0
func (b *ProgressBar) SetSize(size math.Size) {
	b.ProgressBar.SetSize(size)

	b.chevrons = nil
	if size.Area() > 0 {
		b.chevrons = b.theme.Driver().CreateCanvas(size)
		b.chevronWidth = size.H / 2
		cw := b.chevronWidth
		for x := -cw * 2; x < size.W; x += cw * 2 {
			// x0    x2
			// |  x1 |  x3
			//    |     |
			// A-----B    - y0
			//  \     \
			//   \     \
			//    F     C - y1
			//   /     /
			//  /     /
			// E-----D    - y2
			y0, y1, y2 := 0, size.H/2, size.H
			x0, x1 := x, x+cw/2
			x2, x3 := x0+cw, x1+cw
			var chevron = gxui.Polygon{
				/* A */ gxui.PolygonVertex{Position: math.Point{X: x0, Y: y0}},
				/* B */ gxui.PolygonVertex{Position: math.Point{X: x2, Y: y0}},
				/* C */ gxui.PolygonVertex{Position: math.Point{X: x3, Y: y1}},
				/* D */ gxui.PolygonVertex{Position: math.Point{X: x2, Y: y2}},
				/* E */ gxui.PolygonVertex{Position: math.Point{X: x0, Y: y2}},
				/* F */ gxui.PolygonVertex{Position: math.Point{X: x1, Y: y1}},
			}
			b.chevrons.DrawPolygon(chevron, gxui.TransparentPen, gxui.CreateBrush(gxui.Gray30))
		}
		b.chevrons.Complete()
	}
}
Exemple #2
0
func (v *viewport) SetSizeDips(size math.Size) {
	v.driver.syncDriver(func() {
		v.sizeDips = size
		v.sizeDipsUnscaled = size.ScaleS(v.scaling)
		v.window.SetSize(v.sizeDipsUnscaled.W, v.sizeDipsUnscaled.H)
	})
}
Exemple #3
0
func (f *font) Measure(fl *gxui.TextBlock) math.Size {
	size := math.Size{W: 0, H: f.glyphMaxSizeDips.H}
	var offset math.Point
	for _, r := range fl.Runes {
		if r == '\n' {
			offset.X = 0
			offset.Y += f.glyphMaxSizeDips.H
			continue
		}
		offset.X += f.advanceDips(r)
		size = size.Max(math.Size{W: offset.X, H: offset.Y + f.glyphMaxSizeDips.H})
	}
	return size
}
Exemple #4
0
func createGlyphPage(resolution resolution, glyphMaxSizePixels math.Size) *glyphPage {
	// Handle exceptionally large glyphs.
	size := math.Size{W: glyphPageWidth, H: glyphPageHeight}.Max(glyphMaxSizePixels)
	size.W = align(size.W, glyphSizeAlignment)
	size.H = align(size.H, glyphSizeAlignment)

	return &glyphPage{
		resolution:         resolution,
		glyphMaxSizePixels: glyphMaxSizePixels,
		size:               size,
		image:              image.NewAlpha(image.Rect(0, 0, size.W, size.H)),
		offsets:            make(map[rune]math.Point),
		rowHeight:          0,
		rast:               raster.NewRasterizer(glyphMaxSizePixels.W, glyphMaxSizePixels.H),
	}
}
Exemple #5
0
func newGlyphPage(face fnt.Face, r rune) *glyphPage {
	// Start the page big enough to hold the initial rune.
	b, _, _ := face.GlyphBounds(r)
	bounds := rectangle26_6toRect(b)
	size := math.Size{W: glyphPageWidth, H: glyphPageHeight}.Max(bounds.Size())
	size.W = align(size.W, glyphSizeAlignment)
	size.H = align(size.H, glyphSizeAlignment)

	page := &glyphPage{
		image:     image.NewAlpha(image.Rect(0, 0, size.W, size.H)),
		size:      size,
		entries:   make(map[rune]glyphEntry),
		rowHeight: 0,
	}
	page.add(face, r)
	return page
}
Exemple #6
0
func (l *List) DesiredSize(min, max math.Size) math.Size {
	if l.adapter == nil {
		return min
	}
	count := math.Max(l.itemCount, 1)
	var s math.Size
	if l.orientation.Horizontal() {
		s = math.Size{W: l.itemSize.W * count, H: l.itemSize.H}
	} else {
		s = math.Size{W: l.itemSize.W, H: l.itemSize.H * count}
	}
	if l.scrollBarEnabled {
		if l.orientation.Horizontal() {
			s.H += l.scrollBar.DesiredSize(min, max).H
		} else {
			s.W += l.scrollBar.DesiredSize(min, max).W
		}
	}
	return s.Expand(l.outer.Padding()).Clamp(min, max)
}
Exemple #7
0
func (f *font) Layout(fl *gxui.TextBlock) (offsets []math.Point) {
	sizeDips := math.Size{}
	offsets = make([]math.Point, len(fl.Runes))
	var offset math.Point
	for i, r := range fl.Runes {
		if r == '\n' {
			offset.X = 0
			offset.Y += f.glyphMaxSizeDips.H
			continue
		}

		offsets[i] = offset
		offset.X += f.advanceDips(r)
		sizeDips = sizeDips.Max(math.Size{W: offset.X, H: offset.Y + f.glyphMaxSizeDips.H})
	}

	origin := f.align(fl.AlignRect, sizeDips, f.ascentDips, fl.H, fl.V)
	for i, p := range offsets {
		offsets[i] = p.Add(origin)
	}
	return offsets
}
Exemple #8
0
func (l *ScrollLayout) SetScrollOffset(scrollOffset math.Point) bool {
	var cs math.Size
	if l.child != nil {
		cs = l.child.Control.Size()
	}

	s := l.innerSize
	scrollOffset = scrollOffset.Min(cs.Sub(s).Point()).Max(math.Point{})

	l.scrollBarX.Control.SetVisible(l.canScrollX && cs.W > s.W)
	l.scrollBarY.Control.SetVisible(l.canScrollY && cs.H > s.H)
	l.scrollBarX.Control.(gxui.ScrollBar).SetScrollPosition(l.scrollOffset.X, l.scrollOffset.X+s.W)
	l.scrollBarY.Control.(gxui.ScrollBar).SetScrollPosition(l.scrollOffset.Y, l.scrollOffset.Y+s.H)

	if l.scrollOffset != scrollOffset {
		l.scrollOffset = scrollOffset
		l.Relayout()
		return true
	}

	return false
}
Exemple #9
0
func (l *LinearLayout) DesiredSize(min, max math.Size) math.Size {
	if l.sizeMode.Fill() {
		return max
	}

	bounds := min.Rect()
	children := l.outer.Children()

	horizontal := l.direction.Orientation().Horizontal()
	offset := math.Point{X: 0, Y: 0}
	for _, c := range children {
		cs := c.Control.DesiredSize(math.ZeroSize, max)
		cm := c.Control.Margin()
		cb := cs.Expand(cm).Rect().Offset(offset)
		if horizontal {
			offset.X += cb.W()
		} else {
			offset.Y += cb.H()
		}
		bounds = bounds.Union(cb)
	}

	return bounds.Size().Expand(l.outer.Padding()).Clamp(min, max)
}
Exemple #10
0
func (a *DefaultAdapter) SetSizeAsLargest(theme Theme) {
	s := math.Size{}
	font := theme.DefaultFont()
	for i := 0; i < a.Count(); i++ {
		switch t := a.ItemAt(i).(type) {
		case Viewer:
			s = s.Max(t.View(theme).DesiredSize(math.ZeroSize, math.MaxSize))

		case Stringer:
			s = s.Max(font.Measure(&TextBlock{
				Runes: []rune(t.String()),
			}))

		default:
			s = s.Max(font.Measure(&TextBlock{
				Runes: []rune(fmt.Sprintf("%+v", t)),
			}))
		}
	}
	a.SetSize(s)
}
Exemple #11
0
func (l *List) LayoutChildren() {
	if l.adapter == nil {
		l.outer.RemoveAll()
		return
	}

	if !l.RelayoutSuspended() {
		// Disable relayout on AddChild / RemoveChild as we're performing layout here.
		l.SetRelayoutSuspended(true)
		defer l.SetRelayoutSuspended(false)
	}

	s := l.outer.Size().Contract(l.Padding())
	o := l.Padding().LT()

	var itemSize math.Size
	if l.orientation.Horizontal() {
		itemSize = math.Size{W: l.itemSize.W, H: s.H}
	} else {
		itemSize = math.Size{W: s.W, H: l.itemSize.H}
	}

	startIndex, endIndex := l.VisibleItemRange(true)
	majorAxisItemSize := l.MajorAxisItemSize()

	d := startIndex*majorAxisItemSize - l.scrollOffset

	mark := l.layoutMark
	l.layoutMark++

	for idx := startIndex; idx < endIndex; idx++ {
		item := l.adapter.ItemAt(idx)

		details, found := l.details[item]
		if found {
			if details.mark == mark {
				panic(fmt.Errorf("Adapter for control '%s' returned duplicate item (%v) for indices %v and %v",
					gxui.Path(l.outer), item, details.index, idx))
			}
		} else {
			control := l.adapter.Create(l.theme, idx)
			details.onClickSubscription = control.OnClick(func(ev gxui.MouseEvent) {
				l.ItemClicked(ev, item)
			})
			details.child = l.AddChildAt(0, control)
		}
		details.mark = mark
		details.index = idx
		l.details[item] = details

		c := details.child
		cm := c.Control.Margin()
		cs := itemSize.Contract(cm).Max(math.ZeroSize)
		if l.orientation.Horizontal() {
			c.Layout(math.CreateRect(d, cm.T, d+cs.W, cm.T+cs.H).Offset(o))
		} else {
			c.Layout(math.CreateRect(cm.L, d, cm.L+cs.W, d+cs.H).Offset(o))
		}
		d += majorAxisItemSize
	}

	// Reap unused items
	for item, details := range l.details {
		if details.mark != mark {
			details.onClickSubscription.Unlisten()
			l.RemoveChild(details.child.Control)
			delete(l.details, item)
		}
	}

	if l.scrollBarEnabled {
		ss := l.scrollBar.DesiredSize(math.ZeroSize, s)
		if l.Orientation().Horizontal() {
			l.scrollBarChild.Layout(math.CreateRect(0, s.H-ss.H, s.W, s.H).Canon().Offset(o))
		} else {
			l.scrollBarChild.Layout(math.CreateRect(s.W-ss.W, 0, s.W, s.H).Canon().Offset(o))
		}

		// Only show the scroll bar if needed
		entireContentVisible := startIndex == 0 && endIndex == l.itemCount
		l.scrollBar.SetVisible(!entireContentVisible)
	}

	l.UpdateItemMouseOver()
}