mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 17:08:38 +00:00
uic: layout spacing and margins
This commit is contained in:
parent
975f18b7b0
commit
a3d527ca6b
@ -16,6 +16,7 @@ type UiLayoutItem struct {
|
|||||||
type UiLayout struct {
|
type UiLayout struct {
|
||||||
Class string `xml:"class,attr"`
|
Class string `xml:"class,attr"`
|
||||||
Name string `xml:"name,attr"`
|
Name string `xml:"name,attr"`
|
||||||
|
Properties []UiProperty `xml:"property"`
|
||||||
Items []UiLayoutItem `xml:"item"`
|
Items []UiLayoutItem `xml:"item"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +81,11 @@ type UiResources struct {
|
|||||||
type UiConnections struct {
|
type UiConnections struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UiLayoutDefault struct {
|
||||||
|
Spacing *int `xml:"spacing,attr,omitempty"`
|
||||||
|
Margin *int `xml:"margin,attr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type UiFile struct {
|
type UiFile struct {
|
||||||
XMLName xml.Name // should always be xml.Name{Local: "ui"}
|
XMLName xml.Name // should always be xml.Name{Local: "ui"}
|
||||||
|
|
||||||
@ -88,4 +94,5 @@ type UiFile struct {
|
|||||||
Widget UiWidget `xml:"widget"` // There's only one root widget
|
Widget UiWidget `xml:"widget"` // There's only one root widget
|
||||||
Resources UiResources `xml:"resources"`
|
Resources UiResources `xml:"resources"`
|
||||||
Connections UiConnections `xml:"connections"`
|
Connections UiConnections `xml:"connections"`
|
||||||
|
LayoutDefault *UiLayoutDefault `xml:"layoutdefault,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultGridMargin = 11
|
||||||
|
DefaultSpacing = 6
|
||||||
|
)
|
||||||
|
|
||||||
func collectClassNames_Widget(u *UiWidget) []string {
|
func collectClassNames_Widget(u *UiWidget) []string {
|
||||||
var ret []string
|
var ret []string
|
||||||
if u.Name != "" {
|
if u.Name != "" {
|
||||||
@ -58,6 +63,83 @@ func normalizeEnumName(s string) string {
|
|||||||
return `qt.` + strings.Replace(s, `::`, `__`, -1)
|
return `qt.` + strings.Replace(s, `::`, `__`, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderProperties(properties []UiProperty, ret *strings.Builder, targetName, parentClass string, isLayout bool) error {
|
||||||
|
|
||||||
|
contentsMargins := [4]int{DefaultGridMargin, DefaultGridMargin, DefaultGridMargin, DefaultGridMargin} // left, top, right, bottom
|
||||||
|
customContentsMargins := false
|
||||||
|
customSpacing := false
|
||||||
|
|
||||||
|
for _, prop := range properties {
|
||||||
|
setterFunc := `.Set` + strings.ToUpper(string(prop.Name[0])) + prop.Name[1:]
|
||||||
|
|
||||||
|
if prop.Name == "geometry" {
|
||||||
|
if !(prop.RectVal.X == 0 && prop.RectVal.Y == 0) {
|
||||||
|
// Set all 4x properties
|
||||||
|
ret.WriteString(`ui.` + targetName + `.SetGeometry(qt.NewQRect(` + fmt.Sprintf("%d, %d, %d, %d", prop.RectVal.X, prop.RectVal.Y, prop.RectVal.Width, prop.RectVal.Height) + "))\n")
|
||||||
|
|
||||||
|
} else if !(prop.RectVal.Width == 0 && prop.RectVal.Height == 0) {
|
||||||
|
// Only width/height were supplied
|
||||||
|
ret.WriteString(`ui.` + targetName + `.Resize(` + fmt.Sprintf("%d, %d", prop.RectVal.Width, prop.RectVal.Height) + ")\n")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if prop.Name == "leftMargin" {
|
||||||
|
contentsMargins[0] = mustParseInt(*prop.NumberVal)
|
||||||
|
customContentsMargins = true
|
||||||
|
|
||||||
|
} else if prop.Name == "topMargin" {
|
||||||
|
contentsMargins[1] = mustParseInt(*prop.NumberVal)
|
||||||
|
customContentsMargins = true
|
||||||
|
|
||||||
|
} else if prop.Name == "rightMargin" {
|
||||||
|
contentsMargins[2] = mustParseInt(*prop.NumberVal)
|
||||||
|
customContentsMargins = true
|
||||||
|
|
||||||
|
} else if prop.Name == "bottomMargin" {
|
||||||
|
contentsMargins[3] = mustParseInt(*prop.NumberVal)
|
||||||
|
customContentsMargins = true
|
||||||
|
|
||||||
|
} else if prop.StringVal != nil {
|
||||||
|
// "windowTitle", "title", "text"
|
||||||
|
ret.WriteString(`ui.` + targetName + setterFunc + `(` + generateString(prop.StringVal, parentClass) + ")\n")
|
||||||
|
|
||||||
|
} else if prop.NumberVal != nil {
|
||||||
|
// "currentIndex"
|
||||||
|
if prop.Name == "spacing" {
|
||||||
|
customSpacing = true
|
||||||
|
}
|
||||||
|
ret.WriteString(`ui.` + targetName + setterFunc + `(` + *prop.NumberVal + ")\n")
|
||||||
|
|
||||||
|
} else if prop.BoolVal != nil {
|
||||||
|
// "childrenCollapsible"
|
||||||
|
ret.WriteString(`ui.` + targetName + setterFunc + `(` + formatBool(*prop.BoolVal) + ")\n")
|
||||||
|
|
||||||
|
} else if prop.EnumVal != nil {
|
||||||
|
// "frameShape"
|
||||||
|
|
||||||
|
// Newer versions of Qt Designer produce the fully qualified enum
|
||||||
|
// names (A::B::C) but miqt changed to use the short names. Need to
|
||||||
|
// detect the case and convert it to match
|
||||||
|
ret.WriteString(`ui.` + targetName + setterFunc + `(` + normalizeEnumName(*prop.EnumVal) + ")\n")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ret.WriteString("/* miqt-uic: no handler for " + targetName + " property '" + prop.Name + "' */\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if customContentsMargins || isLayout {
|
||||||
|
ret.WriteString(`ui.` + targetName + `.SetContentsMargins(` + fmt.Sprintf("%d, %d, %d, %d", contentsMargins[0], contentsMargins[1], contentsMargins[2], contentsMargins[3]) + ")\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !customSpacing && isLayout {
|
||||||
|
// Layouts must specify spacing, unless, we specified it already
|
||||||
|
ret.WriteString(`ui.` + targetName + `.SetSpacing(` + fmt.Sprintf("%d", DefaultSpacing) + ")\n")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func generateWidget(w UiWidget, parentName string, parentClass string) (string, error) {
|
func generateWidget(w UiWidget, parentName string, parentClass string) (string, error) {
|
||||||
ret := strings.Builder{}
|
ret := strings.Builder{}
|
||||||
|
|
||||||
@ -69,43 +151,10 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
for _, prop := range w.Properties {
|
|
||||||
setterFunc := `.Set` + strings.ToUpper(string(prop.Name[0])) + prop.Name[1:]
|
|
||||||
|
|
||||||
if prop.Name == "geometry" {
|
err := renderProperties(w.Properties, &ret, w.Name, parentClass, false)
|
||||||
if !(prop.RectVal.X == 0 && prop.RectVal.Y == 0) {
|
if err != nil {
|
||||||
// Set all 4x properties
|
return "", err
|
||||||
ret.WriteString(`ui.` + w.Name + `.SetGeometry(qt.NewQRect(` + fmt.Sprintf("%d, %d, %d, %d", prop.RectVal.X, prop.RectVal.Y, prop.RectVal.Width, prop.RectVal.Height) + "))\n")
|
|
||||||
|
|
||||||
} else if !(prop.RectVal.Width == 0 && prop.RectVal.Height == 0) {
|
|
||||||
// Only width/height were supplied
|
|
||||||
ret.WriteString(`ui.` + w.Name + `.Resize(` + fmt.Sprintf("%d, %d", prop.RectVal.Width, prop.RectVal.Height) + ")\n")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if prop.StringVal != nil {
|
|
||||||
// "windowTitle", "title", "text"
|
|
||||||
ret.WriteString(`ui.` + w.Name + setterFunc + `(` + generateString(prop.StringVal, parentClass) + ")\n")
|
|
||||||
|
|
||||||
} else if prop.NumberVal != nil {
|
|
||||||
// "currentIndex"
|
|
||||||
ret.WriteString(`ui.` + w.Name + setterFunc + `(` + *prop.NumberVal + ")\n")
|
|
||||||
|
|
||||||
} else if prop.BoolVal != nil {
|
|
||||||
// "childrenCollapsible"
|
|
||||||
ret.WriteString(`ui.` + w.Name + setterFunc + `(` + formatBool(*prop.BoolVal) + ")\n")
|
|
||||||
|
|
||||||
} else if prop.EnumVal != nil {
|
|
||||||
// "frameShape"
|
|
||||||
|
|
||||||
// Newer versions of Qt Designer produce the fully qualified enum
|
|
||||||
// names (A::B::C) but miqt changed to use the short names. Need to
|
|
||||||
// detect the case and convert it to match
|
|
||||||
ret.WriteString(`ui.` + w.Name + setterFunc + `(` + normalizeEnumName(*prop.EnumVal) + ")\n")
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ret.WriteString("/* miqt-uic: no handler for " + w.Name + " property '" + prop.Name + "' */\n")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
@ -117,15 +166,17 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
|
|||||||
} else if w.Class == "QDockWidget" && parentClass == "QMainWindow" && attr.Name == "dockWidgetArea" {
|
} else if w.Class == "QDockWidget" && parentClass == "QMainWindow" && attr.Name == "dockWidgetArea" {
|
||||||
ret.WriteString(parentName + `.AddDockWidget(qt.DockWidgetArea(` + *attr.NumberVal + `), ui.` + w.Name + `)` + "\n")
|
ret.WriteString(parentName + `.AddDockWidget(qt.DockWidgetArea(` + *attr.NumberVal + `), ui.` + w.Name + `)` + "\n")
|
||||||
|
|
||||||
|
} else if w.Class == "QToolBar" && parentClass == "QMainWindow" && attr.Name == "toolBarArea" {
|
||||||
|
ret.WriteString(parentName + `.AddToolBar(` + normalizeEnumName(*attr.EnumVal) + `, ui.` + w.Name + `)` + "\n")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ret.WriteString("/* miqt-uic: no handler for " + w.Name + " attribute '" + attr.Name + "' */\n")
|
ret.WriteString("/* miqt-uic: no handler for " + w.Name + " attribute '" + attr.Name + "' */\n")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO
|
|
||||||
// w.Attributes
|
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
|
|
||||||
if w.Layout != nil {
|
if w.Layout != nil {
|
||||||
ctor := constructorFunctionFor(w.Layout.Class)
|
ctor := constructorFunctionFor(w.Layout.Class)
|
||||||
|
|
||||||
@ -134,6 +185,15 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
|
|||||||
ui.` + w.Layout.Name + `.SetObjectName(` + strconv.Quote(w.Layout.Name) + `)
|
ui.` + w.Layout.Name + `.SetObjectName(` + strconv.Quote(w.Layout.Name) + `)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
// Layout->Properties
|
||||||
|
|
||||||
|
err := renderProperties(w.Layout.Properties, &ret, w.Layout.Name, parentClass, true) // Always emit spacing/padding calls
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout->Items
|
||||||
|
|
||||||
for i, child := range w.Layout.Items {
|
for i, child := range w.Layout.Items {
|
||||||
|
|
||||||
// A layout item is either a widget, or a spacer
|
// A layout item is either a widget, or a spacer
|
||||||
@ -304,7 +364,22 @@ func generateWidget(w UiWidget, parentName string, parentClass string) (string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generate(packageName string, goGenerateArgs string, u UiFile) ([]byte, error) {
|
func generate(packageName string, goGenerateArgs string, u UiFile) ([]byte, error) {
|
||||||
|
|
||||||
ret := strings.Builder{}
|
ret := strings.Builder{}
|
||||||
|
|
||||||
|
// Update globals for layoutdefault, if present
|
||||||
|
|
||||||
|
if u.LayoutDefault != nil {
|
||||||
|
if u.LayoutDefault.Spacing != nil {
|
||||||
|
DefaultSpacing = *u.LayoutDefault.Spacing
|
||||||
|
}
|
||||||
|
if u.LayoutDefault.Margin != nil {
|
||||||
|
DefaultGridMargin = *u.LayoutDefault.Margin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header
|
||||||
|
|
||||||
ret.WriteString(`// Generated by miqt-uic. To update this file, edit the .ui file in
|
ret.WriteString(`// Generated by miqt-uic. To update this file, edit the .ui file in
|
||||||
// Qt Designer, and then run 'go generate'.
|
// Qt Designer, and then run 'go generate'.
|
||||||
//
|
//
|
||||||
|
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,3 +90,12 @@ func formatBool(b bool) string {
|
|||||||
}
|
}
|
||||||
return "false"
|
return "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mustParseInt(s string) int {
|
||||||
|
val, err := strconv.ParseInt(s, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic("parseInt(" + s + "): " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(val) // n.b. might do 32-bit truncation(!)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user