Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

snap to grid ?

Status
Not open for further replies.

zskater

Programmer
Apr 14, 2001
22
GB
I am designing a drawing package for my uni project
At the moment i have a scrollable canvas with a grid on it
I have buttons that when pressed i can drop a rectangular object on to the canvas
where my cursor is

What i would now like to do is include some code to get the rectangles to line up next to each other
easily, when i move them around they have to much freedom and it is really hard to line
the edges up
I think what i need is some snap to grid type function but i cant find any example code
anywhere

Can anyone help ?

Cheers Steve
 
There is no "snap-to-grid" feature built into the Canvas widget, sorry to say. That would be a useful feature in many applications. However, it's not too difficult to implement.

In one of my classes, we already have a series of examples showing how to create a simple rectangles drawing program. I just took the last one in that series and added a snap-to-grid feature, both for drawing rectangles and for moving them around the canvas.

To use this application, Click-Drag-Release with the left mouse button to create a rectangle. Hold down the Control key and Click-Drag-Release to move an existing rectangle.

You might be particularly interested in the rect_move_end procedure, which queries the current coordinates of a rectangle, and then adjusts them so that the upper-lefthand corner is on the nearest grid point.

My apologies for the formatting of this example code. The line lengths are longer than those supported by Tek-Tips, and I don't feel like going through the entire program trying to do good line wraps.

Code:
# ----------------------------------------------------------------------
#  FILE: rect5.tcl
#  DESCRIPTION: Implementing a "snap to grid" feature."
# ======================================================================
#              Copyright (c) 2001-2 Kenneth Jones
# ======================================================================

canvas .pic
pack .pic

bind .pic <ButtonPress-1>   {rect_create_start %W %x %y}
bind .pic <B1-Motion>       {rect_create_drag %W %x %y}
bind .pic <ButtonRelease-1> {rect_create_end %W %x %y}

# The size of the grid divisions

set GRIDSIZE 20

# Note that the space is required in the following binding actions.
# If the action looks like a NULL string, the bind command removes
# any existing binding for the specified event.

bind .pic <Control-ButtonPress-1>   { }
bind .pic <Control-B1-Motion>       { }
bind .pic <Control-ButtonRelease-1> { }

proc rect_create_start {canv x y} {
    global GRIDSIZE
    global rect

    # Start drawing rectangle on the nearest grid point
    
    set rect(x0) [expr {round($x/$GRIDSIZE)*$GRIDSIZE}]
    set rect(y0) [expr {round($y/$GRIDSIZE)*$GRIDSIZE}]

    set rect(id) [$canv create rect $rect(x0) $rect(y0) $rect(x0) $rect(y0)]

    $canv bind $rect(id) <Control-ButtonPress-1>         [list rect_move_start $canv $rect(id) %x %y]

    $canv bind $rect(id) <Control-B1-Motion>         [list rect_move_drag $canv $rect(id) %x %y]

    $canv bind $rect(id) <Control-ButtonRelease-1>         [list rect_move_end $canv $rect(id) %x %y]
}

proc rect_create_drag {canv x y} {
    global rect
    $canv coords $rect(id) $rect(x0) $rect(y0) $x $y
}

proc rect_create_end {canv x y} {
    global GRIDSIZE
    global rect

    # Make final vertex on the nearest grid point

    set x [expr {round($x/$GRIDSIZE)*$GRIDSIZE}]
    set y [expr {round($y/$GRIDSIZE)*$GRIDSIZE}]
    rect_create_drag $canv $x $y
    $canv itemconfigure $rect(id) -fill blue
}

proc rect_move_start {canv id x y} {
    global rect
    set rect(xs) $x
    set rect(ys) $y
    $canv raise $id
    $canv itemconfigure $id -stipple gray50
}

proc rect_move_drag {canv id x y} {
    global rect
    $canv move $id [expr {$x-$rect(xs)}] [expr {$y-$rect(ys)}]
    set rect(xs) $x
    set rect(ys) $y
}

proc rect_move_end {canv id x y} {
    global GRIDSIZE
    rect_move_drag $canv $id $x $y

    # Get the final coordinates of the rectangle

    foreach {x0 y0 x1 y1} [$canv coords $id] {break}

    # Put the upper-lefthand corner on the nearest grid point

    $canv move $id         [expr {(round($x0/$GRIDSIZE)*$GRIDSIZE)-$x0}]         [expr {(round($y0/$GRIDSIZE)*$GRIDSIZE)-$y0}]

    $canv itemconfigure $id -stipple &quot;&quot;
}
- Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Once again thanks very much for your help, away to try some stuff out with my program.
Its been difficult learning tcl on my own in one month and designing this for my university team project,tcl is deffinetly something I want to continue with, does your company work in the UK or just the US ?

CHEERS STEVE
 
Well, Avia's offices are in San Francisco, California. But I'm quite willing to travel wherever the work is. If a client in the UK wanted training or to have me work on a project, I'd be happy to come on over. I'm always looking to add to my frequent flyer account... :) - Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top