TODO item: proportional scaling



I was looking through the TODO file for dia and ran across the following:

* If you hold down shift while moving the handle of an 'Element',
  scale while keeping same proportions.

So, I thought I'd try my hand at it.  It only works for boxes right now, but
shouldn't be too difficult to make it work for the other basic objects.  Here's
the patch for v0.88.1 (I'm not working with the CVS version at this point.)

diff -pr dia-0.88.1/app/modify_tool.c dia-0.88.1.modified/app/modify_tool.c
*** dia-0.88.1/app/modify_tool.c        Sun Mar 25 20:05:16 2001
--- dia-0.88.1.modified/app/modify_tool.c       Wed May  1 15:59:39 2002
*************** modify_motion(ModifyTool *tool, GdkEvent
*** 280,285 ****
--- 280,286 ----
    Point now, delta, full_delta;
    gboolean auto_scroll, vertical = FALSE;
    ConnectionPoint *connectionpoint;
+   ModifierKeys modifier = MODIFIER_NONE;
  
    if (tool->state==STATE_NONE)
      return; /* Fast path... */
*************** modify_motion(ModifyTool *tool, GdkEvent
*** 383,390 ****
      }
  
      object_add_updates(tool->object, ddisp->diagram);
      tool->object->ops->move_handle(tool->object, tool->handle, &to,
!                                  HANDLE_MOVE_USER,0);
      object_add_updates(tool->object, ddisp->diagram);
    
      diagram_update_connections_selection(ddisp->diagram);
--- 384,392 ----
      }
  
      object_add_updates(tool->object, ddisp->diagram);
+     if (event->state & GDK_SHIFT_MASK) modifier = MODIFIER_SHIFT;
      tool->object->ops->move_handle(tool->object, tool->handle, &to,
!                                  HANDLE_MOVE_USER,modifier);
      object_add_updates(tool->object, ddisp->diagram);
    
      diagram_update_connections_selection(ddisp->diagram);
*************** modify_button_release(ModifyTool *tool, 
*** 433,438 ****
--- 435,441 ----
    GList *list;
    int i;
    Object *obj;
+   ModifierKeys modifier = MODIFIER_NONE;
    
    switch (tool->state) {
    case STATE_MOVE_OBJECT:
*************** modify_button_release(ModifyTool *tool, 
*** 473,481 ****
      
      /* Final move: */
      object_add_updates(tool->object, ddisp->diagram);
      tool->object->ops->move_handle(tool->object, tool->handle,
                                   &tool->last_to,
!                                  HANDLE_MOVE_USER_FINAL,0);
      object_add_updates(tool->object, ddisp->diagram);
  
      /* Connect if possible: */
--- 476,485 ----
      
      /* Final move: */
      object_add_updates(tool->object, ddisp->diagram);
+     if (event->state & GDK_SHIFT_MASK) modifier = MODIFIER_SHIFT;
      tool->object->ops->move_handle(tool->object, tool->handle,
                                   &tool->last_to,
!                                  HANDLE_MOVE_USER_FINAL,modifier);
      object_add_updates(tool->object, ddisp->diagram);
  
      /* Connect if possible: */
diff -pr dia-0.88.1/lib/element.c dia-0.88.1.modified/lib/element.c
*** dia-0.88.1/lib/element.c    Sun Mar 25 20:05:17 2001
--- dia-0.88.1.modified/lib/element.c   Wed May  1 16:04:20 2002
*************** element_move_handle(Element *elem, Handl
*** 150,155 ****
--- 150,159 ----
    default:
      message_error("Error, called element_move_handle() with wrong handle-id\n");
    }
+ 
+   if (elem->width != 0 && elem->height != 0) {
+     elem->aspectRatio = elem->width / elem->height;
+   }
  }
  
  void
*************** element_copy(Element *from, Element *to)
*** 280,285 ****
--- 284,290 ----
    to->corner = from->corner;
    to->width = from->width;
    to->height = from->height;
+   to->aspectRatio = from->aspectRatio;
    
    for (i=0;i<8;i++) {
      to->resize_handles[i] = from->resize_handles[i];
*************** void element_load(Element *elem, ObjectN
*** 330,333 ****
--- 335,343 ----
    if (attr != NULL)
      elem->height = data_real( attribute_first_data(attr));
  
+   if (elem->height != 0.0) {
+     elem->aspectRatio = elem->width / elem->height;
+   } else {
+     elem->aspectRatio = 0.0;
+   }
  }
diff -pr dia-0.88.1/lib/element.h dia-0.88.1.modified/lib/element.h
*** dia-0.88.1/lib/element.h    Fri Feb 23 09:45:43 2001
--- dia-0.88.1.modified/lib/element.h   Wed May  1 16:00:20 2002
*************** struct _Element {
*** 41,46 ****
--- 41,48 ----
    real width;
    real height;
  
+   real aspectRatio;
+ 
    ElementBBExtras extra_spacing;
  };
  
diff -pr dia-0.88.1/objects/standard/box.c dia-0.88.1.modified/objects/standard/box.c
*** dia-0.88.1/objects/standard/box.c   Mon Apr 30 20:56:01 2001
--- dia-0.88.1.modified/objects/standard/box.c  Wed May  1 16:05:54 2002
*************** box_move_handle(Box *box, Handle *handle
*** 308,314 ****
    assert(handle!=NULL);
    assert(to!=NULL);
  
!   element_move_handle(&box->element, handle->id, to, reason);
  
    box_update_data(box);
  }
--- 308,318 ----
    assert(handle!=NULL);
    assert(to!=NULL);
  
!   if (modifiers == MODIFIER_SHIFT) {
!     element_move_handle_aspect(&box->element, handle->id, to, (real) box->element.aspectRatio);
!   } else {
!     element_move_handle(&box->element, handle->id, to, reason);
!   }
  
    box_update_data(box);
  }
*************** box_create(Point *startpoint,
*** 511,516 ****
--- 515,521 ----
    elem->corner = *startpoint;
    elem->width = DEFAULT_WIDTH;
    elem->height = DEFAULT_WIDTH;
+   elem->aspectRatio = elem->width / elem->height;
  
    box->border_width =  attributes_get_default_linewidth();
    box->border_color = attributes_get_foreground();

I don't know that this is the best way to do this, but it does work.  The basic
idea is in addition to the width and height, keep a copy of the aspect ratio
of an element in the element object.  Then, when resizing, if the shift key is
pressed, call the element_move_handle_aspect function rather than
element_move_handle.  The element_move_handle function updates the aspect ratio
when it's finished while element_move_handle_aspect does not, since it should
be the same.  That's about it.  Just have to make sure that the aspect ratio
is calculated anytime the height or width changes.  The only real trouble comes
when the height or width is 0.  This is a little tricky and I used some ugly
hacks to make it work.  Oh, I have to keep track of the ratio in the element
(I guess you could keep it in the box, but then it can't be used in other
objects) because if an object ever gets a width or height of zero, you don't
want to recalculate the ratio.  Also, if you calculate the ratio everytime the
move_handle method gets called, if the width goes to zero, the aspect ratio
does as well, and then weird things start happening (I had what looked like
5 unconnected handles stuck to the side of the window.)
-- 
Titus Anderson 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]