summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--actionlist.go14
-rw-r--r--boxlayout.go106
-rw-r--r--container.go133
-rw-r--r--declarative/builder.go4
-rw-r--r--declarative/checkbox.go1
-rw-r--r--declarative/combobox.go1
-rw-r--r--declarative/composite.go1
-rw-r--r--declarative/customwidget.go1
-rw-r--r--declarative/dateedit.go1
-rw-r--r--declarative/datelabel.go1
-rw-r--r--declarative/dialog.go2
-rw-r--r--declarative/gradientcomposite.go1
-rw-r--r--declarative/groupbox.go1
-rw-r--r--declarative/imageview.go1
-rw-r--r--declarative/interfaces.go1
-rw-r--r--declarative/label.go1
-rw-r--r--declarative/lineedit.go1
-rw-r--r--declarative/lineerrorpresenter.go1
-rw-r--r--declarative/linklabel.go1
-rw-r--r--declarative/listbox.go1
-rw-r--r--declarative/mainwindow.go2
-rw-r--r--declarative/numberedit.go1
-rw-r--r--declarative/numberlabel.go1
-rw-r--r--declarative/progressbar.go1
-rw-r--r--declarative/pushbutton.go1
-rw-r--r--declarative/radiobutton.go1
-rw-r--r--declarative/radiobuttongroupbox.go1
-rw-r--r--declarative/scrollview.go1
-rw-r--r--declarative/separator.go1
-rw-r--r--declarative/slider.go1
-rw-r--r--declarative/splitbutton.go1
-rw-r--r--declarative/splitter.go1
-rw-r--r--declarative/tableview.go1
-rw-r--r--declarative/tabpage.go1
-rw-r--r--declarative/tabwidget.go1
-rw-r--r--declarative/textedit.go1
-rw-r--r--declarative/textlabel.go1
-rw-r--r--declarative/toolbar.go1
-rw-r--r--declarative/toolbutton.go1
-rw-r--r--declarative/treeview.go1
-rw-r--r--declarative/webview.go1
-rw-r--r--dialog.go2
-rw-r--r--flowlayout.go128
-rw-r--r--fontresource.go83
-rw-r--r--form.go2
-rw-r--r--gridlayout.go131
-rw-r--r--tableview.go29
-rw-r--r--tabpagelist.go4
-rw-r--r--toolbar.go8
-rw-r--r--tooltip.go6
-rw-r--r--util.go15
-rw-r--r--widget.go13
-rw-r--r--window.go83
54 files changed, 451 insertions, 350 deletions
diff --git a/AUTHORS b/AUTHORS
index ce5e8663..b44a7a88 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -29,3 +29,4 @@ Semyon Tokarev <zlobzn@gmail.com>
Shawn Sun <datago@yeah.net>
Tim Dufrane <tim.dufrane@gmail.com>
Vincent Vanackere <vincent.vanackere@gmail.com>
+Dmitry Bagdanov <dimbojob@gmail.com>
diff --git a/actionlist.go b/actionlist.go
index c15880eb..508faf31 100644
--- a/actionlist.go
+++ b/actionlist.go
@@ -174,3 +174,17 @@ func (l *ActionList) updateSeparatorVisibility() error {
return nil
}
+
+func (l *ActionList) AttachShortcuts(w Window) {
+ shortcuts := make(map[Shortcut]*Action, len(l.actions))
+ for _, action := range l.actions {
+ if action.Shortcut().Key != 0 {
+ shortcuts[action.Shortcut()] = action
+ }
+ }
+ w.KeyDown().Attach(func(key Key) {
+ if action, ok := shortcuts[Shortcut{ModifiersDown(), key}]; ok {
+ action.raiseTriggered()
+ }
+ })
+}
diff --git a/boxlayout.go b/boxlayout.go
index 96d8afd2..ce08199f 100644
--- a/boxlayout.go
+++ b/boxlayout.go
@@ -20,24 +20,24 @@ const (
)
type BoxLayout struct {
- container Container
- margins Margins
- spacing int
+ LayoutBase
orientation Orientation
- alignment Alignment2D
hwnd2StretchFactor map[win.HWND]int
- sizeAndDPI2MinSize map[sizeAndDPI]Size
- resetNeeded bool
}
func newBoxLayout(orientation Orientation) *BoxLayout {
- return &BoxLayout{
+ l := &BoxLayout{
+ LayoutBase: LayoutBase{
+ sizeAndDPI2MinSize: make(map[sizeAndDPI]Size),
+ margins96dpi: Margins{9, 9, 9, 9},
+ spacing96dpi: 6,
+ },
orientation: orientation,
hwnd2StretchFactor: make(map[win.HWND]int),
- sizeAndDPI2MinSize: make(map[sizeAndDPI]Size),
- margins: Margins{9, 9, 9, 9},
- spacing: 6,
}
+ l.layout = l
+
+ return l
}
func NewHBoxLayout() *BoxLayout {
@@ -48,42 +48,6 @@ func NewVBoxLayout() *BoxLayout {
return newBoxLayout(Vertical)
}
-func (l *BoxLayout) Container() Container {
- return l.container
-}
-
-func (l *BoxLayout) SetContainer(value Container) {
- if value != l.container {
- if l.container != nil {
- l.container.SetLayout(nil)
- }
-
- l.container = value
-
- if value != nil && value.Layout() != Layout(l) {
- value.SetLayout(l)
-
- l.Update(true)
- }
- }
-}
-
-func (l *BoxLayout) Margins() Margins {
- return l.margins
-}
-
-func (l *BoxLayout) SetMargins(value Margins) error {
- if value.HNear < 0 || value.VNear < 0 || value.HFar < 0 || value.VFar < 0 {
- return newError("margins must be positive")
- }
-
- l.margins = value
-
- l.Update(false)
-
- return nil
-}
-
func (l *BoxLayout) Orientation() Orientation {
return l.orientation
}
@@ -105,42 +69,6 @@ func (l *BoxLayout) SetOrientation(value Orientation) error {
return nil
}
-func (l *BoxLayout) Alignment() Alignment2D {
- return l.alignment
-}
-
-func (l *BoxLayout) SetAlignment(alignment Alignment2D) error {
- if alignment != l.alignment {
- if alignment < AlignHVDefault || alignment > AlignHFarVFar {
- return newError("invalid Alignment value")
- }
-
- l.alignment = alignment
-
- l.Update(false)
- }
-
- return nil
-}
-
-func (l *BoxLayout) Spacing() int {
- return l.spacing
-}
-
-func (l *BoxLayout) SetSpacing(value int) error {
- if value != l.spacing {
- if value < 0 {
- return newError("spacing cannot be negative")
- }
-
- l.spacing = value
-
- l.Update(false)
- }
-
- return nil
-}
-
func (l *BoxLayout) StretchFactor(widget Widget) int {
if factor, ok := l.hwnd2StretchFactor[widget.Handle()]; ok {
return factor
@@ -251,16 +179,12 @@ func (l *BoxLayout) MinSizeForSize(size Size) Size {
bounds := Rectangle{Width: size.Width, Height: size.Height}
- wb := l.container.AsWindowBase()
- margins := wb.marginsFrom96DPI(l.margins)
- spacing := wb.intFrom96DPI(l.spacing)
-
- items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, bounds, margins, spacing, l.hwnd2StretchFactor)
+ items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, bounds, l.margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return Size{}
}
- s := Size{margins.HNear + margins.HFar, margins.VNear + margins.VFar}
+ s := Size{l.margins.HNear + l.margins.HFar, l.margins.VNear + l.margins.VFar}
var maxSecondary int
@@ -286,10 +210,10 @@ func (l *BoxLayout) MinSizeForSize(size Size) Size {
}
if l.orientation == Horizontal {
- s.Width += (len(items) - 1) * spacing
+ s.Width += (len(items) - 1) * l.spacing
s.Height += maxSecondary
} else {
- s.Height += (len(items) - 1) * spacing
+ s.Height += (len(items) - 1) * l.spacing
s.Width += maxSecondary
}
@@ -327,7 +251,7 @@ func (l *BoxLayout) Update(reset bool) error {
ifContainerIsScrollViewDoCoolSpecialLayoutStuff(l)
- items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, l.container.ClientBounds(), l.container.AsWindowBase().marginsFrom96DPI(l.margins), l.container.AsWindowBase().intFrom96DPI(l.spacing), l.hwnd2StretchFactor)
+ items, err := boxLayoutItems(widgetsToLayout(l.Container().Children()), l.orientation, l.alignment, l.container.ClientBounds(), l.margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return err
}
diff --git a/container.go b/container.go
index b94bccda..be0814f5 100644
--- a/container.go
+++ b/container.go
@@ -100,6 +100,121 @@ type Layout interface {
Update(reset bool) error
}
+type LayoutBase struct {
+ layout Layout
+ container Container
+ sizeAndDPI2MinSize map[sizeAndDPI]Size
+ margins96dpi Margins
+ margins Margins
+ spacing96dpi int
+ spacing int
+ alignment Alignment2D
+ resetNeeded bool
+}
+
+func (l *LayoutBase) sizeAndDPIToMinSize() map[sizeAndDPI]Size {
+ return l.sizeAndDPI2MinSize
+}
+
+func (l *LayoutBase) Container() Container {
+ return l.container
+}
+
+func (l *LayoutBase) SetContainer(value Container) {
+ if value == l.container {
+ return
+ }
+
+ if l.container != nil {
+ l.container.SetLayout(nil)
+ }
+
+ l.container = value
+
+ if value != nil && value.Layout() != l.layout {
+ value.SetLayout(l.layout)
+ }
+
+ l.updateMargins()
+ l.updateSpacing()
+
+ l.layout.Update(true)
+}
+
+func (l *LayoutBase) Margins() Margins {
+ return l.margins96dpi
+}
+
+func (l *LayoutBase) SetMargins(value Margins) error {
+ if value == l.margins96dpi {
+ return nil
+ }
+
+ if value.HNear < 0 || value.VNear < 0 || value.HFar < 0 || value.VFar < 0 {
+ return newError("margins must be positive")
+ }
+
+ l.margins96dpi = value
+
+ l.updateMargins()
+
+ l.layout.Update(false)
+
+ return nil
+}
+
+func (l *LayoutBase) Spacing() int {
+ return l.spacing96dpi
+}
+
+func (l *LayoutBase) SetSpacing(value int) error {
+ if value == l.spacing96dpi {
+ return nil
+ }
+
+ if value < 0 {
+ return newError("spacing cannot be negative")
+ }
+
+ l.spacing96dpi = value
+
+ l.updateSpacing()
+
+ l.layout.Update(false)
+
+ return nil
+}
+
+func (l *LayoutBase) updateMargins() {
+ if l.container != nil {
+ l.margins = l.container.AsWindowBase().marginsFrom96DPI(l.margins96dpi)
+ }
+}
+
+func (l *LayoutBase) updateSpacing() {
+ if l.container != nil {
+ l.spacing = l.container.AsWindowBase().intFrom96DPI(l.spacing96dpi)
+ }
+}
+
+func (l *LayoutBase) Alignment() Alignment2D {
+ return l.alignment
+}
+
+func (l *LayoutBase) SetAlignment(alignment Alignment2D) error {
+ if alignment != l.alignment {
+ if alignment < AlignHVDefault || alignment > AlignHFarVFar {
+ return newError("invalid Alignment value")
+ }
+
+ l.alignment = alignment
+
+ l.layout.Update(false)
+ }
+
+ return nil
+}
+
type sizeAndDPI struct {
size Size
dpi int
@@ -316,6 +431,24 @@ func (cb *ContainerBase) applyFont(font *Font) {
applyFontToDescendants(cb.window.(Widget), font)
}
+func (cb *ContainerBase) applyDPI(dpi int) {
+ cb.WidgetBase.applyDPI(dpi)
+
+ applyDPIToDescendants(cb.window.(Widget), dpi)
+
+ if cb.layout != nil {
+ if ums, ok := cb.layout.(interface {
+ updateMargins()
+ updateSpacing()
+ }); ok {
+ ums.updateMargins()
+ ums.updateSpacing()
+ }
+
+ cb.layout.Update(false)
+ }
+}
+
func (cb *ContainerBase) Children() *WidgetList {
return cb.children
}
diff --git a/declarative/builder.go b/declarative/builder.go
index a0d423a3..da0a7788 100644
--- a/declarative/builder.go
+++ b/declarative/builder.go
@@ -202,6 +202,10 @@ func (b *Builder) InitWidget(d Widget, w walk.Window, customInit func() error) e
w.SizeChanged().Attach(handler)
}
+ if db := b.bool("DoubleBuffering"); db {
+ w.SetDoubleBuffering(true)
+ }
+
if rtl := b.bool("RightToLeftReading"); rtl {
w.SetRightToLeftReading(true)
}
diff --git a/declarative/checkbox.go b/declarative/checkbox.go
index 40c40f6b..5c551c38 100644
--- a/declarative/checkbox.go
+++ b/declarative/checkbox.go
@@ -15,6 +15,7 @@ type CheckBox struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/combobox.go b/declarative/combobox.go
index 473446ef..28694645 100644
--- a/declarative/combobox.go
+++ b/declarative/combobox.go
@@ -19,6 +19,7 @@ type ComboBox struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/composite.go b/declarative/composite.go
index 065f501a..d466b26b 100644
--- a/declarative/composite.go
+++ b/declarative/composite.go
@@ -16,6 +16,7 @@ type Composite struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/customwidget.go b/declarative/customwidget.go
index 44dbb84b..8dd3c5ce 100644
--- a/declarative/customwidget.go
+++ b/declarative/customwidget.go
@@ -23,6 +23,7 @@ type CustomWidget struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/dateedit.go b/declarative/dateedit.go
index 41eb3683..9a933c81 100644
--- a/declarative/dateedit.go
+++ b/declarative/dateedit.go
@@ -19,6 +19,7 @@ type DateEdit struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/datelabel.go b/declarative/datelabel.go
index d2c63ab1..0591fec7 100644
--- a/declarative/datelabel.go
+++ b/declarative/datelabel.go
@@ -15,6 +15,7 @@ type DateLabel struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/dialog.go b/declarative/dialog.go
index f869b773..a42edb3f 100644
--- a/declarative/dialog.go
+++ b/declarative/dialog.go
@@ -15,6 +15,7 @@ type Dialog struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
@@ -77,6 +78,7 @@ func (d Dialog) Create(owner walk.Form) error {
// Window
Background: d.Background,
ContextMenuItems: d.ContextMenuItems,
+ DoubleBuffering: d.DoubleBuffering,
Enabled: d.Enabled,
Font: d.Font,
MaxSize: d.MaxSize,
diff --git a/declarative/gradientcomposite.go b/declarative/gradientcomposite.go
index 70746d7b..7527b20a 100644
--- a/declarative/gradientcomposite.go
+++ b/declarative/gradientcomposite.go
@@ -16,6 +16,7 @@ type GradientComposite struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/groupbox.go b/declarative/groupbox.go
index 9b23ed87..0d60b998 100644
--- a/declarative/groupbox.go
+++ b/declarative/groupbox.go
@@ -15,6 +15,7 @@ type GroupBox struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/imageview.go b/declarative/imageview.go
index 392f2698..8e208824 100644
--- a/declarative/imageview.go
+++ b/declarative/imageview.go
@@ -26,6 +26,7 @@ type ImageView struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/interfaces.go b/declarative/interfaces.go
index 13e4d690..8f300ac7 100644
--- a/declarative/interfaces.go
+++ b/declarative/interfaces.go
@@ -89,6 +89,7 @@ type formInfo struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/label.go b/declarative/label.go
index afb219f5..68d31a24 100644
--- a/declarative/label.go
+++ b/declarative/label.go
@@ -15,6 +15,7 @@ type Label struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/lineedit.go b/declarative/lineedit.go
index 2c59ff6c..d4f52e7f 100644
--- a/declarative/lineedit.go
+++ b/declarative/lineedit.go
@@ -23,6 +23,7 @@ type LineEdit struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/lineerrorpresenter.go b/declarative/lineerrorpresenter.go
index 4f4bc8de..49a5d4f4 100644
--- a/declarative/lineerrorpresenter.go
+++ b/declarative/lineerrorpresenter.go
@@ -15,6 +15,7 @@ type LineErrorPresenter struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/linklabel.go b/declarative/linklabel.go
index 7ba20991..16ad4505 100644
--- a/declarative/linklabel.go
+++ b/declarative/linklabel.go
@@ -15,6 +15,7 @@ type LinkLabel struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/listbox.go b/declarative/listbox.go
index 6e97d8b7..41e9208d 100644
--- a/declarative/listbox.go
+++ b/declarative/listbox.go
@@ -20,6 +20,7 @@ type ListBox struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/mainwindow.go b/declarative/mainwindow.go
index 2731b223..cb967701 100644
--- a/declarative/mainwindow.go
+++ b/declarative/mainwindow.go
@@ -13,6 +13,7 @@ type MainWindow struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
@@ -70,6 +71,7 @@ func (mw MainWindow) Create() error {
// Window
Background: mw.Background,
ContextMenuItems: mw.ContextMenuItems,
+ DoubleBuffering: mw.DoubleBuffering,
Enabled: mw.Enabled,
Font: mw.Font,
MaxSize: mw.MaxSize,
diff --git a/declarative/numberedit.go b/declarative/numberedit.go
index 25461706..c0d8e637 100644
--- a/declarative/numberedit.go
+++ b/declarative/numberedit.go
@@ -15,6 +15,7 @@ type NumberEdit struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/numberlabel.go b/declarative/numberlabel.go
index db5477e9..d3bf2141 100644
--- a/declarative/numberlabel.go
+++ b/declarative/numberlabel.go
@@ -15,6 +15,7 @@ type NumberLabel struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/progressbar.go b/declarative/progressbar.go
index 933ca149..c621ae20 100644
--- a/declarative/progressbar.go
+++ b/declarative/progressbar.go
@@ -15,6 +15,7 @@ type ProgressBar struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/pushbutton.go b/declarative/pushbutton.go
index 2b86c446..1e9e037d 100644
--- a/declarative/pushbutton.go
+++ b/declarative/pushbutton.go
@@ -15,6 +15,7 @@ type PushButton struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/radiobutton.go b/declarative/radiobutton.go
index 5e35a58b..d617fa76 100644
--- a/declarative/radiobutton.go
+++ b/declarative/radiobutton.go
@@ -15,6 +15,7 @@ type RadioButton struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/radiobuttongroupbox.go b/declarative/radiobuttongroupbox.go
index 1df041cf..9bdfa238 100644
--- a/declarative/radiobuttongroupbox.go
+++ b/declarative/radiobuttongroupbox.go
@@ -15,6 +15,7 @@ type RadioButtonGroupBox struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/scrollview.go b/declarative/scrollview.go
index ffb5aa5f..4334ce3c 100644
--- a/declarative/scrollview.go
+++ b/declarative/scrollview.go
@@ -15,6 +15,7 @@ type ScrollView struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/separator.go b/declarative/separator.go
index 976fadc4..3079aa94 100644
--- a/declarative/separator.go
+++ b/declarative/separator.go
@@ -15,6 +15,7 @@ type HSeparator struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/slider.go b/declarative/slider.go
index 35378ef7..4bb9fecc 100644
--- a/declarative/slider.go
+++ b/declarative/slider.go
@@ -15,6 +15,7 @@ type Slider struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/splitbutton.go b/declarative/splitbutton.go
index ca9c07a5..71ae6b4a 100644
--- a/declarative/splitbutton.go
+++ b/declarative/splitbutton.go
@@ -15,6 +15,7 @@ type SplitButton struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/splitter.go b/declarative/splitter.go
index 01b28000..a893f228 100644
--- a/declarative/splitter.go
+++ b/declarative/splitter.go
@@ -15,6 +15,7 @@ type HSplitter struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/tableview.go b/declarative/tableview.go
index 23c836be..27b3ebf1 100644
--- a/declarative/tableview.go
+++ b/declarative/tableview.go
@@ -16,6 +16,7 @@ type TableView struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/tabpage.go b/declarative/tabpage.go
index f00008ef..2d1757bf 100644
--- a/declarative/tabpage.go
+++ b/declarative/tabpage.go
@@ -15,6 +15,7 @@ type TabPage struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/tabwidget.go b/declarative/tabwidget.go
index ac9d89a5..d4d5213f 100644
--- a/declarative/tabwidget.go
+++ b/declarative/tabwidget.go
@@ -15,6 +15,7 @@ type TabWidget struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/textedit.go b/declarative/textedit.go
index 5cdc2989..923a209e 100644
--- a/declarative/textedit.go
+++ b/declarative/textedit.go
@@ -16,6 +16,7 @@ type TextEdit struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/textlabel.go b/declarative/textlabel.go
index ec0b2064..8108ebf6 100644
--- a/declarative/textlabel.go
+++ b/declarative/textlabel.go
@@ -30,6 +30,7 @@ type TextLabel struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/toolbar.go b/declarative/toolbar.go
index 93547626..d996bf35 100644
--- a/declarative/toolbar.go
+++ b/declarative/toolbar.go
@@ -24,6 +24,7 @@ type ToolBar struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/toolbutton.go b/declarative/toolbutton.go
index df1ed915..aa6556ba 100644
--- a/declarative/toolbutton.go
+++ b/declarative/toolbutton.go
@@ -15,6 +15,7 @@ type ToolButton struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/treeview.go b/declarative/treeview.go
index d0b3bc97..1a6ac949 100644
--- a/declarative/treeview.go
+++ b/declarative/treeview.go
@@ -15,6 +15,7 @@ type TreeView struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/declarative/webview.go b/declarative/webview.go
index c9c3b12f..651fa4a5 100644
--- a/declarative/webview.go
+++ b/declarative/webview.go
@@ -15,6 +15,7 @@ type WebView struct {
Background Brush
ContextMenuItems []MenuItem
+ DoubleBuffering bool
Enabled Property
Font Font
MaxSize Size
diff --git a/dialog.go b/dialog.go
index a0eddbbb..8f4f0eca 100644
--- a/dialog.go
+++ b/dialog.go
@@ -8,9 +8,7 @@ package walk
import (
"unsafe"
-)
-import (
"github.com/lxn/win"
)
diff --git a/flowlayout.go b/flowlayout.go
index e5c79cce..6292e281 100644
--- a/flowlayout.go
+++ b/flowlayout.go
@@ -11,13 +11,8 @@ import (
)
type FlowLayout struct {
- container Container
+ LayoutBase
hwnd2StretchFactor map[win.HWND]int
- margins Margins
- sizeAndDPI2MinSize map[sizeAndDPI]Size
- spacing int
- alignment Alignment2D
- resetNeeded bool
}
type flowLayoutSection struct {
@@ -32,77 +27,17 @@ type flowLayoutSectionItem struct {
}
func NewFlowLayout() *FlowLayout {
- return &FlowLayout{sizeAndDPI2MinSize: make(map[sizeAndDPI]Size)}
-}
-
-func (l *FlowLayout) Container() Container {
- return l.container
-}
-
-func (l *FlowLayout) SetContainer(value Container) {
- if value != l.container {
- if l.container != nil {
- l.container.SetLayout(nil)
- }
-
- l.container = value
-
- if value != nil && value.Layout() != Layout(l) {
- value.SetLayout(l)
-
- l.Update(true)
- }
- }
-}
-
-func (l *FlowLayout) Margins() Margins {
- return l.margins
-}
-
-func (l *FlowLayout) SetMargins(value Margins) error {
- if value.HNear < 0 || value.VNear < 0 || value.HFar < 0 || value.VFar < 0 {
- return newError("margins must be positive")
+ l := &FlowLayout{
+ LayoutBase: LayoutBase{
+ sizeAndDPI2MinSize: make(map[sizeAndDPI]Size),
+ margins96dpi: Margins{9, 9, 9, 9},
+ spacing96dpi: 6,
+ },
+ hwnd2StretchFactor: make(map[win.HWND]int),
}
+ l.layout = l
- l.margins = value
-
- return nil
-}
-
-func (l *FlowLayout) Spacing() int {
- return l.spacing
-}
-
-func (l *FlowLayout) SetSpacing(value int) error {
- if value != l.spacing {
- if value < 0 {
- return newError("spacing cannot be negative")
- }
-
- l.spacing = value
-
- l.Update(false)
- }
-
- return nil
-}
-
-func (l *FlowLayout) Alignment() Alignment2D {
- return l.alignment
-}
-
-func (l *FlowLayout) SetAlignment(alignment Alignment2D) error {
- if alignment != l.alignment {
- if alignment < AlignHVDefault || alignment > AlignHFarVFar {
- return newError("invalid Alignment value")
- }
-
- l.alignment = alignment
-
- l.Update(false)
- }
-
- return nil
+ return l
}
func (l *FlowLayout) StretchFactor(widget Widget) int {
@@ -176,9 +111,6 @@ func (l *FlowLayout) MinSizeForSize(size Size) Size {
var s Size
var maxPrimary int
- wb := l.container.AsWindowBase()
- spacing := wb.intFrom96DPI(l.spacing)
-
for i, section := range sections {
var widgets []Widget
var sectionMinWidth int
@@ -187,12 +119,12 @@ func (l *FlowLayout) MinSizeForSize(size Size) Size {
sectionMinWidth += item.minSize.Width
}
- sectionMinWidth += (len(section.items) - 1) * spacing
+ sectionMinWidth += (len(section.items) - 1) * l.spacing
maxPrimary = maxi(maxPrimary, sectionMinWidth)
bounds.Height = section.secondaryMinSize
- margins := wb.marginsFrom96DPI(l.margins)
+ margins := l.margins
if i > 0 {
margins.VNear = 0
}
@@ -200,8 +132,7 @@ func (l *FlowLayout) MinSizeForSize(size Size) Size {
margins.VFar = 0
}
-
- layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, spacing, l.hwnd2StretchFactor)
+ layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return Size{}
}
@@ -222,13 +153,13 @@ func (l *FlowLayout) MinSizeForSize(size Size) Size {
s.Height += maxSecondary
- bounds.Y += maxSecondary + spacing
+ bounds.Y += maxSecondary + l.spacing
}
s.Width = maxPrimary
- s.Width += wb.intFrom96DPI(l.margins.HNear + l.margins.HFar)
- s.Height += wb.intFrom96DPI(l.margins.VNear + l.margins.VFar + (len(sections)-1)*l.spacing)
+ s.Width += l.margins.HNear + l.margins.HFar
+ s.Height += l.margins.VNear + l.margins.VFar + (len(sections)-1)*l.spacing
if s.Width > 0 && s.Height > 0 {
l.sizeAndDPI2MinSize[sizeAndDPI{size, dpi}] = s
@@ -267,8 +198,6 @@ func (l *FlowLayout) Update(reset bool) error {
bounds := l.container.ClientBounds()
sections := l.sectionsForPrimarySize(bounds.Width)
- wb := l.container.AsWindowBase()
-
for i, section := range sections {
var widgets []Widget
for _, item := range section.items {
@@ -277,7 +206,7 @@ func (l *FlowLayout) Update(reset bool) error {
bounds.Height = section.secondaryMinSize
- margins := wb.marginsFrom96DPI(l.margins)
+ margins := l.margins
if i > 0 {
margins.VNear = 0
}
@@ -285,9 +214,7 @@ func (l *FlowLayout) Update(reset bool) error {
margins.VFar = 0
}
- spacing := wb.intFrom96DPI(l.spacing)
-
- layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, spacing, l.hwnd2StretchFactor)
+ layoutItems, err := boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor)
if err != nil {
return err
}
@@ -306,7 +233,7 @@ func (l *FlowLayout) Update(reset bool) error {
bounds.Height = maxSecondary + margins.VNear + margins.VFar
- if layoutItems, err = boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, spacing, l.hwnd2StretchFactor); err != nil {
+ if layoutItems, err = boxLayoutItems(widgets, Horizontal, l.alignment, bounds, margins, l.spacing, l.hwnd2StretchFactor); err != nil {
return err
}
@@ -314,7 +241,7 @@ func (l *FlowLayout) Update(reset bool) error {
return err
}
- bounds.Y += bounds.Height + spacing
+ bounds.Y += bounds.Height + l.spacing
}
return nil
@@ -326,17 +253,14 @@ func (l *FlowLayout) sectionsForPrimarySize(primarySize int) []flowLayoutSection
var sections []flowLayoutSection
- margins := l.container.AsWindowBase().marginsFrom96DPI(l.margins)
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
-
section := flowLayoutSection{
- primarySpaceLeft: primarySize - margins.HNear - margins.HFar,
+ primarySpaceLeft: primarySize - l.margins.HNear - l.margins.HFar,
}
addSection := func() {
sections = append(sections, section)
section.items = nil
- section.primarySpaceLeft = primarySize - margins.HNear - margins.HFar
+ section.primarySpaceLeft = primarySize - l.margins.HNear - l.margins.HFar
section.secondaryMinSize = 0
}
@@ -354,7 +278,7 @@ func (l *FlowLayout) sectionsForPrimarySize(primarySize int) []flowLayoutSection
addItem := func() {
section.items = append(section.items, item)
if len(section.items) > 1 {
- section.primarySpaceLeft -= spacing
+ section.primarySpaceLeft -= l.spacing
}
section.primarySpaceLeft -= item.minSize.Width
@@ -364,7 +288,7 @@ func (l *FlowLayout) sectionsForPrimarySize(primarySize int) []flowLayoutSection
if section.primarySpaceLeft < item.minSize.Width && len(section.items) == 0 {
addItem()
addSection()
- } else if section.primarySpaceLeft < spacing+item.minSize.Width && len(section.items) > 0 {
+ } else if section.primarySpaceLeft < l.spacing+item.minSize.Width && len(section.items) > 0 {
addSection()
addItem()
} else {
@@ -377,8 +301,8 @@ func (l *FlowLayout) sectionsForPrimarySize(primarySize int) []flowLayoutSection
}
if len(sections) > 0 {
- sections[0].secondaryMinSize += margins.VNear
- sections[len(sections)-1].secondaryMinSize += margins.VFar
+ sections[0].secondaryMinSize += l.margins.VNear
+ sections[len(sections)-1].secondaryMinSize += l.margins.VFar
}
return sections
diff --git a/fontresource.go b/fontresource.go
new file mode 100644
index 00000000..1496232a
--- /dev/null
+++ b/fontresource.go
@@ -0,0 +1,83 @@
+// Copyright 2010 The Walk Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build windows
+
+package walk
+
+import (
+ "github.com/lxn/win"
+ "syscall"
+)
+
+// FontMemResource represents a font resource loaded into memory from
+// the application's resources.
+type FontMemResource struct {
+ hFontResource win.HANDLE
+}
+
+func newFontMemResource(resourceName *uint16) (*FontMemResource, error) {
+ hModule := win.HMODULE(win.GetModuleHandle(nil))
+ if hModule == win.HMODULE(0) {
+ return nil, lastError("GetModuleHandle")
+ }
+
+ hres := win.FindResource(hModule, resourceName, win.MAKEINTRESOURCE(8) /*RT_FONT*/)
+ if hres == win.HRSRC(0) {
+ return nil, lastError("FindResource")
+ }
+
+ size := win.SizeofResource(hModule, hres)
+ if size == 0 {
+ return nil, lastError("SizeofResource")
+ }
+
+ hResLoad := win.LoadResource(hModule, hres)
+ if hResLoad == win.HGLOBAL(0) {
+ return nil, lastError("LoadResource")
+ }
+
+ ptr := win.LockResource(hResLoad)
+ if ptr == 0 {
+ return nil, lastError("LockResource")
+ }
+
+ numFonts := uint32(0)
+ hFontResource := win.AddFontMemResourceEx(ptr, size, nil, &numFonts)
+
+ if hFontResource == win.HANDLE(0) || numFonts == 0 {
+ return nil, lastError("AddFontMemResource")
+ }
+
+ return &FontMemResource { hFontResource: hFontResource }, nil
+}
+
+// NewFontMemResourceByName function loads a font resource from the executable's resources
+// using the resource name.
+// The font must be embedded into resources using corresponding operator in the
+// application's RC script.
+func NewFontMemResourceByName(name string) (*FontMemResource, error) {
+ lpstr, err := syscall.UTF16PtrFromString(name)
+ if err != nil {
+ return nil, err
+ }
+
+ return newFontMemResource(lpstr)
+}
+
+// NewFontMemResourceById function loads a font resource from the executable's resources
+// using the resource ID.
+// The font must be embedded into resources using corresponding operator in the
+// application's RC script.
+func NewFontMemResourceById(id int) (*FontMemResource, error) {
+ return newFontMemResource(win.MAKEINTRESOURCE(uintptr(id)))
+}
+
+// Dispose removes the font resource from memory
+func (fmr *FontMemResource) Dispose() {
+ if fmr.hFontResource != 0 {
+ win.RemoveFontMemResourceEx(fmr.hFontResource)
+ fmr.hFontResource = 0
+ }
+}
diff --git a/form.go b/form.go
index ba4cdda2..74878352 100644
--- a/form.go
+++ b/form.go
@@ -712,7 +712,7 @@ func (fb *FormBase) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) u
rc := (*win.RECT)(unsafe.Pointer(lParam))
fb.window.SetBounds(rectangleFromRECT(*rc))
- fb.applyFont(fb.Font())
+ fb.applyDPI(int(win.HIWORD(uint32(wParam))))
case win.WM_SYSCOMMAND:
if wParam == win.SC_CLOSE {
diff --git a/gridlayout.go b/gridlayout.go
index 82938c81..c418a956 100644
--- a/gridlayout.go
+++ b/gridlayout.go
@@ -30,97 +30,27 @@ type gridLayoutWidgetInfo struct {
}
type GridLayout struct {
- container Container
- margins Margins
- spacing int
- alignment Alignment2D
+ LayoutBase
rowStretchFactors []int
columnStretchFactors []int
widgetBase2Info map[*WidgetBase]*gridLayoutWidgetInfo
cells [][]gridLayoutCell
- sizeAndDPI2MinSize map[sizeAndDPI]Size
- resetNeeded bool
}
func NewGridLayout() *GridLayout {
l := &GridLayout{
- widgetBase2Info: make(map[*WidgetBase]*gridLayoutWidgetInfo),
- sizeAndDPI2MinSize: make(map[sizeAndDPI]Size),
+ LayoutBase: LayoutBase{
+ sizeAndDPI2MinSize: make(map[sizeAndDPI]Size),
+ margins96dpi: Margins{9, 9, 9, 9},
+ spacing96dpi: 6,
+ },
+ widgetBase2Info: make(map[*WidgetBase]*gridLayoutWidgetInfo),
}
+ l.layout = l
return l
}
-func (l *GridLayout) Container() Container {
- return l.container
-}
-
-func (l *GridLayout) SetContainer(value Container) {
- if value != l.container {
- if l.container != nil {
- l.container.SetLayout(nil)
- }
-
- l.container = value
-
- if value != nil && value.Layout() != Layout(l) {
- value.SetLayout(l)
-
- l.Update(true)
- }
- }
-}
-
-func (l *GridLayout) Margins() Margins {
- return l.margins
-}
-
-func (l *GridLayout) SetMargins(value Margins) error {
- if value.HNear < 0 || value.VNear < 0 || value.HFar < 0 || value.VFar < 0 {
- return newError("margins must be positive")
- }
-
- l.margins = value
-
- return nil
-}
-
-func (l *GridLayout) Spacing() int {
- return l.spacing
-}
-
-func (l *GridLayout) SetSpacing(value int) error {
- if value != l.spacing {
- if value < 0 {
- return newError("spacing cannot be negative")
- }
-
- l.spacing = value
-
- l.Update(false)
- }
-
- return nil
-}
-
-func (l *GridLayout) Alignment() Alignment2D {
- return l.alignment
-}
-
-func (l *GridLayout) SetAlignment(alignment Alignment2D) error {
- if alignment != l.alignment {
- if alignment < AlignHVDefault || alignment > AlignHFarVFar {
- return newError("invalid Alignment value")
- }
-
- l.alignment = alignment
-
- l.Update(false)
- }
-
- return nil
-}
-
func (l *GridLayout) sufficientStretchFactors(stretchFactors []int, required int) []int {
oldLen := len(stretchFactors)
if oldLen < required {
@@ -467,17 +397,13 @@ func (l *GridLayout) MinSizeForSize(size Size) Size {
heights[row] = maxHeight
}
- margins := l.container.AsWindowBase().marginsFrom96DPI(l.margins)
-
- width := margins.HNear + margins.HFar
- height := margins.VNear + margins.VFar
-
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
+ width := l.margins.HNear + l.margins.HFar
+ height := l.margins.VNear + l.margins.VFar
for i, w := range ws {
if w > 0 {
if i > 0 {
- width += spacing
+ width += l.spacing
}
width += w
}
@@ -485,7 +411,7 @@ func (l *GridLayout) MinSizeForSize(size Size) Size {
for i, h := range heights {
if h > 0 {
if i > 0 {
- height += spacing
+ height += l.spacing
}
height += h
}
@@ -500,13 +426,12 @@ func (l *GridLayout) MinSizeForSize(size Size) Size {
func (l *GridLayout) spannedWidth(info *gridLayoutWidgetInfo, widths []int) int {
width := 0
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
for i := info.cell.column; i < info.cell.column+info.spanHorz; i++ {
if w := widths[i]; w > 0 {
width += w
if i > info.cell.column {
- width += spacing
+ width += l.spacing
}
}
}
@@ -516,13 +441,12 @@ func (l *GridLayout) spannedWidth(info *gridLayoutWidgetInfo, widths []int) int
func (l *GridLayout) spannedHeight(info *gridLayoutWidgetInfo, heights []int) int {
height := 0
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
for i := info.cell.row; i < info.cell.row+info.spanVert; i++ {
if h := heights[i]; h > 0 {
height += h
if i > info.cell.row {
- height += spacing
+ height += l.spacing
}
}
}
@@ -601,9 +525,6 @@ func (l *GridLayout) Update(reset bool) error {
items := make([]layoutResultItem, 0, len(l.widgetBase2Info))
- margins := l.container.AsWindowBase().marginsFrom96DPI(l.margins)
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
-
for wb, info := range l.widgetBase2Info {
widget := wb.window.(Widget)
@@ -611,17 +532,17 @@ func (l *GridLayout) Update(reset bool) error {
continue
}
- x := margins.HNear
+ x := l.margins.HNear
for i := 0; i < info.cell.column; i++ {
if w := widths[i]; w > 0 {
- x += w + spacing
+ x += w + l.spacing
}
}
- y := margins.VNear
+ y := l.margins.VNear
for i := 0; i < info.cell.row; i++ {
if h := heights[i]; h > 0 {
- y += h + spacing
+ y += h + l.spacing
}
}
@@ -800,24 +721,20 @@ func (l *GridLayout) sectionSizesForSpace(orientation Orientation, space int, wi
sort.Stable(sortedSections)
- margins := l.container.AsWindowBase().marginsFrom96DPI(l.margins)
-
if orientation == Horizontal {
- space -= margins.HNear + margins.HFar
+ space -= l.margins.HNear + l.margins.HFar
} else {
- space -= margins.VNear + margins.VFar
+ space -= l.margins.VNear + l.margins.VFar
}
- spacing := l.container.AsWindowBase().intFrom96DPI(l.spacing)
-
var spacingRemaining int
for _, max := range maxSizes {
if max > 0 {
- spacingRemaining += spacing
+ spacingRemaining += l.spacing
}
}
if spacingRemaining > 0 {
- spacingRemaining -= spacing
+ spacingRemaining -= l.spacing
}
offsets := [3]int{0, sectionCountWithGreedyNonSpacer, sectionCountWithGreedyNonSpacer + sectionCountWithGreedySpacer}
@@ -851,8 +768,8 @@ func (l *GridLayout) sectionSizesForSpace(orientation Orientation, space int, wi
minSizesRemaining -= min
stretchFactorsRemaining -= stretch
- space -= (size + spacing)
- spacingRemaining -= spacing
+ space -= (size + l.spacing)
+ spacingRemaining -= l.spacing
}
}
diff --git a/tableview.go b/tableview.go
index e84ec667..23f68b2c 100644
--- a/tableview.go
+++ b/tableview.go
@@ -1106,23 +1106,38 @@ func (tv *TableView) SetSelectedIndexes(indexes []int) error {
return newError("SendMessage(LVM_SETITEMSTATE)")
}
+ selectAll := false
lvi.State = win.LVIS_FOCUSED | win.LVIS_SELECTED
for _, i := range indexes {
- if win.FALSE == win.SendMessage(tv.hwndFrozenLV, win.LVM_SETITEMSTATE, uintptr(i), lp) {
+ val := uintptr(i)
+ if i == -1 {
+ selectAll = true
+ val = ^uintptr(0)
+ }
+ if win.FALSE == win.SendMessage(tv.hwndFrozenLV, win.LVM_SETITEMSTATE, val, lp) && i != -1 {
return newError("SendMessage(LVM_SETITEMSTATE)")
}
- if win.FALSE == win.SendMessage(tv.hwndNormalLV, win.LVM_SETITEMSTATE, uintptr(i), lp) {
+ if win.FALSE == win.SendMessage(tv.hwndNormalLV, win.LVM_SETITEMSTATE, val, lp) && i != -1 {
return newError("SendMessage(LVM_SETITEMSTATE)")
}
}
- idxs := make([]int, len(indexes))
+ if !selectAll {
+ idxs := make([]int, len(indexes))
- for i, j := range indexes {
- idxs[i] = j
- }
+ for i, j := range indexes {
+ idxs[i] = j
+ }
- tv.selectedIndexes = idxs
+ tv.selectedIndexes = idxs
+ } else {
+ count := int(win.SendMessage(tv.hwndNormalLV, win.LVM_GETSELECTEDCOUNT, 0, 0))
+ idxs := make([]int, count)
+ for i := range idxs {
+ idxs[i] = i
+ }
+ tv.selectedIndexes = idxs
+ }
return nil
}
diff --git a/tabpagelist.go b/tabpagelist.go
index b425b301..ce05ddf4 100644
--- a/tabpagelist.go
+++ b/tabpagelist.go
@@ -108,6 +108,10 @@ func (l *TabPageList) Insert(index int, item *TabPage) error {
}
}
+ if item.Layout() != nil {
+ item.Layout().Update(false)
+ }
+
return nil
}
diff --git a/toolbar.go b/toolbar.go
index 82570646..4664f363 100644
--- a/toolbar.go
+++ b/toolbar.go
@@ -329,7 +329,7 @@ func (tb *ToolBar) initButtonForAction(action *Action, state, style *byte, image
*style |= win.BTNS_GROUP
}
- if tb.buttonStyle != ToolBarButtonImageOnly {
+ if tb.buttonStyle != ToolBarButtonImageOnly && len(action.text) > 0 {
*style |= win.BTNS_SHOWTEXT
}
@@ -358,7 +358,11 @@ func (tb *ToolBar) initButtonForAction(action *Action, state, style *byte, image
actionText = action.Text()
}
- *text = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(actionText)))
+ if len(actionText) != 0 {
+ *text = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(actionText)))
+ } else if len(action.toolTip) != 0 {
+ *text = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(action.toolTip)))
+ }
return
}
diff --git a/tooltip.go b/tooltip.go
index 5aa996d0..dde551ea 100644
--- a/tooltip.go
+++ b/tooltip.go
@@ -15,8 +15,10 @@ import (
"github.com/lxn/win"
)
-// see https://msdn.microsoft.com/en-us/library/windows/desktop/bb760416(v=vs.85).aspx
-const maxToolTipTextLen = 80 // including NUL terminator
+// https://msdn.microsoft.com/en-us/library/windows/desktop/bb760416(v=vs.85).aspx says 80,
+// but in reality, that hasn't been enforced for many many Windows versions. So we give it
+// 1024 instead.
+const maxToolTipTextLen = 1024 // including NUL terminator
func init() {
var err error
diff --git a/util.go b/util.go
index c07daeba..6036b581 100644
--- a/util.go
+++ b/util.go
@@ -256,6 +256,21 @@ func applyFontToDescendants(window Window, font *Font) {
})
}
+func applyDPIToDescendants(window Window, dpi int) {
+ wb := window.AsWindowBase()
+ wb.applyDPI(dpi)
+
+ walkDescendants(window, func(w Window) bool {
+ if w.Handle() == wb.hWnd {
+ return true
+ }
+
+ w.(applyDPIer).applyDPI(dpi)
+
+ return true
+ })
+}
+
func walkDescendants(window Window, f func(w Window) bool) {
window = window.AsWindowBase().window
diff --git a/widget.go b/widget.go
index e67e90bd..83a73d29 100644
--- a/widget.go
+++ b/widget.go
@@ -470,18 +470,9 @@ func (wb *WidgetBase) updateParentLayoutWithReset(reset bool) error {
layout := parent.Layout()
- var sizeAndDPI2MinSize map[sizeAndDPI]Size
- switch l := layout.(type) {
- case *BoxLayout:
- sizeAndDPI2MinSize = l.sizeAndDPI2MinSize
+ if lb, ok := layout.(interface{ sizeAndDPIToMinSize() map[sizeAndDPI]Size }); ok {
+ sizeAndDPI2MinSize := lb.sizeAndDPIToMinSize()
- case *GridLayout:
- sizeAndDPI2MinSize = l.sizeAndDPI2MinSize
-
- case *FlowLayout:
- sizeAndDPI2MinSize = l.sizeAndDPI2MinSize
- }
- if sizeAndDPI2MinSize != nil {
for k := range sizeAndDPI2MinSize {
delete(sizeAndDPI2MinSize, k)
}
diff --git a/window.go b/window.go
index b15b79a1..33e32204 100644
--- a/window.go
+++ b/window.go
@@ -86,6 +86,10 @@ type Window interface {
// of.
Disposing() *Event
+ // DoubleBuffering returns whether double buffering of the
+ // drawing is enabled, which may help reduce flicker.
+ DoubleBuffering() bool
+
// DPI returns the current DPI value of the Window.
DPI() int
@@ -322,9 +326,6 @@ type WindowBase struct {
minSize Size
background Brush
cursor Cursor
- suspended bool
- visible bool
- enabled bool
name2Property map[string]Property
enabledProperty Property
enabledChangedPublisher EventPublisher
@@ -333,6 +334,10 @@ type WindowBase struct {
focusedProperty Property
focusedChangedPublisher EventPublisher
calcTextSizeInfoPrev *calcTextSizeInfo
+ dpi int
+ suspended bool
+ visible bool
+ enabled bool
}
var (
@@ -774,6 +779,12 @@ func (wb *WindowBase) SetCursor(value Cursor) {
wb.cursor = value
}
+// DoubleBuffering returns whether double buffering of the
+// drawing is enabled, which may help reduce flicker.
+func (wb *WindowBase) DoubleBuffering() bool {
+ return wb.hasExtendedStyleBits(win.WS_EX_COMPOSITED)
+}
+
// SetDoubleBuffering enables or disables double buffering of the
// drawing, which may help reduce flicker.
func (wb *WindowBase) SetDoubleBuffering(enabled bool) error {
@@ -782,15 +793,37 @@ func (wb *WindowBase) SetDoubleBuffering(enabled bool) error {
// DPI returns the current DPI value of the WindowBase.
func (wb *WindowBase) DPI() int {
- return int(win.GetDpiForWindow(wb.hWnd))
+ if wb.dpi == 0 {
+ if widget, ok := wb.window.(Widget); ok {
+ if parent := widget.Parent(); parent != nil {
+ wb.dpi = parent.DPI()
+ }
+ }
+
+ if wb.dpi == 0 {
+ wb.dpi = int(win.GetDpiForWindow(wb.hWnd))
+ }
+ }
+
+ return wb.dpi
+}
+
+type applyDPIer interface {
+ applyDPI(dpi int)
+}
+
+func (wb *WindowBase) applyDPI(dpi int) {
+ wb.dpi = dpi
+
+ wb.window.SetFont(wb.window.Font())
}
func (wb *WindowBase) intFrom96DPI(value int) int {
- return wb.scaleInt(value, float64(wb.DPI()) / 96.0)
+ return wb.scaleInt(value, float64(wb.DPI())/96.0)
}
func (wb *WindowBase) intTo96DPI(value int) int {
- return wb.scaleInt(value, 96.0 / float64(wb.DPI()))
+ return wb.scaleInt(value, 96.0/float64(wb.DPI()))
}
func (wb *WindowBase) scaleInt(value int, scale float64) int {
@@ -798,28 +831,28 @@ func (wb *WindowBase) scaleInt(value int, scale float64) int {
}
func (wb *WindowBase) marginsFrom96DPI(value Margins) Margins {
- return wb.scaleMargins(value, float64(wb.DPI()) / 96.0)
+ return wb.scaleMargins(value, float64(wb.DPI())/96.0)
}
func (wb *WindowBase) marginsTo96DPI(value Margins) Margins {
- return wb.scaleMargins(value, 96.0 / float64(wb.DPI()))
+ return wb.scaleMargins(value, 96.0/float64(wb.DPI()))
}
func (wb *WindowBase) scaleMargins(value Margins, scale float64) Margins {
return Margins{
HNear: int(float64(value.HNear) * scale),
VNear: int(float64(value.VNear) * scale),
- HFar: int(float64(value.HFar) * scale),
- VFar: int(float64(value.VFar) * scale),
+ HFar: int(float64(value.HFar) * scale),
+ VFar: int(float64(value.VFar) * scale),
}
}
func (wb *WindowBase) pointFrom96DPI(value Point) Point {
- return wb.scalePoint(value, float64(wb.DPI()) / 96.0)
+ return wb.scalePoint(value, float64(wb.DPI())/96.0)
}
func (wb *WindowBase) pointTo96DPI(value Point) Point {
- return wb.scalePoint(value, 96.0 / float64(wb.DPI()))
+ return wb.scalePoint(value, 96.0/float64(wb.DPI()))
}
func (wb *WindowBase) scalePoint(value Point, scale float64) Point {
@@ -830,33 +863,33 @@ func (wb *WindowBase) scalePoint(value Point, scale float64) Point {
}
func (wb *WindowBase) rectangleFrom96DPI(value Rectangle) Rectangle {
- return wb.scaleRectangle(value, float64(wb.DPI()) / 96.0)
+ return wb.scaleRectangle(value, float64(wb.DPI())/96.0)
}
func (wb *WindowBase) rectangleTo96DPI(value Rectangle) Rectangle {
- return wb.scaleRectangle(value, 96.0 / float64(wb.DPI()))
+ return wb.scaleRectangle(value, 96.0/float64(wb.DPI()))
}
func (wb *WindowBase) scaleRectangle(value Rectangle, scale float64) Rectangle {
return Rectangle{
- X: int(float64(value.X) * scale),
- Y: int(float64(value.Y) * scale),
- Width: int(float64(value.Width) * scale),
+ X: int(float64(value.X) * scale),
+ Y: int(float64(value.Y) * scale),
+ Width: int(float64(value.Width) * scale),
Height: int(float64(value.Height) * scale),
}
}
func (wb *WindowBase) sizeFrom96DPI(value Size) Size {
- return wb.scaleSize(value, float64(wb.DPI()) / 96.0)
+ return wb.scaleSize(value, float64(wb.DPI())/96.0)
}
func (wb *WindowBase) sizeTo96DPI(value Size) Size {
- return wb.scaleSize(value, 96.0 / float64(wb.DPI()))
+ return wb.scaleSize(value, 96.0/float64(wb.DPI()))
}
func (wb *WindowBase) scaleSize(value Size, scale float64) Size {
return Size{
- Width: int(float64(value.Width) * scale),
+ Width: int(float64(value.Width) * scale),
Height: int(float64(value.Height) * scale),
}
}
@@ -1218,8 +1251,8 @@ type fontInfoAndDPI struct {
}
var (
- dialogBaseUnitsUTF16StringPtr = syscall.StringToUTF16Ptr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
- fontInfoAndDPI2DialogBaseUnits = make(map[fontInfoAndDPI]Size)
+ dialogBaseUnitsUTF16StringPtr = syscall.StringToUTF16Ptr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
+ fontInfoAndDPI2DialogBaseUnits = make(map[fontInfoAndDPI]Size)
)
func (wb *WindowBase) dialogBaseUnits() Size {
@@ -1228,9 +1261,9 @@ func (wb *WindowBase) dialogBaseUnits() Size {
font := wb.window.Font()
fi := fontInfoAndDPI{
fontInfo: fontInfo{
- family: font.Family(),
- pointSize: font.PointSize(),
- style: font.Style(),
+ family: font.Family(),
+ pointSize: font.PointSize(),
+ style: font.Style(),
},
dpi: wb.DPI()}
if s, ok := fontInfoAndDPI2DialogBaseUnits[fi]; ok {