github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/winc/panel.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  	"fmt"
    11  
    12  	"github.com/secoba/wails/v2/internal/frontend/desktop/windows/winc/w32"
    13  )
    14  
    15  type Panel struct {
    16  	ControlBase
    17  	layoutMng LayoutManager
    18  }
    19  
    20  func NewPanel(parent Controller) *Panel {
    21  	pa := new(Panel)
    22  
    23  	RegClassOnlyOnce("winc_Panel")
    24  	pa.hwnd = CreateWindow("winc_Panel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE)
    25  	pa.parent = parent
    26  	RegMsgHandler(pa)
    27  
    28  	pa.SetFont(DefaultFont)
    29  	pa.SetText("")
    30  	pa.SetSize(200, 65)
    31  	return pa
    32  }
    33  
    34  // SetLayout panel implements DockAllow interface.
    35  func (pa *Panel) SetLayout(mng LayoutManager) {
    36  	pa.layoutMng = mng
    37  }
    38  
    39  func (pa *Panel) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
    40  	switch msg {
    41  	case w32.WM_SIZE, w32.WM_PAINT:
    42  		if pa.layoutMng != nil {
    43  			pa.layoutMng.Update()
    44  		}
    45  	}
    46  	return w32.DefWindowProc(pa.hwnd, msg, wparam, lparam)
    47  }
    48  
    49  var errorPanelPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(255, 128, 128)))
    50  var errorPanelOkPen = NewPen(w32.PS_GEOMETRIC, 2, NewSolidColorBrush(RGB(220, 220, 220)))
    51  
    52  // ErrorPanel shows errors or important messages.
    53  // It is meant to stand out of other on screen controls.
    54  type ErrorPanel struct {
    55  	ControlBase
    56  	pen    *Pen
    57  	margin int
    58  }
    59  
    60  // NewErrorPanel.
    61  func NewErrorPanel(parent Controller) *ErrorPanel {
    62  	f := new(ErrorPanel)
    63  	f.init(parent)
    64  
    65  	f.SetFont(DefaultFont)
    66  	f.SetText("No errors")
    67  	f.SetSize(200, 65)
    68  	f.margin = 5
    69  	f.pen = errorPanelOkPen
    70  	return f
    71  }
    72  
    73  func (epa *ErrorPanel) init(parent Controller) {
    74  	RegClassOnlyOnce("winc_ErrorPanel")
    75  
    76  	epa.hwnd = CreateWindow("winc_ErrorPanel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE)
    77  	epa.parent = parent
    78  
    79  	RegMsgHandler(epa)
    80  }
    81  
    82  func (epa *ErrorPanel) SetMargin(margin int) {
    83  	epa.margin = margin
    84  }
    85  
    86  func (epa *ErrorPanel) Printf(format string, v ...interface{}) {
    87  	epa.SetText(fmt.Sprintf(format, v...))
    88  	epa.ShowAsError(false)
    89  }
    90  
    91  func (epa *ErrorPanel) Errorf(format string, v ...interface{}) {
    92  	epa.SetText(fmt.Sprintf(format, v...))
    93  	epa.ShowAsError(true)
    94  }
    95  
    96  func (epa *ErrorPanel) ShowAsError(show bool) {
    97  	if show {
    98  		epa.pen = errorPanelPen
    99  	} else {
   100  		epa.pen = errorPanelOkPen
   101  	}
   102  	epa.Invalidate(true)
   103  }
   104  
   105  func (epa *ErrorPanel) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
   106  	switch msg {
   107  	case w32.WM_ERASEBKGND:
   108  		canvas := NewCanvasFromHDC(w32.HDC(wparam))
   109  		r := epa.Bounds()
   110  		r.rect.Left += int32(epa.margin)
   111  		r.rect.Right -= int32(epa.margin)
   112  		r.rect.Top += int32(epa.margin)
   113  		r.rect.Bottom -= int32(epa.margin)
   114  		// old code used NewSystemColorBrush(w32.COLOR_BTNFACE)
   115  		canvas.DrawFillRect(r, epa.pen, NewSystemColorBrush(w32.COLOR_WINDOW))
   116  
   117  		r.rect.Left += 5
   118  		canvas.DrawText(epa.Text(), r, 0, epa.Font(), RGB(0, 0, 0))
   119  		canvas.Dispose()
   120  		return 1
   121  	}
   122  	return w32.DefWindowProc(epa.hwnd, msg, wparam, lparam)
   123  }
   124  
   125  // MultiPanel contains other panels and only makes one of them visible.
   126  type MultiPanel struct {
   127  	ControlBase
   128  	current int
   129  	panels  []*Panel
   130  }
   131  
   132  func NewMultiPanel(parent Controller) *MultiPanel {
   133  	mpa := new(MultiPanel)
   134  
   135  	RegClassOnlyOnce("winc_MultiPanel")
   136  	mpa.hwnd = CreateWindow("winc_MultiPanel", parent, w32.WS_EX_CONTROLPARENT, w32.WS_CHILD|w32.WS_VISIBLE)
   137  	mpa.parent = parent
   138  	RegMsgHandler(mpa)
   139  
   140  	mpa.SetFont(DefaultFont)
   141  	mpa.SetText("")
   142  	mpa.SetSize(300, 200)
   143  	mpa.current = -1
   144  	return mpa
   145  }
   146  
   147  func (mpa *MultiPanel) Count() int { return len(mpa.panels) }
   148  
   149  // AddPanel adds panels to the internal list, first panel is visible all others are hidden.
   150  func (mpa *MultiPanel) AddPanel(panel *Panel) {
   151  	if len(mpa.panels) > 0 {
   152  		panel.Hide()
   153  	}
   154  	mpa.current = 0
   155  	mpa.panels = append(mpa.panels, panel)
   156  }
   157  
   158  // ReplacePanel replaces panel, useful for refreshing controls on screen.
   159  func (mpa *MultiPanel) ReplacePanel(index int, panel *Panel) {
   160  	mpa.panels[index] = panel
   161  }
   162  
   163  // DeletePanel removed panel.
   164  func (mpa *MultiPanel) DeletePanel(index int) {
   165  	mpa.panels = append(mpa.panels[:index], mpa.panels[index+1:]...)
   166  }
   167  
   168  func (mpa *MultiPanel) Current() int {
   169  	return mpa.current
   170  }
   171  
   172  func (mpa *MultiPanel) SetCurrent(index int) {
   173  	if index >= len(mpa.panels) {
   174  		panic("index greater than number of panels")
   175  	}
   176  	if mpa.current == -1 {
   177  		panic("no current panel, add panels first")
   178  	}
   179  	for i := range mpa.panels {
   180  		if i != index {
   181  			mpa.panels[i].Hide()
   182  			mpa.panels[i].Invalidate(true)
   183  		}
   184  	}
   185  	mpa.panels[index].Show()
   186  	mpa.panels[index].Invalidate(true)
   187  	mpa.current = index
   188  }
   189  
   190  func (mpa *MultiPanel) WndProc(msg uint32, wparam, lparam uintptr) uintptr {
   191  	switch msg {
   192  	case w32.WM_SIZE:
   193  		// resize contained panels
   194  		for _, p := range mpa.panels {
   195  			p.SetPos(0, 0)
   196  			p.SetSize(mpa.Size())
   197  		}
   198  	}
   199  	return w32.DefWindowProc(mpa.hwnd, msg, wparam, lparam)
   200  }