Make header action cluster own menus
This commit is contained in:
+65
-39
@@ -39,68 +39,87 @@ func (u *ui) headerActions(gtx layout.Context) layout.Dimensions {
|
|||||||
if u.shouldShowLifecycleSetup() || u.isVaultLocked() || u.shouldShowDesktopWorkingHeader() {
|
if u.shouldShowLifecycleSetup() || u.isVaultLocked() || u.shouldShowDesktopWorkingHeader() {
|
||||||
return layout.Dimensions{}
|
return layout.Dimensions{}
|
||||||
}
|
}
|
||||||
spacing := gtx.Dp(unit.Dp(8))
|
cluster := u.newHeaderActionCluster(gtx)
|
||||||
metrics := headerlayout.ActionMetrics{Spacing: spacing, SyncInnerSpacing: gtx.Dp(unit.Dp(3))}
|
|
||||||
if !u.usesCompactViewport() {
|
|
||||||
metrics.SyncInnerSpacing = gtx.Dp(unit.Dp(4))
|
|
||||||
}
|
|
||||||
actionCluster := func(gtx layout.Context) layout.Dimensions {
|
|
||||||
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
metrics.SyncDims, metrics.SyncPrimaryDims, metrics.SyncToggleDims = u.syncButtonGroupWithMetrics(gtx)
|
|
||||||
return metrics.SyncDims
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
btn := material.Button(u.theme, &u.lockVault, "Lock")
|
|
||||||
metrics.LockDims = btn.Layout(gtx)
|
|
||||||
return metrics.LockDims
|
|
||||||
}),
|
|
||||||
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
||||||
metrics.MainDims = u.mainMenuButtonGroup(gtx)
|
|
||||||
return metrics.MainDims
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
rowOps := op.Record(gtx.Ops)
|
|
||||||
metrics.RowDims = actionCluster(gtx)
|
|
||||||
rowCall := rowOps.Stop()
|
|
||||||
metrics.RowOriginX = max(0, gtx.Constraints.Max.X-metrics.RowDims.Size.X)
|
|
||||||
|
|
||||||
surface := headerlayout.DropdownSurface{ContainerWidth: gtx.Constraints.Max.X, LeftInset: 0, TopInset: 0}
|
surface := headerlayout.DropdownSurface{ContainerWidth: gtx.Constraints.Max.X, LeftInset: 0, TopInset: 0}
|
||||||
|
|
||||||
rowDims := layout.E.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
rowDims := layout.E.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||||
rowCall.Add(gtx.Ops)
|
cluster.RowCall.Add(gtx.Ops)
|
||||||
return metrics.RowDims
|
return cluster.Metrics.RowDims
|
||||||
})
|
})
|
||||||
if u.usesCompactViewport() {
|
if u.usesCompactViewport() {
|
||||||
u.maybeLogHeaderBounds(newHeaderButtonBounds(image.Pt(u.frameInsetPx, u.frameInsetPx), metrics.Bounds()))
|
u.maybeLogHeaderBounds(newHeaderButtonBounds(image.Pt(u.frameInsetPx, u.frameInsetPx), cluster.Metrics.Bounds()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.usesCompactViewport() {
|
if u.usesCompactViewport() {
|
||||||
if u.syncMenuOpen {
|
if u.syncMenuOpen {
|
||||||
u.phoneSyncMenuVisible = true
|
u.phoneSyncMenuVisible = true
|
||||||
u.phoneSyncMenuAnchor = metrics.SyncAnchor().Point()
|
u.phoneSyncMenuAnchor = cluster.Metrics.SyncAnchor().Point()
|
||||||
}
|
}
|
||||||
if u.mainMenuOpen {
|
if u.mainMenuOpen {
|
||||||
u.phoneMainMenuVisible = true
|
u.phoneMainMenuVisible = true
|
||||||
u.phoneMainMenuAnchor = metrics.MainAnchor().Point()
|
u.phoneMainMenuAnchor = cluster.Metrics.MainAnchor().Point()
|
||||||
}
|
}
|
||||||
return layout.Dimensions{Size: image.Pt(gtx.Constraints.Max.X, rowDims.Size.Y)}
|
return layout.Dimensions{Size: image.Pt(gtx.Constraints.Max.X, rowDims.Size.Y)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.syncMenuOpen {
|
if cluster.ShowSyncMenu() {
|
||||||
surface.Draw(gtx, metrics.SyncAnchor(), u.syncMenu)
|
surface.Draw(gtx, cluster.Metrics.SyncAnchor(), cluster.SyncMenu)
|
||||||
}
|
}
|
||||||
if u.mainMenuOpen {
|
if cluster.ShowMainMenu() {
|
||||||
surface.Draw(gtx, metrics.MainAnchor(), u.mainMenu)
|
surface.Draw(gtx, cluster.Metrics.MainAnchor(), cluster.MainMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rowDims
|
return rowDims
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type headerActionCluster struct {
|
||||||
|
Metrics headerlayout.ActionMetrics
|
||||||
|
RowCall op.CallOp
|
||||||
|
SyncMenu layout.Widget
|
||||||
|
MainMenu layout.Widget
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c headerActionCluster) ShowSyncMenu() bool { return c.SyncMenu != nil }
|
||||||
|
|
||||||
|
func (c headerActionCluster) ShowMainMenu() bool { return c.MainMenu != nil }
|
||||||
|
|
||||||
|
func (u *ui) newHeaderActionCluster(gtx layout.Context) headerActionCluster {
|
||||||
|
cluster := headerActionCluster{
|
||||||
|
SyncMenu: u.syncMenuWidget(),
|
||||||
|
MainMenu: u.mainMenuWidget(),
|
||||||
|
}
|
||||||
|
spacing := gtx.Dp(unit.Dp(8))
|
||||||
|
cluster.Metrics = headerlayout.ActionMetrics{Spacing: spacing, SyncInnerSpacing: gtx.Dp(unit.Dp(3))}
|
||||||
|
if !u.usesCompactViewport() {
|
||||||
|
cluster.Metrics.SyncInnerSpacing = gtx.Dp(unit.Dp(4))
|
||||||
|
}
|
||||||
|
rowOps := op.Record(gtx.Ops)
|
||||||
|
cluster.Metrics.RowDims = cluster.layoutRow(gtx, u)
|
||||||
|
cluster.RowCall = rowOps.Stop()
|
||||||
|
cluster.Metrics.RowOriginX = max(0, gtx.Constraints.Max.X-cluster.Metrics.RowDims.Size.X)
|
||||||
|
return cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *headerActionCluster) layoutRow(gtx layout.Context, u *ui) layout.Dimensions {
|
||||||
|
return layout.Flex{Spacing: layout.SpaceStart}.Layout(gtx,
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
c.Metrics.SyncDims, c.Metrics.SyncPrimaryDims, c.Metrics.SyncToggleDims = u.syncButtonGroupWithMetrics(gtx)
|
||||||
|
return c.Metrics.SyncDims
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
btn := material.Button(u.theme, &u.lockVault, "Lock")
|
||||||
|
c.Metrics.LockDims = btn.Layout(gtx)
|
||||||
|
return c.Metrics.LockDims
|
||||||
|
}),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
c.Metrics.MainDims = u.mainMenuButtonGroup(gtx)
|
||||||
|
return c.Metrics.MainDims
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
type headerButtonBounds struct {
|
type headerButtonBounds struct {
|
||||||
SyncPrimary image.Rectangle
|
SyncPrimary image.Rectangle
|
||||||
SyncToggle image.Rectangle
|
SyncToggle image.Rectangle
|
||||||
@@ -212,6 +231,13 @@ func (u *ui) brandImage(gtx layout.Context, src paint.ImageOp, widthDP, heightDP
|
|||||||
return img.Layout(gtx)
|
return img.Layout(gtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ui) mainMenuWidget() layout.Widget {
|
||||||
|
if !u.mainMenuOpen {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return u.mainMenu
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) mainMenu(gtx layout.Context) layout.Dimensions {
|
func (u *ui) mainMenu(gtx layout.Context) layout.Dimensions {
|
||||||
rows := []layout.Widget{
|
rows := []layout.Widget{
|
||||||
func(gtx layout.Context) layout.Dimensions {
|
func(gtx layout.Context) layout.Dimensions {
|
||||||
|
|||||||
@@ -58,6 +58,13 @@ func (u *ui) syncMenuToggle(gtx layout.Context) layout.Dimensions {
|
|||||||
return btn.Layout(gtx)
|
return btn.Layout(gtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *ui) syncMenuWidget() layout.Widget {
|
||||||
|
if !u.syncMenuOpen {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return u.syncMenu
|
||||||
|
}
|
||||||
|
|
||||||
func (u *ui) syncMenu(gtx layout.Context) layout.Dimensions {
|
func (u *ui) syncMenu(gtx layout.Context) layout.Dimensions {
|
||||||
model := u.buildSyncMenuModel()
|
model := u.buildSyncMenuModel()
|
||||||
profiles := u.availableRemoteProfiles()
|
profiles := u.availableRemoteProfiles()
|
||||||
|
|||||||
Reference in New Issue
Block a user