diff --git a/ui/cryptomaterial/segmented_control.go b/ui/cryptomaterial/segmented_control.go index 566852122..39f2403e0 100644 --- a/ui/cryptomaterial/segmented_control.go +++ b/ui/cryptomaterial/segmented_control.go @@ -166,11 +166,11 @@ func (sc *SegmentedControl) Changed() bool { return changed } -func (sc *SegmentedControl) SetSelectedSegment(segment string) { +func (sc *SegmentedControl) SelectedSegmentAtIndex(index int) { sc.mu.Lock() defer sc.mu.Unlock() - for i, item := range sc.segmentTitles { - if item == segment { + for i := range sc.segmentTitles { + if i == index { sc.selectedIndex = i break } diff --git a/ui/cryptomaterial/toggle_button.go b/ui/cryptomaterial/toggle_button.go deleted file mode 100644 index 0a2f52094..000000000 --- a/ui/cryptomaterial/toggle_button.go +++ /dev/null @@ -1,101 +0,0 @@ -package cryptomaterial - -import ( - "gioui.org/layout" -) - -type ToggleButton struct { - btns []*Button - theme *Theme - radius CornerRadius // this radius is used by the clickable - selectedItem int // defaults to first btn - - colorInverted bool - callback func(selectedItem int) -} - -func (t *Theme) ToggleButton(btns []*Button, colorInverted bool) *ToggleButton { - tb := &ToggleButton{ - theme: t, - btns: btns, - selectedItem: -1, - colorInverted: colorInverted, - } - - for i := range tb.btns { - b := tb.btns[i] - if tb.colorInverted { - b.HighlightColor = tb.theme.Color.Gray5 - } else { - b.HighlightColor = tb.theme.Color.Surface - } - b.Color = tb.theme.Color.Text - } - - return tb -} - -func (tb *ToggleButton) SelectItemAtIndex(index int) { - itemsLen := len(tb.btns) - if index > itemsLen || index < 0 { - return // no-op - } - - tb.selectedItem = index - if tb.callback != nil { - tb.callback(index) - } -} - -func (tb *ToggleButton) SetToggleButtonCallback(callback func(selectedItem int)) { - tb.callback = callback -} - -func (tb *ToggleButton) handleClickables() { - for index := range tb.btns { - b := tb.btns[index] - for b.Clicked() { - tb.selectedItem = index - if tb.callback != nil { - tb.callback(tb.selectedItem) - } - } - } -} - -func (tb *ToggleButton) Layout(gtx layout.Context) layout.Dimensions { - tb.handleClickables() - var btns []layout.FlexChild - for index := range tb.btns { - b := tb.btns[index] - if index == tb.selectedItem { - if tb.colorInverted { - b.Background = tb.theme.Color.Gray5 - } else { - b.Background = tb.theme.Color.Surface - } - } else { - if tb.colorInverted { - b.Background = tb.theme.Color.Surface - } else { - b.Background = tb.theme.Color.Gray5 - } - } - btns = append(btns, layout.Rigid(func(gtx layout.Context) layout.Dimensions { - return layout.UniformInset(5).Layout(gtx, b.Layout) - })) - } - - bg := tb.theme.Color.Gray5 - if tb.colorInverted { - bg = tb.theme.Color.Surface - } - return LinearLayout{ - Width: WrapContent, - Height: WrapContent, - Background: bg, - Border: Border{ - Radius: Radius(8), - }, - }.Layout(gtx, btns...) -} diff --git a/ui/page/dcrdex/dcrdex_page.go b/ui/page/dcrdex/dcrdex_page.go index 3d544ecfe..4ec1d415e 100644 --- a/ui/page/dcrdex/dcrdex_page.go +++ b/ui/page/dcrdex/dcrdex_page.go @@ -34,6 +34,7 @@ func NewDEXPage(l *load.Load) *DEXPage { MasterPage: app.NewMasterPage(DCRDEXID), openTradeMainPage: l.Theme.NewClickable(false), } + dp.inited = true return dp } diff --git a/ui/page/dcrdex/market.go b/ui/page/dcrdex/market.go index 92da3edb5..9cd8ac6f4 100644 --- a/ui/page/dcrdex/market.go +++ b/ui/page/dcrdex/market.go @@ -60,7 +60,7 @@ type DEXMarketPage struct { marketSelector *cryptomaterial.DropDown - toggleBuyAndSellBtn *cryptomaterial.ToggleButton + toggleBuyAndSellBtn *cryptomaterial.SegmentedControl orderTypesDropdown *cryptomaterial.DropDown isMarketOrder bool @@ -71,15 +71,13 @@ type DEXMarketPage struct { seeFullOrderBookBtn cryptomaterial.Button - buySellBtn cryptomaterial.Button + createOrderBtn cryptomaterial.Button buyOrder bool immediateOrder cryptomaterial.CheckBoxStyle immediateMoreInfo *cryptomaterial.Clickable - orders []*order - toggleOpenAndHistoryOrderBtn *cryptomaterial.ToggleButton + toggleOpenAndHistoryOrderBtn *cryptomaterial.SegmentedControl - noOrderMsg string showLoader bool } @@ -91,21 +89,23 @@ func NewDEXMarketPage(l *load.Load) *DEXMarketPage { Axis: layout.Vertical, Alignment: layout.Middle, }, - openOrdersContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, - tradeHistoryContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, - GenericPageModal: app.NewGenericPageModal(DEXAccountOnboardingID), - scrollContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, - priceEditor: newTextEditor(l.Theme, values.String(values.StrPrice), "0", false), - totalEditor: newTextEditor(th, values.String(values.StrTotal), "", false), - switchLotsOrAmount: l.Theme.Switch(), // TODO: Set last user choice, default is unchecked. - lotsAmountEditor: newTextEditor(l.Theme, values.String(values.StrLots), "0", false), - buySellBtn: th.Button(values.String(values.StrBuy)), // TODO: toggle - buyOrder: true, - immediateOrder: th.CheckBox(new(widget.Bool), values.String(values.StrImmediate)), - orderTypesDropdown: th.DropDown(orderTypes, values.DEXOrderTypes, 0), - immediateMoreInfo: th.NewClickable(false), - addServerBtn: th.NewClickable(false), - seeFullOrderBookBtn: th.Button(values.String(values.StrSeeMore)), + openOrdersContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, + tradeHistoryContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, + GenericPageModal: app.NewGenericPageModal(DEXAccountOnboardingID), + scrollContainer: &widget.List{List: layout.List{Axis: layout.Vertical, Alignment: layout.Middle}}, + priceEditor: newTextEditor(l.Theme, values.String(values.StrPrice), "0", false), + totalEditor: newTextEditor(th, values.String(values.StrTotal), "", false), + switchLotsOrAmount: l.Theme.Switch(), // TODO: Set last user choice, default is unchecked. + lotsAmountEditor: newTextEditor(l.Theme, values.String(values.StrLots), "0", false), + createOrderBtn: th.Button(values.String(values.StrBuy)), // TODO: toggle + buyOrder: true, + immediateOrder: th.CheckBox(new(widget.Bool), values.String(values.StrImmediate)), + orderTypesDropdown: th.DropDown(orderTypes, values.DEXOrderTypes, 0), + immediateMoreInfo: th.NewClickable(false), + addServerBtn: th.NewClickable(false), + seeFullOrderBookBtn: th.Button(values.String(values.StrSeeMore)), + toggleBuyAndSellBtn: th.SegmentedControl([]string{values.String(values.StrBuy), values.String(values.StrSell)}), + toggleOpenAndHistoryOrderBtn: th.SegmentedControl([]string{values.String(values.StrOpenOrders), values.String(values.StrTradeHistory)}), } pg.orderTypesDropdown.Width = values.MarginPadding120 @@ -114,44 +114,6 @@ func NewDEXMarketPage(l *load.Load) *DEXMarketPage { pg.orderTypesDropdown.Hoverable = false pg.orderTypesDropdown.NavigationIconColor = &pg.Theme.Color.Primary - buyBtn := th.Button(values.String(values.StrBuy)) - buyBtn.Font.Weight = font.SemiBold - sellBtn := th.Button(values.String(values.StrSell)) - sellBtn.Font.Weight = font.SemiBold - - toggleBtns := []*cryptomaterial.Button{&buyBtn, &sellBtn} - pg.toggleBuyAndSellBtn = th.ToggleButton(toggleBtns, false) - pg.toggleBuyAndSellBtn.SetToggleButtonCallback(func(selectedItem int) { - if selectedItem == 0 { // Buy - pg.buyOrder = true - pg.buySellBtn.Text = values.String(values.StrBuy) - pg.buySellBtn.Background = pg.Theme.Color.Green500 - pg.buySellBtn.HighlightColor = pg.Theme.Color.Success - } else if selectedItem == 1 { // Sell - pg.buyOrder = false - pg.buySellBtn.Text = values.String(values.StrSell) - pg.buySellBtn.Background = pg.Theme.Color.Orange - pg.buySellBtn.HighlightColor = pg.Theme.Color.OrangeRipple - } - }) - pg.toggleBuyAndSellBtn.SelectItemAtIndex(0) - - openOrderBtn := th.Button(values.String(values.StrOpenOrders)) - openOrderBtn.Font.Weight = font.SemiBold - historyOrderBtn := th.Button(values.String(values.StrTradeHistory)) - historyOrderBtn.Font.Weight = font.SemiBold - - toggleOpenAndHistoryOrderBtn := []*cryptomaterial.Button{&openOrderBtn, &historyOrderBtn} - pg.toggleOpenAndHistoryOrderBtn = th.ToggleButton(toggleOpenAndHistoryOrderBtn, true) - pg.toggleOpenAndHistoryOrderBtn.SetToggleButtonCallback(func(selectedItem int) { - if selectedItem == 0 { // TODO: Fetch open orders - pg.noOrderMsg = values.String(values.StrNoOpenOrdersMsg) - } else if selectedItem == 1 { // TODO: Fetch History orders - pg.noOrderMsg = values.String(values.StrNoTradeHistoryMsg) - } - }) - pg.toggleOpenAndHistoryOrderBtn.SelectItemAtIndex(0) - pg.priceEditor.IsTitleLabel = false pg.lotsAmountEditor.IsTitleLabel = false pg.totalEditor.IsTitleLabel = false @@ -163,6 +125,8 @@ func NewDEXMarketPage(l *load.Load) *DEXMarketPage { pg.immediateOrder.Font.Weight = font.SemiBold + pg.setBuyOrSell() + return pg } @@ -207,6 +171,8 @@ func (pg *DEXMarketPage) OnNavigatedTo() { pg.serverSelector.Hoverable, pg.marketSelector.Hoverable = false, false pg.serverSelector.Width, pg.marketSelector.Width = u300, u300 + + // TODO: Fetch orders or order history. } func assetIcon(th *cryptomaterial.Theme, assetType libutils.AssetType) *cryptomaterial.Image { @@ -673,7 +639,7 @@ func (pg *DEXMarketPage) orderForm() func(gtx C) D { }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, - layout.Flexed(1, pg.buySellBtn.Layout), + layout.Flexed(1, pg.createOrderBtn.Layout), ) }), ) @@ -866,14 +832,21 @@ func (pg *DEXMarketPage) openOrdersAndHistory(gtx C) D { Orientation: layout.Vertical, }.Layout(gtx, layout.Rigid(func(gtx C) D { - return pg.toggleOpenAndHistoryOrderBtn.Layout(gtx) + return layout.Inset{Left: u2}.Layout(gtx, pg.toggleOpenAndHistoryOrderBtn.Layout) }), layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween, Alignment: layout.Middle}.Layout(gtx, headersFn...) }), layout.Rigid(func(gtx C) D { if len(orders) == 0 { - return components.LayoutNoOrderHistoryWithMsg(gtx, pg.Load, false, pg.noOrderMsg) + selectedItem := pg.toggleOpenAndHistoryOrderBtn.SelectedIndex() + var noOrderMsg string + if selectedItem == 0 { // TODO: Fetch open orders + noOrderMsg = values.String(values.StrNoOpenOrdersMsg) + } else if selectedItem == 1 { // TODO: Fetch History orders + noOrderMsg = values.String(values.StrNoTradeHistoryMsg) + } + return components.LayoutNoOrderHistoryWithMsg(gtx, pg.Load, false, noOrderMsg) } return pg.Theme.List(pg.openOrdersContainer).Layout(gtx, len(orders), func(gtx C, index int) D { @@ -941,6 +914,23 @@ func (pg *DEXMarketPage) orderColumn(header bool, txt string, columnWidth unit.D }) } +func (pg *DEXMarketPage) setBuyOrSell() { + buySellSegmentIndex := pg.toggleBuyAndSellBtn.SelectedIndex() + if buySellSegmentIndex == 0 { // Buy + pg.buyOrder = true + pg.createOrderBtn.Text = values.String(values.StrBuy) + pg.createOrderBtn.Background = pg.Theme.Color.Green500 + pg.createOrderBtn.HighlightColor = pg.Theme.Color.Success + return + } + + // Sell + pg.buyOrder = false + pg.createOrderBtn.Text = values.String(values.StrSell) + pg.createOrderBtn.Background = pg.Theme.Color.Orange + pg.createOrderBtn.HighlightColor = pg.Theme.Color.OrangeRipple +} + // HandleUserInteractions is called just before Layout() to determine if any // user interaction recently occurred on the page and may be used to update the // page's UI components shortly before they are displayed. @@ -960,6 +950,10 @@ func (pg *DEXMarketPage) HandleUserInteractions() { pg.isMarketOrder = pg.orderTypesDropdown.SelectedIndex() != limitOrderIndex } + if pg.toggleBuyAndSellBtn.Changed() { + pg.setBuyOrSell() + } + for pg.seeFullOrderBookBtn.Clicked() { // TODO: display full order book log.Info("Display full order book")