Version 10 of Move any widget

Updated 2010-03-28 21:45:47 by wjg

SeS: In my quest to develop a gui generator, I have reached a stage in which I need to provide the user the ability to explore widgets placement and do a quick and easy form layout design. Same idea as some of us are already familiar with within Visual Basic and C++. The code presented here is a simplified version in order to be able to share it with a wider tcl/tk community, from newbie to guru.

The code as presented is developed in & for (yes, the tool is creating itself) tG2 v1.06.01

Some limitations which have already been solved in tG2:

  - the titlebar height and framewidth of a toplevel is assumed fixed
  - when widgets are placed in frames, it will create another offset which needs to be taken into account, recursively...

The presented code is tested with tcl/tk v8.4.19 & WinXP OS.

# ------------------------------------------------------------------------------
bind . <Configure> {set components(geo) [split [split [wm geometry .] "x"] "+"]}

# ------------------------------------------------------------------------------
bind . <Motion> {
  if {$components(moveObject) != ""} {
    place $components(moveObject) \
      -x [expr [winfo pointerx .] - [lindex $components(geo) 1] - 3  - $objectXoff] \
      -y [expr [winfo pointery .] - [lindex $components(geo) 2] - 29 - $objectYoff]
  }
}

# ------------------------------------------------------------------------------
proc makeMovableObject {w} {
  set cmd "bind $w  <Motion>    \{$w config -cursor crosshair\}"; eval $cmd
  set cmd "bind $w  <Leave>     \{$w config -cursor \"\"\}"; eval $cmd
  set cmd "bind $w  <ButtonPress-1>   \{+; 
    set objectXoff \[expr %x]
    set objectYoff \[expr %y]
    set components(moveObject) $w
    eval \[bind . <Motion>\]
  \}"
  eval $cmd
  
  bind $w <ButtonRelease-1> {+; 
    set components(moveObject) ""
  }
}

set components(moveObject) ""
eval [bind . <Configure>]

# ---------------------------------- TEST CODE ---------------------------------
button .button1 -text "hello world"
place .button1 -x 50 -y 50
makeMovableObject .button1

label .label1 -text "hello again"
place .label1 -x 50 -y 80
makeMovableObject .label1

AMG: Is there any particular reason why the braces backslashed inside of double quotes? e.g. "foo \{ bar \} quux" As far as I know, this is only necessary when a brace-quoted string (here, the third argument to proc) contains mismatched braces, and this is necessary even outside double quotes, for instance in comments. Maybe you're just doing it out of stylistic preference, which is just fine.

Also I am curious about this use of eval. Why put the script inside a variable? Just pass it to eval directly. I can see why you're tempted to use eval, since you want substitutions to take place inside braces, but you can usually just run bind directly and avoid quoting hell by leveraging the list command:

bind $w <Motion> [list $w config -cursor crosshair]

Here, you also have the option of using the %W bind substitution, which is replaced with the window name. It works the same as %x and %y, which you already use.

You use "eval [bind . <Motion>\]" to execute the script associated with the <Motion> event. You can also use the [event generate command to do pretty much the same thing. Or you can use {*} instead of eval: "{*}[bind . <Motion>]". Also I suggest putting your bind scripts in procs to simplify the argument to bind, to make them easier to call, and to improve performance (this makes bytecode compilation possible). For example:

proc click {w x y} {
    global objectXoff objectYoff components
    set objectXoff $x
    set objectYoff $y
    set components(moveObject) $w
    event generate $w <Motion>
}
bind $w <ButtonPress-1> {click %w %x %y}

Try to avoid using <Motion> when you can just use <Enter>. But in this application, you shouldn't need bindings for setting the cursor anyway. Just set the cursor for the widget once, and the window system will automatically change the mouse pointer to match the cursor of the widget it's currently on.

Another question: what is expr doing? The only thing I can think of is that it forces the internal representation of %x and %y to be a number, but this is going to automatically happen anyway so there's no need to be explicit.

While I'm on the subject of expr, you really should brace your expr-essions in your <Motion> binding for the "." widget. This improves both performance and security.

SeS - 27 Mar 2010 Thanks for the feedback AMG, I think I can answer all your questions at once by simply saying that there is no particular reason for using any of the methods I decided to use, just stuff I learned from the past 4+ years and I am still learning... The thing is, there are so many ways in tcl/tk to solve a specific problem, I just have to make a choice, sometimes it is not the most logical nor up to usual (IT) standards. Don't expect that from an electronics expert anyway, I have to be pragmatic in most cases, if it works, I am usually happy. I see tG2 as a multi-stage development, the first stage is to create the program with a solid & sound architecture with the (limited) knowledge that I have at the moment, to prove the concept to myself and enjoy it's output both private and professional, later I hope to tune the script to a sharable version. So, your advises and that of other guru's are always appreciated and I will try to adapt my scripts to a way of programming the majority does, to make sure if I decide to share the code of tG2 one day (final stage), people will enjoy updating/improving it. Regards, SeS.


Fabricio Rocha - 14 Mar 2010 - Very interesting project, Lars.... Is there any way to contact you? I found no info in your page...

SeS - 2010-03-17 08:30:21

Fabriccio, I am sorry that I created a confusion here by omitting/forgetting my initials (SeS or SES_home). For some reason, Lars made an update or something and the page is written on his name, I think this is not on purpose, something he or myself did wrong during page creation? I do not want to reveal my real name yet to prevent any email communication at this moment. I am an electronics engineer working for a semicon company, so I have a daytime job, this project is a private project, so you do understand that I am kind of bizzy, that's the reason. Thank you though for your interest, please follow me on the progress by subscribing to the youtube account. As soon as I am confident I have a sharable version of tG2 I will let the world know.

Of course dont hesitate to ask me questions via this channel, as soon as I have time and check out these pages, I will try answer your questions. Regards, SeS.

Lars H: Indeed, I was just gnoming by (fixing spelling of category name). Content one wants to take credit for should carry some sort of signature.


SeS - 2010-03-17 09:09:58

Thanks Lars! Also, for the record:

This is the first page I created at wiki.tcl.tk, but I have more contributions by commenting to initiatives by other enthusiasts/developers:

Ctext

Drag and Drop

Simple Block Selection for Text Widget

And now I really have to go back to work...

Regards, SeS

SEH: tG2 looks very interesting. You should submit it as a Google Summer of Code project. You could mentor a student to make improvements to it all summer, while you get back to your day job!

SES: 28 Mar 2010 : Thanks SEH, I like your idea, but outsourcing the development of a program which is not documented and exists 60% in real code and 40% still in my mind as idea's, is a risky business. You end up supporting / directing the student, so maybe loose more time. Furthermore, I am also using the output of this private project for my job, it´s a perfect oppertunity to test it while using it actively. This kind of feedback is valuable if one wants to create a bugfree program to enhousiasts like you and I, and not risk a bad first impression by users due to undiscovered bugs. I am aware that time is ticking and I am risking release of tG2 in a time when the tcl/tk community is already advanced to tcl/tk v8.7 or maybe even higher...if it's worth it, I think the community will embrace, update and improve it anyway. Regards, SeS.


WJG (28/03/10) I think that your project is a good idea and I wish you every success. I started something similar a few years ago using the place widget command. I was thinking of making something similar to the old Hypercard that was shipped with Macs back in the 1990s! I followed the link to Youtube to see the demos, more good stuff.