gschem

a_pan.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <math.h>
00024 
00025 #include "gschem.h"
00026 
00027 #ifdef HAVE_LIBDMALLOC
00028 #include <dmalloc.h>
00029 #endif
00030 
00031 
00037 void a_pan_general(GSCHEM_TOPLEVEL *w_current, double world_cx, double world_cy,
00038            double relativ_zoom_factor,int flags)
00039 {
00040   TOPLEVEL *toplevel = w_current->toplevel;
00041   /* see libgeda/include/defines.h for flags */
00042   /*if the borders should be ignored always, remove, outcomment or changes
00043     the flags in the function-calls*/
00044   /*    flags |= A_PAN_IGNORE_BORDERS;
00045    */       
00046   /* think it's better that the zoomfactor is defined as pix/mills
00047      this will be the same as w_current->page_current->to_screen_x/y_constant*/
00048   int zoom_max = 5; 
00049   int diff;
00050   double zx, zy, zoom_old, zoom_new, zoom_min;
00051 
00052 #if DEBUG
00053   printf("a_pan_general(): world_cx=%f, world_cy=%f\n",world_cx, world_cy);
00054 #endif  
00055 
00056   /* calc minimum zoomfactors and choose the smaller one. They are equal
00057      if the aspectratio of the world is the same as the screen ratio */
00058   zx = (double) toplevel->width / (toplevel->init_right -
00059                                     toplevel->init_left);
00060   zy = (double) toplevel->height / (toplevel->init_bottom -
00061                                      toplevel->init_top);
00062   zoom_min = zx < zy ? zx : zy;
00063 
00064 #if DEBUG
00065   printf("  zx_min=%f, zy_min=%f , flags=%d\n ",zx, zy, flags);
00066 #endif  
00067 
00068   /* to_screen_x_constant and to_screen_y_constant are almost the same.
00069      lets use to_screen_y_constant */
00070   zoom_old = toplevel->page_current->to_screen_y_constant;
00071         
00072   /* calc new zooming factor */
00073   /* check if there's a zoom_full (relativ_zoom_factor == -1) */
00074   if (relativ_zoom_factor <0)  {
00075     zoom_new = zoom_min;
00076   }
00077   else {
00078     zoom_new = zoom_old * relativ_zoom_factor;
00079     zoom_new = zoom_new > zoom_max ? zoom_max : zoom_new;
00080     if (!(flags & A_PAN_IGNORE_BORDERS)) {
00081       zoom_new = zoom_new < zoom_min ? zoom_min : zoom_new;
00082     }
00083   }
00084 
00085   /* calculate the new visible area; adding 0.5 to round */
00086   toplevel->page_current->left = world_cx - (double) toplevel->width
00087     / 2 / zoom_new + 0.5;
00088   toplevel->page_current->right = world_cx + (double) toplevel->width
00089     / 2 / zoom_new + 0.5;
00090   toplevel->page_current->top = world_cy - (double) toplevel->height
00091     / 2 / zoom_new + 0.5;
00092   toplevel->page_current->bottom = world_cy + (double) toplevel->height
00093     / 2 / zoom_new + 0.5;
00094     
00095   /* and put it back to the borders */
00096   if (!(flags & A_PAN_IGNORE_BORDERS)) {
00097     /* check right border */
00098     if (toplevel->page_current->right > toplevel->init_right) {
00099       toplevel->page_current->left += toplevel->init_right -
00100                                        toplevel->page_current->right;
00101       toplevel->page_current->right = toplevel->init_right;
00102     }
00103     /* check left border */
00104     if (toplevel->page_current->left < toplevel->init_left) {
00105       toplevel->page_current->right += toplevel->init_left -
00106                                         toplevel->page_current->left;
00107       toplevel->page_current->left = toplevel->init_left;
00108     }
00109 
00110     /* If there is any slack, center the view */
00111     diff = (toplevel->page_current->right -
00112             toplevel->page_current->left) -
00113            (toplevel->init_right - toplevel->init_left);
00114     if (diff > 0) {
00115       toplevel->page_current->left -= diff / 2;
00116       toplevel->page_current->right -= diff / 2;
00117     }
00118 
00119     /* check bottom border */
00120     if (toplevel->page_current->bottom > toplevel->init_bottom) {
00121       toplevel->page_current->top += toplevel->init_bottom -
00122                                       toplevel->page_current->bottom;
00123       toplevel->page_current->bottom = toplevel->init_bottom;
00124     }
00125     /* check top border */
00126     if (toplevel->page_current->top < toplevel->init_top) {
00127       toplevel->page_current->bottom += toplevel->init_top -
00128                                          toplevel->page_current->top;
00129       toplevel->page_current->top = toplevel->init_top;
00130     }
00131 
00132     /* If there is any slack, center the view */
00133     diff = (toplevel->page_current->bottom -
00134             toplevel->page_current->top) -
00135            (toplevel->init_bottom - toplevel->init_top);
00136     if (diff > 0) {
00137       toplevel->page_current->top -= diff / 2;
00138       toplevel->page_current->bottom -= diff / 2;
00139     }
00140 
00141   }
00142     
00143 #if DEBUG
00144   printf("zoom_old: %f, zoom_new: %f \n ",zoom_old, zoom_new);
00145   printf("left: %d, right: %d, top: %d, bottom: %d\n",
00146          toplevel->page_current->left, toplevel->page_current->right, 
00147      toplevel->page_current->top, toplevel->page_current->bottom);
00148   printf("aspect: %f\n",
00149          (float) fabs(toplevel->page_current->right  
00150               - toplevel->page_current->left) /
00151          (float) fabs(toplevel->page_current->bottom 
00152               - toplevel->page_current->top ));
00153 #endif
00154     
00155   /* set_window */
00156   set_window(toplevel, toplevel->page_current,
00157              toplevel->page_current->left  ,
00158              toplevel->page_current->right ,
00159              toplevel->page_current->top   ,
00160              toplevel->page_current->bottom);
00161 
00162   i_update_grid_info (w_current);
00163 
00164   /* redraw */
00165   if (!(flags & A_PAN_DONT_REDRAW)) {
00166     x_scrollbars_update(w_current);
00167     o_invalidate_all (w_current);
00168   }
00169 }
00170 
00175 void a_pan(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
00176 {
00177   /* make mouse to the new world-center;
00178      attention: there are information looses because of type cast in mil_x */
00179 
00180   a_pan_general(w_current, w_x, w_y, 1, 0);
00181 
00187   /* x_basic_warp_cursor(w_current->drawing_area, x, y); */
00188 }
00189 
00195 void a_pan_mouse(GSCHEM_TOPLEVEL *w_current, int diff_x, int diff_y)
00196 {
00197   TOPLEVEL *toplevel = w_current->toplevel;
00198   double world_cx, world_cy;
00199   double page_cx, page_cy;
00200 
00201 #if DEBUG
00202   printf("a_pan_mouse(): diff_x=%d, diff_y=%d\n", diff_x, diff_y);
00203 #endif  
00204 
00205   page_cx = (toplevel->page_current->left + toplevel->page_current->right) / 2.0;
00206   page_cy = (toplevel->page_current->top + toplevel->page_current->bottom) / 2.0;
00207 
00208   world_cx = page_cx - WORLDabs (w_current, diff_x);
00209   world_cy = page_cy + WORLDabs (w_current, diff_y);
00210 
00211 #if DEBUG
00212   printf("  world_cx=%f, world_cy=%f\n",
00213      world_cx, world_cy);
00214 #endif
00215   
00216   a_pan_general(w_current, world_cx, world_cy, 1, 0);
00217 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines