diff --git a/ui/chapartheme/theme.go b/ui/chapartheme/theme.go index 91a4740e..f7923e4d 100644 --- a/ui/chapartheme/theme.go +++ b/ui/chapartheme/theme.go @@ -27,6 +27,7 @@ type Theme struct { TextColor color.NRGBA ButtonTextColor color.NRGBA SendButtonBgColor color.NRGBA + DeleteButtonBgColor color.NRGBA SwitchBgColor color.NRGBA TabInactiveColor color.NRGBA SeparatorColor color.NRGBA @@ -93,6 +94,7 @@ func (t *Theme) Switch(isDark bool) *material.Theme { t.ErrorColor = rgb(0xff7373) t.WarningColor = rgb(0xffe073) t.BadgeBgColor = rgb(0x2b2d31) + t.DeleteButtonBgColor = rgb(0xff7373) } else { t.LoaderColor = rgb(0x000000) t.Theme.Palette.Fg = rgb(0x000000) @@ -119,6 +121,7 @@ func (t *Theme) Switch(isDark bool) *material.Theme { t.ErrorColor = rgb(0xff7373) t.WarningColor = rgb(0xffe073) t.BadgeBgColor = rgb(0x2b2d31) + t.DeleteButtonBgColor = rgb(0xff7373) } return t.Theme diff --git a/ui/pages/protofiles/controller.go b/ui/pages/protofiles/controller.go index 06a3b1ec..b6864c0a 100644 --- a/ui/pages/protofiles/controller.go +++ b/ui/pages/protofiles/controller.go @@ -29,6 +29,7 @@ func NewController(view *View, state *state.ProtoFiles, repo repository.Reposito view.SetOnAdd(c.onAdd) view.SetOnDelete(c.onDelete) + view.SetOnDeleteSelected(c.onDeleteSelected) return c } @@ -69,13 +70,13 @@ func (c *Controller) onAdd() { } func (c *Controller) onDelete(p *domain.ProtoFile) { - ws := c.state.GetProtoFile(p.MetaData.ID) - if ws == nil { + pr := c.state.GetProtoFile(p.MetaData.ID) + if pr == nil { fmt.Println("failed to get proto-file", p.MetaData.ID) return } - if err := c.state.RemoveProtoFile(p, false); err != nil { + if err := c.state.RemoveProtoFile(pr, false); err != nil { fmt.Println("failed to remove proto-file", err) return } @@ -83,6 +84,23 @@ func (c *Controller) onDelete(p *domain.ProtoFile) { c.view.RemoveItem(p) } +func (c *Controller) onDeleteSelected(ids []string) { + for _, id := range ids { + pr := c.state.GetProtoFile(id) + if pr == nil { + fmt.Println("failed to get proto-file", id) + continue + } + + if err := c.state.RemoveProtoFile(pr, false); err != nil { + fmt.Println("failed to remove proto-file", err) + continue + } + + c.view.RemoveItem(pr) + } +} + func (c *Controller) saveProtoFileToDisc(id string) { ws := c.state.GetProtoFile(id) if ws == nil { diff --git a/ui/pages/protofiles/view.go b/ui/pages/protofiles/view.go index 6b122a66..7a26da7c 100644 --- a/ui/pages/protofiles/view.go +++ b/ui/pages/protofiles/view.go @@ -23,7 +23,9 @@ import ( ) type View struct { - addButton widget.Clickable + addButton widget.Clickable + deleteSelectedButton widget.Clickable + searchBox *widgets.TextField grid component.GridState @@ -34,8 +36,9 @@ type View struct { items []*Item filteredItems []*Item - onAdd func() - onDelete func(w *domain.ProtoFile) + onAdd func() + onDelete func(p *domain.ProtoFile) + onDeleteSelected func(ids []string) } type Item struct { @@ -54,6 +57,7 @@ func NewView() *View { search := widgets.NewTextField("", "Search...") search.SetIcon(widgets.SearchIcon, widgets.IconPositionEnd) v := &View{ + mx: &sync.Mutex{}, searchBox: search, } @@ -112,6 +116,10 @@ func (v *View) SetOnDelete(f func(w *domain.ProtoFile)) { v.onDelete = f } +func (v *View) SetOnDeleteSelected(f func(ids []string)) { + v.onDeleteSelected = f +} + func (v *View) Filter(text string) { v.mx.Lock() defer v.mx.Unlock() @@ -139,6 +147,29 @@ func (v *View) header(gtx layout.Context, theme *chapartheme.Theme) layout.Dimen } } + shouldShowDeleteSelected := false + for _, item := range v.items { + if item.checkBox.Value { + shouldShowDeleteSelected = true + break + } + } + + if shouldShowDeleteSelected { + if v.deleteSelectedButton.Clicked(gtx) { + var ids []string + for _, item := range v.items { + if item.checkBox.Value { + ids = append(ids, item.p.MetaData.ID) + } + } + + if v.onDeleteSelected != nil { + v.onDeleteSelected(ids) + } + } + } + return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle, Spacing: layout.SpaceBetween}.Layout(gtx, layout.Rigid(func(gtx layout.Context) layout.Dimensions { return layout.Flex{ @@ -158,6 +189,16 @@ func (v *View) header(gtx layout.Context, theme *chapartheme.Theme) layout.Dimen }), layout.Rigid(func(gtx layout.Context) layout.Dimensions { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(func(gtx layout.Context) layout.Dimensions { + if !shouldShowDeleteSelected { + return layout.Dimensions{} + } + deleteSelectedBtn := widgets.Button(theme.Material(), &v.deleteSelectedButton, widgets.DeleteIcon, widgets.IconPositionStart, "Delete Selected") + deleteSelectedBtn.Color = theme.ButtonTextColor + deleteSelectedBtn.Background = theme.DeleteButtonBgColor + return deleteSelectedBtn.Layout(gtx, theme) + }), + layout.Rigid(layout.Spacer{Width: unit.Dp(5)}.Layout), layout.Rigid(func(gtx layout.Context) layout.Dimensions { newBtn := widgets.Button(theme.Material(), &v.addButton, widgets.PlusIcon, widgets.IconPositionStart, "Add Proto file") newBtn.Color = theme.ButtonTextColor @@ -182,6 +223,13 @@ func (v *View) Layout(gtx layout.Context, theme *chapartheme.Theme) layout.Dimen items = v.filteredItems } + // if checkbox is clicked, check all checkboxes + if v.checkAllBook.Update(gtx) { + for _, item := range items { + item.checkBox.Value = v.checkAllBook.Value + } + } + // minSize := gtx.Dp(unit.Dp(50)) inset := layout.UniformInset(unit.Dp(10)) // Configure a label styled to be a heading.