Example #1
0
func NewHatchBrush(color Color, style HatchStyle) (*HatchBrush, error) {
	lb := &win.LOGBRUSH{LbStyle: win.BS_HATCHED, LbColor: win.COLORREF(color), LbHatch: uintptr(style)}

	hBrush := win.CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &HatchBrush{hBrush: hBrush, color: color, style: style}, nil
}
Example #2
0
func NewSolidColorBrush(color Color) (*SolidColorBrush, error) {
	lb := &win.LOGBRUSH{LbStyle: win.BS_SOLID, LbColor: win.COLORREF(color)}

	hBrush := win.CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &SolidColorBrush{hBrush: hBrush, color: color}, nil
}
Example #3
0
func NewCosmeticPen(style PenStyle, color Color) (*CosmeticPen, error) {
	lb := &win.LOGBRUSH{LbStyle: win.BS_SOLID, LbColor: win.COLORREF(color)}

	style |= win.PS_COSMETIC

	hPen := win.ExtCreatePen(uint32(style), 1, lb, 0, nil)
	if hPen == 0 {
		return nil, newError("ExtCreatePen failed")
	}

	return &CosmeticPen{hPen: hPen, style: style, color: color}, nil
}
Example #4
0
func (c *Canvas) withFontAndTextColor(font *Font, color Color, f func() error) error {
	return c.withGdiObj(win.HGDIOBJ(font.handleForDPI(c.dpiy)), func() error {
		oldColor := win.SetTextColor(c.hdc, win.COLORREF(color))
		if oldColor == win.CLR_INVALID {
			return newError("SetTextColor failed")
		}
		defer func() {
			win.SetTextColor(c.hdc, oldColor)
		}()

		return f()
	})
}
Example #5
0
func (il *ImageList) AddMasked(bitmap *Bitmap) (int32, error) {
	if bitmap == nil {
		return 0, newError("bitmap cannot be nil")
	}

	index := win.ImageList_AddMasked(
		il.hIml,
		bitmap.handle(),
		win.COLORREF(il.maskColor))
	if index == -1 {
		return 0, newError("ImageList_AddMasked failed")
	}

	return index, nil
}
Example #6
0
func (b *SystemColorBrush) logbrush() *win.LOGBRUSH {
	return &win.LOGBRUSH{
		LbStyle: win.BS_SOLID,
		LbColor: win.COLORREF(win.GetSysColor(b.colorIndex)),
	}
}
Example #7
0
func (b *HatchBrush) logbrush() *win.LOGBRUSH {
	return &win.LOGBRUSH{LbStyle: win.BS_HATCHED, LbColor: win.COLORREF(b.color), LbHatch: uintptr(b.style)}
}
Example #8
0
func (b *SolidColorBrush) logbrush() *win.LOGBRUSH {
	return &win.LOGBRUSH{LbStyle: win.BS_SOLID, LbColor: win.COLORREF(b.color)}
}
Example #9
0
func (tv *TableView) WndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr {
	switch msg {
	case win.WM_ERASEBKGND:
		if tv.lastColumnStretched && !tv.inEraseBkgnd {
			tv.inEraseBkgnd = true
			defer func() {
				tv.inEraseBkgnd = false
			}()
			tv.StretchLastColumn()
		}
		return 1

	case win.WM_GETDLGCODE:
		if wParam == win.VK_RETURN {
			return win.DLGC_WANTALLKEYS
		}

	case win.WM_LBUTTONDOWN, win.WM_RBUTTONDOWN, win.WM_LBUTTONDBLCLK, win.WM_RBUTTONDBLCLK:
		var hti win.LVHITTESTINFO
		hti.Pt = win.POINT{win.GET_X_LPARAM(lParam), win.GET_Y_LPARAM(lParam)}
		tv.SendMessage(win.LVM_HITTEST, 0, uintptr(unsafe.Pointer(&hti)))

		if hti.Flags == win.LVHT_NOWHERE && tv.SingleItemSelection() {
			// We keep the current item, if in single item selection mode.
			tv.SetFocus()
			return 0
		}

		switch msg {
		case win.WM_LBUTTONDOWN, win.WM_RBUTTONDOWN:
			if hti.Flags == win.LVHT_ONITEMSTATEICON &&
				tv.itemChecker != nil &&
				tv.CheckBoxes() {

				tv.toggleItemChecked(int(hti.IItem))
			}
		}

	case win.WM_KEYDOWN:
		if wParam == win.VK_SPACE &&
			tv.currentIndex > -1 &&
			tv.itemChecker != nil &&
			tv.CheckBoxes() {

			tv.toggleItemChecked(tv.currentIndex)
		}

	case win.WM_NOTIFY:
		switch int32(((*win.NMHDR)(unsafe.Pointer(lParam))).Code) {
		case win.LVN_GETDISPINFO:
			di := (*win.NMLVDISPINFO)(unsafe.Pointer(lParam))

			row := int(di.Item.IItem)
			col := tv.fromLVColIdx(di.Item.ISubItem)

			if di.Item.Mask&win.LVIF_TEXT > 0 {
				var text string
				switch val := tv.model.Value(row, col).(type) {
				case string:
					text = val

				case float32:
					prec := tv.columns.items[col].precision
					if prec == 0 {
						prec = 2
					}
					text = FormatFloatGrouped(float64(val), prec)

				case float64:
					prec := tv.columns.items[col].precision
					if prec == 0 {
						prec = 2
					}
					text = FormatFloatGrouped(val, prec)

				case time.Time:
					if val.Year() > 1601 {
						text = val.Format(tv.columns.items[col].format)
					}

				case *big.Rat:
					prec := tv.columns.items[col].precision
					if prec == 0 {
						prec = 2
					}
					text = formatBigRatGrouped(val, prec)

				default:
					text = fmt.Sprintf(tv.columns.items[col].format, val)
				}

				utf16 := syscall.StringToUTF16(text)
				buf := (*[264]uint16)(unsafe.Pointer(di.Item.PszText))
				max := mini(len(utf16), int(di.Item.CchTextMax))
				copy((*buf)[:], utf16[:max])
				(*buf)[max-1] = 0
			}

			if tv.imageProvider != nil && di.Item.Mask&win.LVIF_IMAGE > 0 {
				if image := tv.imageProvider.Image(row); image != nil {
					if tv.hIml == 0 {
						tv.applyImageListForImage(image)
					}

					di.Item.IImage = imageIndexMaybeAdd(
						image,
						tv.hIml,
						tv.usingSysIml,
						tv.imageUintptr2Index,
						tv.filePath2IconIndex)
				}
			}

			if di.Item.StateMask&win.LVIS_STATEIMAGEMASK > 0 &&
				tv.itemChecker != nil {
				checked := tv.itemChecker.Checked(row)

				if checked {
					di.Item.State = 0x2000
				} else {
					di.Item.State = 0x1000
				}
			}

		case win.NM_CUSTOMDRAW:
			if tv.alternatingRowBGColor != defaultTVRowBGColor {
				nmlvcd := (*win.NMLVCUSTOMDRAW)(unsafe.Pointer(lParam))

				switch nmlvcd.Nmcd.DwDrawStage {
				case win.CDDS_PREPAINT:
					return win.CDRF_NOTIFYITEMDRAW

				case win.CDDS_ITEMPREPAINT:
					if nmlvcd.Nmcd.DwItemSpec%2 == 1 {
						/*if tv.hasDarkAltBGColor &&
							nmlvcd.Nmcd.UItemState&win.CDIS_HOT == 0 &&
							tv.SendMessage(win.LVM_GETITEMSTATE, nmlvcd.Nmcd.DwItemSpec, win.LVIS_SELECTED) == 0 &&
							int32(tv.SendMessage(win.LVM_GETSELECTEDCOLUMN, 0, 0)) != nmlvcd.ISubItem {
							fmt.Printf("selcol: %d, subitem: %d\n", int32(tv.SendMessage(win.LVM_GETSELECTEDCOLUMN, 0, 0)), nmlvcd.ISubItem)
							nmlvcd.ClrText = white
						}*/
						nmlvcd.ClrTextBk = win.COLORREF(tv.alternatingRowBGColor)
					}

					return win.CDRF_NOTIFYSUBITEMDRAW

				case win.CDDS_ITEMPREPAINT | win.CDDS_SUBITEM:
					if nmlvcd.Nmcd.DwItemSpec%2 == 1 &&
						tv.hasDarkAltBGColor &&
						nmlvcd.Nmcd.UItemState&win.CDIS_HOT == 0 &&
						tv.SendMessage(win.LVM_GETITEMSTATE, nmlvcd.Nmcd.DwItemSpec, win.LVIS_SELECTED) == 0 &&
						int32(tv.SendMessage(win.LVM_GETSELECTEDCOLUMN, 0, 0)) != nmlvcd.ISubItem {

						nmlvcd.ClrText = white
					}

					return win.CDRF_NEWFONT
				}
			}

			return win.CDRF_DODEFAULT

		case win.LVN_COLUMNCLICK:
			nmlv := (*win.NMLISTVIEW)(unsafe.Pointer(lParam))

			col := tv.fromLVColIdx(nmlv.ISubItem)
			tv.columnClickedPublisher.Publish(col)

			if sorter, ok := tv.model.(Sorter); ok && sorter.ColumnSortable(col) {
				prevCol := sorter.SortedColumn()
				var order SortOrder
				if col != prevCol || sorter.SortOrder() == SortDescending {
					order = SortAscending
				} else {
					order = SortDescending
				}
				tv.sortedColumnIndex = col
				tv.sortOrder = order
				sorter.Sort(col, order)
			}

		case win.LVN_ITEMCHANGED:
			nmlv := (*win.NMLISTVIEW)(unsafe.Pointer(lParam))
			selectedNow := nmlv.UNewState&win.LVIS_SELECTED > 0
			selectedBefore := nmlv.UOldState&win.LVIS_SELECTED > 0
			if selectedNow && !selectedBefore {
				tv.currentIndex = int(nmlv.IItem)
				if tv.itemStateChangedEventDelay > 0 {
					tv.delayedCurrentIndexChangedCanceled = false
					if 0 == win.SetTimer(
						tv.hWnd,
						tableViewCurrentIndexChangedTimerId,
						uint32(tv.itemStateChangedEventDelay),
						0) {

						lastError("SetTimer")
					}
				} else {
					tv.currentIndexChangedPublisher.Publish()
				}
			}
			if !tv.SingleItemSelection() {
				tv.updateSelectedIndexes()
			}

		case win.LVN_ITEMACTIVATE:
			nmia := (*win.NMITEMACTIVATE)(unsafe.Pointer(lParam))

			if tv.itemStateChangedEventDelay > 0 {
				tv.delayedCurrentIndexChangedCanceled = true
			}

			tv.SetCurrentIndex(int(nmia.IItem))
			tv.currentIndexChangedPublisher.Publish()

			tv.itemActivatedPublisher.Publish()
		}

	case win.WM_TIMER:
		switch wParam {
		case tableViewCurrentIndexChangedTimerId:
			if !tv.delayedCurrentIndexChangedCanceled {
				tv.currentIndexChangedPublisher.Publish()
			}

		case tableViewSelectedIndexesChangedTimerId:
			tv.selectedIndexesChangedPublisher.Publish()
		}
	}

	return tv.WidgetBase.WndProc(hwnd, msg, wParam, lParam)
}
Example #10
0
	"log"
	"math/big"
	"strconv"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

import (
	"github.com/lxn/win"
)

var (
	defaultTVRowBGColor Color = Color(win.GetSysColor(win.COLOR_WINDOW))
	white                     = win.COLORREF(RGB(255, 255, 255))
)

const (
	tableViewCurrentIndexChangedTimerId = 1 + iota
	tableViewSelectedIndexesChangedTimerId
)

// TableView is a model based widget for record centric, tabular data.
//
// TableView is implemented as a virtual mode list view to support quite large
// amounts of data.
type TableView struct {
	WidgetBase
	columns                            *TableViewColumnList
	model                              TableModel