gschem
|
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 }