khchen / wNim

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

auto layout: UnsatisfiableConstraintException #45

Closed retsyo closed 4 years ago

retsyo commented 4 years ago

I just can't understand VFL well, so this issue may be a problem with my code I have tested the VFL on https://rawgit.com/IjzerenHein/visualformat-editor/master/dist/index.html?vfl=example, however when I translate it into nim, the generated EXE exists and says

solver.nim(74)           addConstraint
Error: unhandled exception:  [UnsatisfiableConstraintException]

so what is the problem? Thanks

import wNim

let app = App()
let frame = Frame(title="title", style=wDefaultFrameStyle or wModalFrame)
let panel = Panel(frame)

let txtInput = TextCtrl(panel, value="50")
let label1 = StaticText(panel, label="label1")

let label2 = StaticText(panel, label="label2")
let txtMax = TextCtrl(panel, value="")

let label3 = StaticText(panel, label="label3")
let txtNum = TextCtrl(panel, value="")

let btn = Button(panel, label="click")

let listbox = ListBox(panel, style=wLbNoSel or wBorderSimple or wLbNeededScroll)

proc layout() =
    panel .autolayout """
        H:{row1:[txtInput(40%)]-[label1]}
        H:{row2:[label2(30%)]-[txtMax]}
        H:{row3:[label3(30%)]-[txtNum]}
        H:{row4:~[btn(20%)]~}
        V:{columnLeft:[row1(row2,row3)]-20-[row2]-20-[row3]-20-[row4(10%)]}

        H:|[columnLeft(70%)]-[listbox]|
        V:|[columnLeft(listbox)]|

    """

panel.wEvent_Size do ():
    layout()

layout()
frame.center()
frame.show()
app.mainLoop()

and the VFL I tested in AUTOLAYOUT.JS' Visual Format Editor

H:[row1:[txtInput(40%)]-[label1]]
H:[row2:[label2(30%)]-[txtMax]]
H:[row3:[label3(30%)]-[txtNum]]
H:[row4:~[btn(20%)]~]
V:[columnLeft:[row1(row2,row3)]-20-[row2]-20-[row3]-20-[row4(10%)]]

H:|[columnLeft(70%)]-[listbox]|
V:|[columnLeft(listbox)]|

s

khchen commented 4 years ago

This code works.


proc layout() =
    panel .autolayout """
        H:|{row1:[txtInput(40%)]-[label1]}-[listbox]|
        H:|{row2:[label2(30%)]-[txtMax]}-[listbox]|
        H:|{row3:[label3(30%)]-[txtNum]}-[listbox]|
        H:|~{row4:[btn(20%)]}~[listbox(30%)]|

        V:|[row1(row2,row3)]-20-[row2]-20-[row3]-20-[row4(10%)]|
        V:|[listbox]|
    """

The point is that I don't treat "view stacks" as an element. It just some kind of batch operation in wNim's autolayout.

retsyo commented 4 years ago

sorry, yet another question. How to autolayout this VFL, which can be presented on https://rawgit.com/IjzerenHein/visualformat-editor/master/dist/index.html?vfl=example

H:|-[row1:[text1(70%)]-[btn1]]-|
H:|-[row2:[text2(70%)]-[btn2]]-|
V:|[row3_1:[btn3]-[checkbox(50%)]]|
H:|[btn3(checkbox)]|
H:|-[row3:[row3_1(btn4,btn5,btn6)]-[btn4]-[btn5]-[btn6]]-|
V:|-[row1(20%)]-[row2(20%)]-[row3]-|

where,

checkbox.width == btn3.width == btn4.width == btn5.width == btn6.width 
(btn3.height + gap + checkbox.height) == btn4.height == btn5.height == btn6.height
checkbox.height == 50% * btn3.height

however

  1. this code will say Error: unhandled exception: [UnsatisfiableConstraintException]
H:|-{row1:[text1(70%)]-[btn1]}-|
H:|-{row2:[text2(70%)]-[btn2]}-|
V:|{row3_1:[btn3]-[checkbox(50%)]}|
H:|[btn3(checkbox)]|
H:|-{row3:[row3_1(btn4,btn5,btn6)]-[btn4]-[btn5]-[btn6]}-|
V:|-[row1(20%)]-[row2(20%)]-[row3]-|

as what you have explained before

  1. line V:|[row3_1:[btn3]-[checkbox(50%)]]| treats checkbox's height to be 50% of the whole panel's height, not 50% of the btn3.height

any hints to fix this problem? Thanks

khchen commented 4 years ago

Again, Don't treat "view stacks" as an element for now. I guess what you want:

import wNim/[wApp, wFrame, wButton]
import macros, strformat

let app = App()
let frame = Frame()

macro createElements(list: varargs[untyped]): untyped =
  result = newStmtList()
  for i in list:
    result.add parseStmt(fmt"let {i} = Button(frame, label=""{i}"")")

createElements(text1, text2, btn1, btn2, btn3, btn4, btn5, btn6, checkbox)

frame.wEvent_Size do ():
  frame.autolayout """
    H:|-[text1..2(70%)]-[btn1..2]-|
    H:|-[btn3(btn4,btn5,btn6)]-[btn4]-[btn5]-[btn6]-|
    H:|-[checkbox]-[btn4]-[btn5]-[btn6]-|
    V:|-[text1(20%)]-[text2(20%)]-[btn3]-[checkbox(btn3)]-|
    V:|-[text1(20%)]-[text2(20%)]-[btn4]-|
    V:|-[btn1(text1)]-[btn2(text2)]-[btn4..6]-|
  """

frame.center()
frame.show()
app.mainLoop()