From ec650392735515f663d079f40ce07cb036d3f97d Mon Sep 17 00:00:00 2001 From: trustable-code Date: Sun, 16 Feb 2020 01:38:34 +0100 Subject: Re-implement label using custom drawing Replaces the native label implementations. Supporting different x and y text alignment. Fixes #90 --- src/nigui.nim | 65 +++++++++++++++++++++++++++-- src/nigui/private/gtk3/gtk3.nim | 6 +-- src/nigui/private/gtk3/platform_impl.nim | 13 +----- src/nigui/private/windows/platform_impl.nim | 6 +-- src/nigui/private/windows/windows.nim | 2 +- 5 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/nigui.nim b/src/nigui.nim index b70d5b0..125a346 100755 --- a/src/nigui.nim +++ b/src/nigui.nim @@ -35,6 +35,16 @@ type YAlign_Center YAlign_Spread + XTextAlign* = enum + XTextAlign_Left + XTextAlign_Right + XTextAlign_Center + + YTextAlign* = enum + YTextAlign_Top + YTextAlign_Bottom + YTextAlign_Center + WidthMode* = enum WidthMode_Static WidthMode_Auto @@ -383,6 +393,8 @@ type Label* = ref object of ControlImpl fText: string + fXTextAlign: XTextAlign + fYTextAlign: YTextAlign ProgressBar* = ref object of ControlImpl fValue: float # should be between 0.0 and 1.0 @@ -960,6 +972,12 @@ proc init*(label: NativeLabel) method text*(label: Label): string {.base.} method `text=`*(label: Label, text: string) {.base.} +method xTextAlign*(label: Label): XTextAlign +method `xTextAlign=`*(label: Label, xTextAlign: XTextAlign) + +method yTextAlign*(label: Label): YTextAlign +method `yTextAlign=`*(label: Label, yTextAlign: YTextAlign) + # ---------------------------------------------------------------------------------------- # ProgressBar @@ -1322,8 +1340,8 @@ method drawTextCentered(canvas: Canvas, text: string, x, y = 0, width, height = var h = height if h == -1: h = canvas.height - let rx = x + (w - canvas.getTextWidth(text)) div 2 - let ry = y + (h - canvas.getTextLineHeight()) div 2 + let rx = x + max((w - canvas.getTextWidth(text)) div 2, 0) + let ry = y + max((h - canvas.getTextLineHeight() * text.countLines) div 2, 0) canvas.drawText(text, rx, ry) method fill(canvas: Canvas) = canvas.drawRectArea(0, 0, canvas.width, canvas.height) @@ -2542,6 +2560,8 @@ proc init(label: Label) = label.fHeightMode = HeightMode_Auto label.minWidth = 10.scaleToDpi label.minHeight = 10.scaleToDpi + label.fXTextAlign = XTextAlign_Left + label.fYTextAlign = YTextAlign_Center method text(label: Label): string = label.fText @@ -2555,7 +2575,46 @@ method naturalWidth(label: Label): int {.locks: "unknown".} = label.getTextWidth method naturalHeight(label: Label): int {.locks: "unknown".} = label.getTextLineHeight() * label.text.countLines -method `onDraw=`(container: NativeLabel, callback: DrawProc) = raiseError("NativeLabel does not allow onDraw.") +method xTextAlign(label: Label): XTextAlign = label.fXTextAlign + +method `xTextAlign=`(label: Label, xTextAlign: XTextAlign) = + label.fXTextAlign = xTextAlign + label.forceRedraw() + +method yTextAlign(label: Label): YTextAlign = label.fYTextAlign + +method `yTextAlign=`(label: Label, yTextAlign: YTextAlign) = + label.fYTextAlign = yTextAlign + label.forceRedraw() + +method handleDrawEvent(label: Label, event: DrawEvent) = + # Use a custom draw for labels, because Windows does not support vertical text aligment. + let callback = label.onDraw + if callback != nil: + callback(event) + return + label.canvas.fontFamily = label.fontFamily + label.canvas.fontSize = label.fontSize + label.canvas.textColor = label.textColor + label.canvas.areaColor = label.backgroundColor + label.canvas.fill() + let x = + case label.xTextAlign + of XTextAlign_Left: + 0 + of XTextAlign_Center: + (label.width - label.naturalWidth) div 2 + of XTextAlign_Right: + label.width - label.naturalWidth + let y = + case label.yTextAlign + of YTextAlign_Top: + 0 + of YTextAlign_Center: + (label.height - label.naturalHeight) div 2 + of YTextAlign_Bottom: + label.height - label.naturalHeight + label.canvas.drawText(label.text, x, y) # ---------------------------------------------------------------------------------------- diff --git a/src/nigui/private/gtk3/gtk3.nim b/src/nigui/private/gtk3/gtk3.nim index 82b555a..67a0e23 100755 --- a/src/nigui/private/gtk3/gtk3.nim +++ b/src/nigui/private/gtk3/gtk3.nim @@ -331,12 +331,12 @@ proc gtk_button_box_set_layout*(widget: pointer, layout_style: cint) {.importc, # proc gtk_message_dialog_new*(parent: pointer, flags: GtkDialogFlags, `type`: GtkMessageType, buttons: GtkButtonsType, message_format: cstring): pointer {.importc, libgtk3.} proc gtk_label_new*(str: cstring): pointer {.importc, libgtk3.} -proc gtk_label_set_text*(label: pointer, str: cstring) {.importc, libgtk3.} +# proc gtk_label_set_text*(label: pointer, str: cstring) {.importc, libgtk3.} # proc gtk_label_get_text*(label: pointer): cstring {.importc, libgtk3.} proc gtk_label_set_ellipsize*(label: pointer, mode: cint) {.importc, libgtk3.} # proc gtk_label_set_justify*(label: pointer, jtype: cint) {.importc, libgtk3.} -proc gtk_label_set_xalign*(label: pointer, xalign: cfloat) {.importc, libgtk3.} -proc gtk_label_set_yalign*(label: pointer, yalign: cfloat) {.importc, libgtk3.} +# proc gtk_label_set_xalign*(label: pointer, xalign: cfloat) {.importc, libgtk3.} +# proc gtk_label_set_yalign*(label: pointer, yalign: cfloat) {.importc, libgtk3.} proc gtk_progress_bar_new*(): pointer {.importc, libgtk3.} proc gtk_progress_bar_set_fraction*(pbar: pointer, fraction: cdouble) {.importc, libgtk3.} diff --git a/src/nigui/private/gtk3/platform_impl.nim b/src/nigui/private/gtk3/platform_impl.nim index f98564d..7ecaf5f 100755 --- a/src/nigui/private/gtk3/platform_impl.nim +++ b/src/nigui/private/gtk3/platform_impl.nim @@ -1356,19 +1356,8 @@ method pAddButtonPressEvent(checkbox: NativeCheckbox) = discard # don't override # ---------------------------------------------------------------------------------------- proc init(label: NativeLabel) = - label.fHandle = gtk_label_new("") - gtk_label_set_xalign(label.fHandle, 0) - gtk_label_set_yalign(label.fHandle, 0.5) - gtk_label_set_ellipsize(label.fHandle, PANGO_ELLIPSIZE_END) label.Label.init() - -method `text=`(label: NativeLabel, text: string) = - procCall label.Label.`text=`(text) - gtk_label_set_text(label.fHandle, text) - app.processEvents() - -method naturalWidth(label: NativeLabel): int {.locks: "unknown".} = label.getTextLineWidth(label.text) + 10 -# Override parent method, to make it big enough for the text to fit in. + label.fFontSize = app.defaultFontSize * 0.95 # ---------------------------------------------------------------------------------------- diff --git a/src/nigui/private/windows/platform_impl.nim b/src/nigui/private/windows/platform_impl.nim index 2ba5f72..3d0cede 100755 --- a/src/nigui/private/windows/platform_impl.nim +++ b/src/nigui/private/windows/platform_impl.nim @@ -1472,12 +1472,8 @@ method `checked=`(checkbox: NativeCheckbox, checked: bool) = # ---------------------------------------------------------------------------------------- proc init(label: NativeLabel) = - label.fHandle = pCreateWindowExWithUserdata("STATIC", WS_CHILD or SS_CENTERIMAGE, 0, pDefaultParentWindow, cast[pointer](label)) label.Label.init() - -method `text=`(label: NativeLabel, text: string) = - procCall label.Label.`text=`(text) - pSetWindowText(label.fHandle, text) + label.fFontSize = app.defaultFontSize * 0.8 # ---------------------------------------------------------------------------------------- diff --git a/src/nigui/private/windows/windows.nim b/src/nigui/private/windows/windows.nim index 6ab983e..26324f8 100755 --- a/src/nigui/private/windows/windows.nim +++ b/src/nigui/private/windows/windows.nim @@ -99,7 +99,7 @@ const SM_CXVSCROLL* = 2 SPI_GETWORKAREA* = 0x0030 SPI_SETKEYBOARDCUES* = 0x100B - SS_CENTERIMAGE* = 0x00000200 + # SS_CENTERIMAGE* = 0x00000200 SW_HIDE* = 0 # SW_MAXIMIZE = 3 SW_SHOW* = 5 -- cgit v1.2.3