khchen / wNim

Nim's Windows GUI Framework
MIT License
326 stars 17 forks source link

[help wanted] dc draw event and draw polygon #60

Closed retsyo closed 4 years ago

retsyo commented 4 years ago

In one simplified case, 2 buttons are created and layout by layout function. Then the buttons are enclosed in a filled polygon to say "they are responsible for task 1". In case you are curious, there is, in fact, another “┐”-shape polygon for task 2. The polygon has a 5-pixel distance between panel and buttons.

the 1st question

Currently, when my application launches, the layout does not work. But after I have resized the window, it functions as expected from then on. So this is the problem, any way to fix it?

the 2nd question

Then, as the code shows, it is tedious to calculate the coordinate of the polygon. What is the name of this kind of problem? So maybe google can find a library/algorithms for it

the 3rd question

is there an easy way to draw the polygon with rounded corners?

Thanks

import wNim
var app = App()

var frame = Frame(title="Draw on Panel")
var panel = Panel(frame)
var btn1 = Button(panel, label="btn1")
var btn2 = Button(panel, label="btn2")

panel.wEvent_Paint do(event: wEvent):
    var dc = PaintDC(event.window)
    dc.clear()
    dc.brush = Brush(color=0xD9AA85)
    dc.pen = wTransparentPen
    dc.setPen(Pen(wBLACK, width=1))

    dc.drawPolygon([
        (panel.getPosition.x + 5, panel.getPosition.y + 5),
        (panel.getPosition.x + 5, panel.getPosition.y + panel.getSize.height - 5),
        (panel.getPosition.x + panel.getSize.width - 5, panel.getPosition.y + panel.getSize.height - 5),
        (panel.getPosition.x + panel.getSize.width - 5, btn2.getPosition.y - 5),
        (btn1.getPosition.x + btn1.getSize.width + 5, btn2.getPosition.y - 5),
        (btn1.getPosition.x + btn1.getSize.width + 5, panel.getPosition.y + 5)
    ])

proc layout() =
    panel.layout:
        btn1:
            left == panel.left + 10
            top == panel.top + 10
            width == panel.width / 4
            height == (panel.height - 10 - 5 - 10)  / 3 * 2

        btn2:
            left == btn1.left
            top == btn1.bottom + 5
            width == panel.width - 20
            height == (panel.height - 10 - 5 - 10)  / 3

panel.wEvent_Size do ():
    layout()

frame.show(true)
app.mainLoop()
khchen commented 4 years ago
  1. Calls layout() before frame.show().
  2. You can try using wRegion.
  3. Same as above.

Ps. Current wDC cannot paint a wRegion object. This may be improved in latter version. The example use FillRgn() and FrameRgn() Win32 API.

import wNim
import winim/inc/wingdi

proc inflate(r: wRect, x, y: int): wRect =
  result.x = r.x - x
  result.y = r.y - y
  result.width = r.width + (x * 2)
  result.height = r.height + (y * 2)

var app = App()

var frame = Frame(title="Draw on Panel")
var panel = Panel(frame)
var btn1 = Button(panel, label="btn1")
var btn2 = Button(panel, label="btn2")

panel.wEvent_Paint do(event: wEvent):
  var
    dc = PaintDC(event.window)
    rect1 = btn1.rect.inflate(5, 5)
    rect2 = btn2.rect.inflate(5, 5)
    brush = Brush(color=0xD9AA85)

  var region = Region(rect1, radius=5.0) or Region(rect2, radius=5.0)
  FillRgn(dc.handle, region.handle, brush.handle)
  FrameRgn(dc.handle, region.handle, wBlackBrush.handle, 1, 1)

proc layout() =
  panel.layout:
    btn1:
      left == panel.left + 10
      top == panel.top + 10
      width == panel.width / 4
      height == (panel.height - 10 - 5 - 10)  / 3 * 2

    btn2:
      left == btn1.left
      top == btn1.bottom + 5
      width == panel.width - 20
      height == (panel.height - 10 - 5 - 10)  / 3

panel.wEvent_Size do ():
  layout()

layout()
frame.show(true)
app.mainLoop()
retsyo commented 4 years ago

thanks it solved most of the questions, but not the round corner of the L. So maybe I should try to coin a complex code to implement it in the feature.

btw, the rounded corner is not so smooth and we can find obvious zigzag.

khchen commented 4 years ago

You can change the radius, for example:

var region = Region(rect1, radius=20.0) or Region(rect2, radius=20.0)