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  }