package ui import ( "fmt" "go_dreamfactory/cmd/v2/lib/common" "go_dreamfactory/cmd/v2/service" "go_dreamfactory/cmd/v2/service/observer" "go_dreamfactory/comm" "go_dreamfactory/modules/user" "go_dreamfactory/pb" "strings" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" "github.com/BabySid/gobase" "github.com/Pallinder/go-randomdata" "github.com/sirupsen/logrus" "github.com/go-vgo/robotgo" ) var ( globalWin *MainWindowImpl toolWin *ToolWindowImpl ) type MainWindow interface { WindowInterface } type MainWindowImpl struct { UIImpl WindowDefaultOptions parent fyne.Window w fyne.Window tb *toolBar //工具条 toys *toys // side sb *statusBar //状态栏 at *appContainer //tabs } func NewMainWindow(ui *UIImpl, parent fyne.Window) MainWindow { gobase.NewScheduler().Start() gobase.RegisterAtExit(gobase.GlobalScheduler.Stop) mw := &MainWindowImpl{ UIImpl: *ui, parent: parent, } globalWin = mw ui.obs.AddListener(observer.EVENT_PING, observer.Listener{ OnNotify: func(data interface{}, args ...interface{}) { logrus.Debug("即将与服务器断开链接") conf := dialog.NewConfirm("链接中断", data.(error).Error(), func( b bool) { ui.app.Quit() }, globalWin.w) conf.SetDismissText("取消") conf.SetConfirmText("退出") conf.Show() }, }) return mw } func GetGlobalWin() *MainWindowImpl { return globalWin } // createWindowContainer create a container with the window content func (ui *MainWindowImpl) createWindowContainer() { // create main layout // status bar ui.sb = newStatusBar() // tool bar toolbar := widget.NewToolbar( widget.NewToolbarAction(theme.MediaVideoIcon(), func() { openApp2(common.TOOLBAR_MONITOR) }), widget.NewToolbarAction(theme.DocumentIcon(), func() { openApp2(common.TOOLBAR_TESTER) }), widget.NewToolbarSpacer(), widget.NewToolbarAction(theme.FileIcon(), func() { newLogViewer().Win.Show() }), ) ui.tb = newToolBar(toolbar) // Fun Toys ui.toys = newToys(ui.obs) // main app tabs ui.at = newAppContainer(appRegister, ui.obs) content := container.NewBorder(ui.tb.toolbar, ui.sb.widget, nil, ui.toys.widget, ui.at) ui.w.SetContent(content) // 屏幕最大 width, height := robotgo.GetScaleSize() ui.w.Resize(fyne.NewSize(float32(width), float32(height))) ui.w.CenterOnScreen() ui.w.SetCloseIntercept(ui.quiteHandle) } func (ui *MainWindowImpl) SetStatusMsg(msg string) { ui.sb.setMessage(fmt.Sprintf("err:%s", msg)) } func (ui *MainWindowImpl) quiteHandle() { dialog.ShowConfirm("推出系统", "确定退出吗", func(b bool) { if !b { return } ui.app.Quit() }, ui.w) } // CreateWindow .... func (ui *MainWindowImpl) CreateWindow(_ string, width, height float32, _ bool) { // init window title := fmt.Sprintf(common.APP_WIN_TITLE, "登录", ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME) w := ui.app.NewWindow(title) ui.AddWindow("main", w) ui.w = w if ui.windowAspect == common.WindowAspect_FullScreen { w.SetFullScreen(true) } else { w.Resize(fyne.NewSize(width, height)) } // w.SetMaster() w.CenterOnScreen() w.Canvas().SetOnTypedKey(func(ke *fyne.KeyEvent) { switch ke.Name { case fyne.KeyEscape: { w.Close() ui.parent.Show() } } }) w.SetCloseIntercept(func() { ui.parent.Show() }) _ = ui.createChooseServerPopUp(w) } // createChooseServerPopUp func (ui *MainWindowImpl) createChooseServerPopUp(w fyne.Window) error { ch := make(chan string) title := fmt.Sprintf(common.APP_WIN_TITLE, "选服", ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME) selServerWin := ui.createChooseServerWindow(title, ch) go func() { data := <-ch selServerWin.Hide() ui.NewWelcomeLabel(data) ui.w.Show() }() return nil } // createChooseServerWindow func (ui *MainWindowImpl) createChooseServerWindow( title string, ch chan string) fyne.Window { // choose server button func makeButton := func(s *service.ServiceConf, parent fyne.Window) *widget.Button { btn := widget.NewButton(s.Name, func() { d := dialog.NewInformation("", common.INFO_WAIT, parent) d.SetDismissText(common.BUTTON_CANCEL) d.Show() logrus.WithFields(logrus.Fields{"server": s.Name, "sid": s.SId}).Debug("choose server") //conn server if err := ui.connService.WsConnect(s.Url); err != nil { d.Hide() dialog.ShowError(err, parent) } else { ch <- fmt.Sprintf("%s:%s", s.SId, s.Name) } }) return btn } w := fyne.CurrentApp().NewWindow(title) sGrid := container.NewGridWithColumns(2) config := ui.configService.GetConfig() if config != nil { for _, s := range config.Services { box := makeButton(s.Service, w) sGrid.Add(box) } } w.SetContent(sGrid) w.SetFixedSize(true) w.Resize(fyne.NewSize(500, 200)) w.Show() w.SetCloseIntercept(func() { ui.parent.Show() w.Close() }) w.CenterOnScreen() return w } // createLoginWin func (ui *MainWindowImpl) createLoginWin(sid, sname string) { account := widget.NewEntry() // account.Text = "user8080" //default account items := []*widget.FormItem{ widget.NewFormItem(common.LABEL_ACCOUNT, account), } dialog.ShowForm(common.FORM_TITLE_LOGIN, common.BUTTON_LOGIN, common.BUTTON_CANCEL, items, func(b bool) { if !b { logrus.Debug("cancel login") } else { if account.Text != "" { logrus.WithField("account", account.Text).Debug("submit login") ui.createWindowContainer() appName, err := ui.at.openDefaultApp() if err != nil { logrus.WithField("appName", appName).Error(err) } // hide toolbar ui.tb.toolbar.Hide() // call after ui.createWindowContainer ui.connService.ListenerPush() if code := ui.pttService.Login(sid, account.Text); code != pb.ErrorCode_Success { err := fmt.Errorf("login err: %v[%d]", code, int32(code)) dialog.ShowError(err, ui.w) } else { ui.obs.AddListener(observer.EVENT_REQ_RSP, observer.Listener{ OnNotify: func(data interface{}, args ...interface{}) { if data == nil { return } msg := data.(*pb.UserMessage) if msg.MainType == string(comm.ModuleUser) && msg.SubType == user.UserSubTypeLogin { rsp := &pb.UserLoginResp{} if !comm.ProtoUnmarshal(msg, rsp) { logrus.Error("unmarshal err") return } // reset main window title subTitle := fmt.Sprintf("%s[%s]", sname, sid) ui.w.SetTitle(fmt.Sprintf(common.APP_WIN_TITLE, subTitle, ui.app.Metadata().Version, ui.app.Metadata().Build, common.APP_NAME)) ui.pttService.SetUser(rsp.Data, rsp.Ex) // isCreateRole if rsp.Data.Created { // set statusbar message ui.sb.setMessage(common.LABEL_WELCOME + rsp.Data.Binduid) // update userinfo ui.obs.Notify(observer.EVENT_USERINFO, ui.pttService.GetUser()) // show toolbar ui.tb.toolbar.Show() } else { // create role ui.createRoleWindowPopUp() } } }, }) } } } }, ui.w) } // createMainWindowMenu create the main window menu func (ui *MainWindowImpl) createMainWindowMenu() *fyne.MainMenu { menuItems := []*fyne.MenuItem{} menu := fyne.Menu{ Label: common.MENU_FILE, Items: menuItems, } return fyne.NewMainMenu(&menu) } // createRoleWindowPopUp func (ui *MainWindowImpl) createRoleWindowPopUp() { nickname := widget.NewEntry() c := container.NewBorder(nil, nil, nil, widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() { nickname.SetText(randomdata.SillyName()) }), nickname, ) items := []*widget.FormItem{ widget.NewFormItem(common.LABEL_NICKNAME, c), } d := dialog.NewForm(common.FORM_TITLE_CREATEROLE, common.BUTTON_OK, common.BUTTON_CANCEL, items, func(b bool) { if nickname.Text != "" { logrus.WithField("nickname", nickname.Text).Debug("submit crete role") if code := ui.pttService.CreateRole(nickname.Text); code != pb.ErrorCode_Success { err := fmt.Errorf("login err: %v[%d]", code, int32(code)) dialog.ShowError(err, ui.w) } else { user := ui.pttService.GetUser() logrus.WithField("uid", user.DbUser.Uid).Debug("create role succ") ui.obs.Notify(observer.EVENT_USERINFO, ui.pttService.GetUser()) ui.tb.toolbar.Show() } } }, ui.w) d.Resize(fyne.NewSize(300, 200)) d.Show() } // NewWelcomeLabel func (ui *MainWindowImpl) NewWelcomeLabel(data string) { p := strings.Split(data, ":") if len(p) != 2 { logrus.WithField("param", p).Error("choose service") return } c := container.NewCenter(container.NewVBox( widget.NewLabelWithStyle(fmt.Sprintf(common.LABEL_CHOOSE, p[0], p[1]), fyne.TextAlignCenter, fyne.TextStyle{Bold: true}), container.NewCenter(container.NewHBox( widget.NewButton(common.BUTTON_LOGIN, func() { ui.createLoginWin(p[0], p[1]) }), )), )) ui.w.SetContent(c) ui.w.SetCloseIntercept(func() { ui.w.Close() ui.parent.Show() }) }