Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Widget.SetVisible(false) not compatible with HSplitter/VSplitter #491

Open
StephanVerbeeck opened this issue Apr 26, 2019 · 2 comments
Open

Comments

@StephanVerbeeck
Copy link

StephanVerbeeck commented Apr 26, 2019

I have isolated the problem in a little program shown here below.
I managed to fix #489 by not using SetVisible() but simply remove and add the TabPage from the Tab widget. Regrettably the same did not work when trying to alter the children list of the Splitter (the application hangs, preventable by SetSuspend() ) but none of the fixes or workarounds that I tried give a proper effect.

Does anybody want to give it a try to get this to work?

Even suggestions on what else I could try are most welcome!

The functionality is needed to hide/show a table with accounting bookings for directories on the hard disk that are not subdirectories of the directory that contains one of the accounting databases.

package main

/*
	TODO
	- implement fix in application
	BUSY
	- make this work
	DONE
	- convert problem to local demo
	V0.1
*/

import (
	"github.com/lxn/walk"
	. "github.com/lxn/walk/declarative"
)

var (
	mainWindow *walk.MainWindow
	splitter   *walk.Splitter
	com        [3]*walk.Composite
)

func main() {
	walk.FocusEffect, _ = walk.NewBorderGlowEffect(walk.RGB(0, 63, 255))
	walk.InteractionEffect, _ = walk.NewDropShadowEffect(walk.RGB(63, 63, 63))
	walk.ValidationErrorEffect, _ = walk.NewBorderGlowEffect(walk.RGB(255, 0, 0))

	_, err := MainWindow{
		Title:    "Optional Widget in Horizontal Splitter",
		Name:     "MainWindow",
		AssignTo: &mainWindow,
		MinSize:  Size{600, 400},
		Size:     Size{1024, 640},
		Layout:   HBox{MarginsZero: true},
		Children: []Widget{
			HSplitter{
				Name:     "Splitter",
				AssignTo: &splitter,
				Children: []Widget{
					Composite{
						Name:       "Com0",
						AssignTo:   &com[0],
						Background: SolidColorBrush{Color: walk.RGB(255, 255, 200)},
						Layout:     VBox{},
						MinSize:    Size{100, 400},
						MaxSize:    Size{400, 4096},
						Children: []Widget{
							LineEdit{Text: "aaaa1"},
							LineEdit{Text: "aaaa2"},
							LineEdit{Text: "aaaa3"},
							VSpacer{},
						},
					},
					Composite{
						Name:       "Com1",
						AssignTo:   &com[1],
						Background: SolidColorBrush{Color: walk.RGB(255, 255, 200)},
						Layout:     VBox{},
						MinSize:    Size{100, 400},
						MaxSize:    Size{400, 4096},
						Children: []Widget{
							LineEdit{Text: "bbbb1"},
							LineEdit{Text: "bbbb2"},
							LineEdit{Text: "bbbb3"},
							VSpacer{},
						},
					},
					Composite{
						Name:       "Com2",
						AssignTo:   &com[2],
						Background: SolidColorBrush{Color: walk.RGB(255, 255, 200)},
						Layout:     VBox{},
						MinSize:    Size{100, 400},
						MaxSize:    Size{400, 4096},
						Children: []Widget{
							LineEdit{Text: "cccc1"},
							LineEdit{Text: "cccc2"},
							LineEdit{Text: "cccc3"},
							VSpacer{},
						},
					},
					HSpacer{},
				},
			},
		},
		MenuItems: []MenuItem{
			Action{Text: "Show item", OnTriggered: showItem},
			Action{Text: "Hide item", OnTriggered: hideItem},
		},
	}.Run()
	if err != nil {
		panic(err)
	}
}

func showItem() {
	setWidgetVisible(true)
}

func hideItem() {
	setWidgetVisible(false)
}

func setWidgetVisible(visible bool) {
	const method = 1

	switch method {
	case 1:
		com[1].SetVisible(visible)

	case 2:
		com[1].SetVisible(visible)
		splitter.Layout().Update(true)

	case 3:
		if com[1].Visible() != visible {
			com[1].SetSuspended(true)
			if visible {
				com[1].SetParent(splitter)
				com[1].SetVisible(true)
			} else {
				com[1].SetVisible(false)
				com[1].SetParent(nil)
			}
			com[1].SetSuspended(false)
			splitter.Layout().Update(true)
		}

	case 4:
		if visible {
			if false && !splitter.Children().Contains(com[1]) {
				//mainWindow.SetSuspended(true)
				//splitter.SetSuspended(true)
				com[1].SetSuspended(true)
				//splitter.Children().Insert(2, com[1])
				splitter.Children().Add(com[1])
				com[1].SetParent(splitter)
				splitter.Layout().Update(true)
				com[1].SetSuspended(false)
				//splitter.SetSuspended(false)
				//mainWindow.SetSuspended(false)
			}
		} else {
			if splitter.Children().Contains(com[1]) {
				//mainWindow.SetSuspended(true)
				//splitter.SetSuspended(true)
				com[1].SetSuspended(true)
				splitter.Children().Remove(com[1])
				com[1].SetParent(nil)
				splitter.Layout().Update(true)
				com[1].SetSuspended(false)
				//splitter.SetSuspended(false)
				//mainWindow.SetSuspended(false)
			}
		}
	}
}
@StephanVerbeeck StephanVerbeeck changed the title Widget.SetVisible(false) not compatible with HSplitter/Vsplitter Widget.SetVisible(false) not compatible with HSplitter/VSplitter Apr 26, 2019
@StephanVerbeeck
Copy link
Author

Seems to work now (although nobody reported fixing it) after update of lxn/win and lxn/walk

@StephanVerbeeck
Copy link
Author

There is one curious bug left in this "making invisible".
When I call walk.MsgBox() (to display a warning or confirmation or ask confirmation of something) then the vertical resize bar and border of the invisible item is suddenly drawn again!
The item that I make invisible is a child (type composite with VBox{} layout) having a parent of type HSplitter{}.
So the invisible item is not drawn but the resizer around it is, and that in the moment that the popup window of the message dialog appears.

I can not show all related code to this bug because the declarative is thousands of lines (divided over different classes and screens and modules by using functions that return single widgets or lists of widgets for that module).

Here follows some code that I use and might also influence this (like storing the GUI position and sizes in a settings file).

// SetBookingsVisible show/hide booking table view depending on whether current data directory has accounting information or not
func SetBookingsVisible(visible bool) {
	if com[2].Visible() != visible {
		com[2].SetAlwaysConsumeSpace(false)
		widgets := com[2].Children()
		for w := 0; w < widgets.Len(); w++ {
			widgets.At(w).SetAlwaysConsumeSpace(false)
		}
		com[2].SetVisible(visible)
		com[2].Parent().Layout().Update(true)
	}
}
. . . 
walk.FocusEffect, _ = walk.NewBorderGlowEffect(walk.RGB(0, 63, 255))
walk.InteractionEffect, _ = walk.NewDropShadowEffect(walk.RGB(63, 63, 63))
walk.ValidationErrorEffect, _ = walk.NewBorderGlowEffect(walk.RGB(255, 0, 0))
. . . 
err := MainWindow{
	Title:           "Accounting",
	Name:            "MainWindow",
	AssignTo:        &mainWindow,
	Icon:            appIcon,
	Font:            accountingSettings.Font,
	MinSize:         Size{600, 400},
	Size:            Size{1024, 640},
	Layout:          HBox{MarginsZero: true},
	OnSizeChanged:   func() { resizeCountDown = 2 },
	OnBoundsChanged: func() { resizeCountDown = 2 },
	OnDropFiles:     ReceiveDroppedFiles,
	Children: []Widget{
		HSplitter{
			Name:       "Splitter",
			AssignTo:   &splitter,
			Background: SolidColorBrush{Color: walk.RGB(255, 255, 200)},
			Children: []Widget{
				Composite{
					Name:     "Dirs",
					AssignTo: &com[0],
					Layout:   VBox{SpacingZero: true, MarginsZero: true},
					MinSize:  Size{100, 400},
					MaxSize:  Size{400, 4096},
					Children: []Widget{
						Label{AssignTo: &dirsLabel, Text: "Directories", TextAlignment: AlignCenter},
						VSplitter{
							Name: "Splitter",
							Children: []Widget{
								DirTreeView(),
								TextEdit{AssignTo: &dirComment, MinSize: Size{100, 100}, OnTextChanged: DirCommentChanged, VScroll: true},
							},
						},
					},
				},
				Composite{
					Name:     "Files",
					AssignTo: &com[1],
					Layout:   VBox{SpacingZero: true, MarginsZero: true},
					MinSize:  Size{150, 400},
					MaxSize:  Size{600, 4096},
					Children: []Widget{
						Label{AssignTo: &filesLabel, Text: "Files", TextAlignment: AlignCenter},
						VSplitter{
							Name: "Splitter",
							Children: []Widget{
								FileTableView(),
								TextEdit{AssignTo: &fileComment, MinSize: Size{150, 100}, OnTextChanged: FileCommentChanged, VScroll: true},
							},
						},
					},
				},
				Composite{
					Name:               "Bookings",
					AssignTo:           &com[2],
					AlwaysConsumeSpace: false,
					Layout:             VBox{SpacingZero: true, MarginsZero: true},
					MinSize:            Size{150, 400},
					MaxSize:            Size{600, 4096},
					Children: []Widget{
						Label{AssignTo: &bookingLabel, Text: "Bookings", TextAlignment: AlignCenter},
						VSplitter{
							Name: "Splitter",
							Children: []Widget{
								BookingTableView(),
								TextEdit{AssignTo: &bookingComment, MinSize: Size{150, 100}, OnTextChanged: BookingCommentChanged, VScroll: true},
							},
						},
					},
				},
				Composite{
					Name:               "View",
					AlwaysConsumeSpace: true,
					MinSize:            Size{200, 400},
					MaxSize:            Size{4096, 4096},
					Layout:             VBox{SpacingZero: true, MarginsZero: true},
					Children: []Widget{
						Label{AssignTo: &statusBar, Text: "~"},
						TabWidget{
							Name:                  "Tabs",
							AssignTo:              &mainTabs,
							StretchFactor:         4,
							OnCurrentIndexChanged: onMainTabChanged,
							OnSizeChanged:         func() { resizeCountDown = 2 },
							Pages: []TabPage{
								TabPage{
									Name:       "View",
									Title:      "View",
									Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
									Layout:     VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										TabWidget{
											Name:                  "Views",
											AssignTo:              &viewTabs,
											OnCurrentIndexChanged: ShowSelectedViewTabWindow,
											Pages: []TabPage{
												TabPage{
													Name:       "Intern",
													Title:      "Intern",
													Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
													Layout:     Grid{SpacingZero: true, MarginsZero: true, Columns: 2},
													Children: []Widget{
														PushButton{Text: "<--", OnClicked: BackDir, MaxSize: Size{30, 20}},
														LineEdit{AssignTo: &urlEdit, OnTextChanged: ViewURL, Enabled: accountingSettings.Visual.EditURL, StretchFactor: 100},
														WebView{AssignTo: &webView, ColumnSpan: 2, OnURLChanged: webViewURLChanged},
													},
												},
											},
										},
									},
								},
								TabPage{
									Name:   "Balance",
									Title:  "Balance",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										BalanceTableView(),
									},
								},
								TabPage{
									Name:   "Bank",
									Title:  "Bank",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										BankTableView(),
									},
								},
								TabPage{
									Name:   "Contacts",
									Title:  "Contacts",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:       "Splitter",
											Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											Children: []Widget{
												ContactTableView(),
												TextEdit{AssignTo: &contactComment, MinSize: Size{100, 100}, OnTextChanged: ContactCommentChanged, VScroll: true},
											},
										},
									},
								},
								TabPage{
									Name:   "Post types",
									Title:  "Post types",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:          "Splitter",
											Background:    SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											StretchFactor: 10,
											Children: []Widget{
												TabWidget{
													Name: "Tabs",
													Pages: []TabPage{
														TabPage{
															Name:   "Tree view",
															Title:  "Tree view",
															Layout: VBox{SpacingZero: true, MarginsZero: true},
															Children: []Widget{
																PostTreeView(),
															},
														},
														TabPage{
															Name:   "Table view",
															Title:  "Table view",
															Layout: VBox{SpacingZero: true, MarginsZero: true},
															Children: []Widget{
																PostTableView(),
															},
														},
													},
												},
												TextEdit{AssignTo: &postComment, MinSize: Size{100, 100}, OnTextChanged: PostCommentChanged, VScroll: true},
											},
										},
									},
								},
								TabPage{
									Name:   "Booking types",
									Title:  "Booking types",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:       "Splitter",
											Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											Children: []Widget{
												BookingTypeTableView(),
												TextEdit{AssignTo: &bookingTypeComment, MinSize: Size{100, 100}, OnTextChanged: BookingTypeCommentChanged, VScroll: true},
											},
										},
									},
								},
								TabPage{
									Name:   "Document types",
									Title:  "Document types",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:       "Splitter",
											Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											Children: []Widget{
												DocumentTypeTableView(),
												TextEdit{AssignTo: &documentTypeComment, MinSize: Size{100, 100}, OnTextChanged: DocumentTypeCommentChanged, VScroll: true},
											},
										},
									},
								},
								TabPage{
									Name:   "Periods",
									Title:  "Periods",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:       "Splitter",
											Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											Children: []Widget{
												PeriodTableView(),
												TextEdit{AssignTo: &periodComment, MinSize: Size{150, 100}, OnTextChanged: PeriodCommentChanged, VScroll: true},
											},
										},
									},
								},
								TabPage{
									Name:   "Help",
									Title:  "Help",
									Layout: VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										VSplitter{
											Name:       "Splitter",
											Background: SolidColorBrush{Color: walk.RGB(200, 255, 255)},
											Children: []Widget{
												HelpTreeView(),
												TextEdit{AssignTo: &helpComment, MinSize: Size{150, 100}, OnTextChanged: HelpCommentChanged, VScroll: true, MaxLength: 100000},
											},
										},
									},
								},
								TabPage{
									AssignTo: &tabPageSettings,
									Name:     "Settings",
									Title:    "Settings",
									Layout:   VBox{SpacingZero: true, MarginsZero: true},
									Children: []Widget{
										ScrollView{
											Layout:   Flow{},
											Children: SettingWidgets(),
										},
									},
								},
							},
						},
					},
				},
			},
		},
	},
	MenuItems: []MenuItem{
		Menu{
			Text: "&File",
			Items: []MenuItem{
				Action{Text: "Create Accounting DB", OnTriggered: MakeAccountingDatabaseHere},
				Action{Text: "Create Accounting Period", OnTriggered: InsertPeriod},
				Action{Text: "Create Accounting Document", OnTriggered: AddDocument},
				Separator{},
				Action{Text: "Save DB changes", OnTriggered: SaveAccount, Shortcut: Shortcut{walk.ModControl, walk.KeyS}},
				Action{Text: "Discard DB changes", OnTriggered: ReloadAccount, Shortcut: Shortcut{walk.ModControl, walk.KeyZ}},
				Action{Text: "Debug Accounting DB", OnTriggered: DebugJSON},
				Separator{},
				Action{Text: "Create Directory", OnTriggered: MakeSubDirHere},
				Action{Text: "Open Directory", OnTriggered: ViewExternDataDir},
				Separator{},
				Action{Text: "Close all views", OnTriggered: CloseViewTabs, Shortcut: Shortcut{walk.ModControl, walk.KeyF4}},
				Action{Text: "Close program", OnTriggered: CloseProgram, Shortcut: Shortcut{walk.ModAlt, walk.KeyF4}},
			},
		},
		Menu{
			Text: "&View",
			Items: []MenuItem{
				Action{Text: "Document", OnTriggered: func() { GotoTab(tabView) }, Shortcut: Shortcut{0, walk.KeyF1}},
				Action{Text: "Balance", OnTriggered: func() { GotoTab(tabBalance) }, Shortcut: Shortcut{0, walk.KeyF2}},
				Action{Text: "Bank", OnTriggered: func() { GotoTab(tabBank) }, Shortcut: Shortcut{0, walk.KeyF3}},
				Action{Text: "Contacts", OnTriggered: func() { GotoTab(tabContacts) }, Shortcut: Shortcut{0, walk.KeyF4}},
				Separator{},
				Action{Text: accountingSettings.Favorite.Dir[0], Visible: !StringIsEmpty(accountingSettings.Favorite.Dir[0]), OnTriggered: func() { GotoDir(accountingSettings.Favorite.Dir[0]) }, Shortcut: Shortcut{0, walk.KeyF5}},
				Action{Text: accountingSettings.Favorite.Dir[1], Visible: !StringIsEmpty(accountingSettings.Favorite.Dir[1]), OnTriggered: func() { GotoDir(accountingSettings.Favorite.Dir[1]) }, Shortcut: Shortcut{0, walk.KeyF6}},
				Action{Text: accountingSettings.Favorite.Dir[2], Visible: !StringIsEmpty(accountingSettings.Favorite.Dir[2]), OnTriggered: func() { GotoDir(accountingSettings.Favorite.Dir[2]) }, Shortcut: Shortcut{0, walk.KeyF7}},
				Action{Text: accountingSettings.Favorite.Dir[3], Visible: !StringIsEmpty(accountingSettings.Favorite.Dir[3]), OnTriggered: func() { GotoDir(accountingSettings.Favorite.Dir[3]) }, Shortcut: Shortcut{0, walk.KeyF8}},
				Separator{},
				Action{Text: accountingSettings.Favorite.File[0], Visible: !StringIsEmpty(accountingSettings.Favorite.File[0]), OnTriggered: func() { GotoFile(accountingSettings.Favorite.File[0]) }, Shortcut: Shortcut{0, walk.KeyF9}},
				Action{Text: accountingSettings.Favorite.File[1], Visible: !StringIsEmpty(accountingSettings.Favorite.File[1]), OnTriggered: func() { GotoFile(accountingSettings.Favorite.File[1]) }, Shortcut: Shortcut{0, walk.KeyF10}},
				Action{Text: accountingSettings.Favorite.File[2], Visible: !StringIsEmpty(accountingSettings.Favorite.File[2]), OnTriggered: func() { GotoFile(accountingSettings.Favorite.File[2]) }, Shortcut: Shortcut{0, walk.KeyF11}},
				Action{Text: accountingSettings.Favorite.File[3], Visible: !StringIsEmpty(accountingSettings.Favorite.File[3]), OnTriggered: func() { GotoFile(accountingSettings.Favorite.File[3]) }, Shortcut: Shortcut{0, walk.KeyF12}},
				Separator{},
				Action{AssignTo: &actionSettings, Text: "Settings", Checkable: true, OnTriggered: ToggleViewSettings},
				Action{Text: "Date/Currency settings", OnTriggered: RunConfigInternational},
			},
		},
		Menu{
			Text:  "&Run",
			Items: ProgramMenuItems(),
		},
		Menu{
			Text: "&About",
			Items: []MenuItem{
				Action{Text: "Help", OnTriggered: func() { mainTabs.SetCurrentIndex(tabHelp) }},
				Action{Text: "Accounting", OnTriggered: AboutAccounting},
			},
		},
	},
	OnKeyUp: oKey,
}.Create()
if err != nil {
	panic(err)
}
for i := range com {
	splitter.SetFixed(com[i], true) // prevent splitter from moving proportional to mainWindow width
}
CheckViewSettings()
go DataDirMonitor()
mainWindow.Run()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant