simonkrauter / NiGui

Cross-platform desktop GUI toolkit written in Nim
MIT License
724 stars 49 forks source link

drawing on with layouts #95

Closed mhessler97 closed 6 months ago

mhessler97 commented 4 years ago

I am trying to make it possible to draw on a window and change what the mouse uses for drawing between circles and rectangles. I am able to get it so that I can draw a circle whenever I click on the window and when a control is the only thing added to a window. however when I try and add layouts so that I can place buttons I am no longer able to add a control to the window and attempts to use the ondraw proc from other sources such as a layout do not work and cause errors. is there any other way to do this or would it be possible to allow a canvas outside of the ondraw proc to be updated with the drawings? I have attached the code below that is working for a simple drawing with left in ideas for adding layouts. thank you for any help.

import nigui

app.init()
var window = newWindow()
window.width = 500
window.height = 500
let controller1 = newControl()
window.add(controller1)
var mainlayout = newLayoutContainer(Layout_Vertical)
var buttons = newLayoutContainer(Layout_Horizontal)
var control1 = newLayoutContainer(Layout_Horizontal)

#window.add(mainlayout)

#mainlayout.add(control1)
var button = newButton("circle")
#buttons.add(button)
#window.add(drawer)

var counter = 1

controller1.setBackgroundColor(rgb(30,60,90))
controller1.widthMode = WidthMode_Expand

controller1.heightMode= HeightMode_Expand
var x,y:int

controller1.onDraw= proc (event:DrawEvent) = 
    let canvas = event.control.canvas
    if counter > 1:
        var size = 8
        canvas.areaColor = rgb(0, 0, 0) # black
        canvas.drawEllipseArea(x - int(size/2), y - int(size/2), size, size)
        canvas.drawRectArea(x, y, 5, 5)

controller1.onMouseButtonDown = proc (event: MouseEvent) =
  echo(event.button, " (", event.x, ", ", event.y, ")")
  x = event.x
  y = event.y
  counter.inc()
  discard controller1.onDraw()
  event.control.forceRedraw()

window.show()
app.run()
simonkrauter commented 4 years ago

What you explained should work. You can draw on a control which is part of a layout. The drawing control should not have any child controls.

I think the code should be like this:

import nigui

app.init()
var window = newWindow()
window.width = 500
window.height = 500

var mainlayout = newLayoutContainer(Layout_Vertical)
window.add(mainlayout)

var buttons = newLayoutContainer(Layout_Horizontal)
mainlayout.add(buttons)

let controller1 = newControl()
mainlayout.add(controller1)

var button = newButton("circle")
buttons.add(button)

var counter = 1

controller1.setBackgroundColor(rgb(30,60,90))
controller1.widthMode = WidthMode_Expand

controller1.heightMode= HeightMode_Expand
var x,y:int

controller1.onDraw= proc (event:DrawEvent) =
    let canvas = event.control.canvas
    if counter > 1:
        var size = 8
        canvas.areaColor = rgb(0, 0, 0) # black
        canvas.drawEllipseArea(x - int(size/2), y - int(size/2), size, size)
        canvas.drawRectArea(x, y, 5, 5)

controller1.onMouseButtonDown = proc (event: MouseEvent) =
  echo(event.button, " (", event.x, ", ", event.y, ")")
  x = event.x
  y = event.y
  counter.inc()
  discard controller1.onDraw()
  event.control.forceRedraw()

window.show()
app.run()
mhessler97 commented 4 years ago

thanks that solved the problem. adding this as an example may be beneficial for future users for figuring out how to dynamically draw on canvas. also is there a way to track mouse movement so that I can form continuous lines while drawing?

simonkrauter commented 6 months ago

I have implemented mouse move events now, see 4c0ae23. You need to use the git head revision. Feedback is welcome, especially how it affects the application's CPU usage under Windows.