github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/winc/tabview.go (about) 1 //go:build windows 2 3 /* 4 * Copyright (C) 2019 The Winc Authors. All Rights Reserved. 5 */ 6 7 package winc 8 9 import ( 10 "syscall" 11 "unsafe" 12 13 "github.com/secoba/wails/v2/internal/frontend/desktop/windows/winc/w32" 14 ) 15 16 // TabView creates MultiPanel internally and manages tabs as panels. 17 type TabView struct { 18 ControlBase 19 20 panels *MultiPanel 21 onSelectedChange EventManager 22 } 23 24 func NewTabView(parent Controller) *TabView { 25 tv := new(TabView) 26 27 tv.InitControl("SysTabControl32", parent, 0, 28 w32.WS_CHILD|w32.WS_VISIBLE|w32.WS_TABSTOP|w32.WS_CLIPSIBLINGS) 29 RegMsgHandler(tv) 30 31 tv.panels = NewMultiPanel(parent) 32 33 tv.SetFont(DefaultFont) 34 tv.SetSize(200, 24) 35 return tv 36 } 37 38 func (tv *TabView) Panels() *MultiPanel { 39 return tv.panels 40 } 41 42 func (tv *TabView) tcitemFromPage(panel *Panel) *w32.TCITEM { 43 text := syscall.StringToUTF16(panel.Text()) 44 item := &w32.TCITEM{ 45 Mask: w32.TCIF_TEXT, 46 PszText: &text[0], 47 CchTextMax: int32(len(text)), 48 } 49 return item 50 } 51 52 func (tv *TabView) AddPanel(text string) *Panel { 53 panel := NewPanel(tv.panels) 54 panel.SetText(text) 55 56 item := tv.tcitemFromPage(panel) 57 index := tv.panels.Count() 58 idx := int(w32.SendMessage(tv.hwnd, w32.TCM_INSERTITEM, uintptr(index), uintptr(unsafe.Pointer(item)))) 59 if idx == -1 { 60 panic("SendMessage(TCM_INSERTITEM) failed") 61 } 62 63 tv.panels.AddPanel(panel) 64 tv.SetCurrent(idx) 65 return panel 66 } 67 68 func (tv *TabView) DeletePanel(index int) { 69 w32.SendMessage(tv.hwnd, w32.TCM_DELETEITEM, uintptr(index), 0) 70 tv.panels.DeletePanel(index) 71 switch { 72 case tv.panels.Count() > index: 73 tv.SetCurrent(index) 74 case tv.panels.Count() == 0: 75 tv.SetCurrent(0) 76 } 77 } 78 79 func (tv *TabView) Current() int { 80 return tv.panels.Current() 81 } 82 83 func (tv *TabView) SetCurrent(index int) { 84 if index < 0 || index >= tv.panels.Count() { 85 panic("invalid index") 86 } 87 if ret := int(w32.SendMessage(tv.hwnd, w32.TCM_SETCURSEL, uintptr(index), 0)); ret == -1 { 88 panic("SendMessage(TCM_SETCURSEL) failed") 89 } 90 tv.panels.SetCurrent(index) 91 } 92 93 func (tv *TabView) WndProc(msg uint32, wparam, lparam uintptr) uintptr { 94 switch msg { 95 case w32.WM_NOTIFY: 96 nmhdr := (*w32.NMHDR)(unsafe.Pointer(lparam)) 97 98 switch int32(nmhdr.Code) { 99 case w32.TCN_SELCHANGE: 100 cur := int(w32.SendMessage(tv.hwnd, w32.TCM_GETCURSEL, 0, 0)) 101 tv.SetCurrent(cur) 102 103 tv.onSelectedChange.Fire(NewEvent(tv, nil)) 104 } 105 } 106 return w32.DefWindowProc(tv.hwnd, msg, wparam, lparam) 107 }