1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #define GET_BOX_WIDTH(w) \
27 abs((w)->second_wx - (w)->first_wx)
28 #define GET_BOX_HEIGHT(w) \
29 abs((w)->second_wy - (w)->first_wy)
30 #define GET_BOX_LEFT(w) \
31 min((w)->first_wx, (w)->second_wx)
32 #define GET_BOX_TOP(w) \
33 max((w)->first_wy, (w)->second_wy)
35 /*! \todo Finish function documentation!!!
37 * \par Function Description
40 void o_box_invalidate_rubber (GschemToplevel
*w_current
)
42 g_return_if_fail (w_current
!= NULL
);
44 GschemPageView
*page_view
= gschem_toplevel_get_current_page_view (w_current
);
46 gschem_page_view_invalidate_world_rect (page_view
,
50 w_current
->second_wy
);
53 /*! \brief Start process to input a new box.
54 * \par Function Description
55 * This function starts the process to input a new box. Parameters for this
56 * box are put into/extracted from the <B>w_current</B> toplevel structure.
57 * <B>w_x</B> and <B>w_y</B> are current coordinates of the pointer in world
60 * The first step is to input one corner of the box. This corner is
61 * (<B>w_x</B>,<B>w_y</B>) snapped to the grid and saved in <B>w_current->first_wx</B>
62 * and <B>w_current->first_wy</B>.
64 * The other corner will be saved in (<B>w_current->second_wx</B>,
65 * <B>w_current->second_wy</B>).
67 * \param [in] w_current The GschemToplevel object.
68 * \param [in] w_x Current x coordinate of pointer in world.
69 * \param [in] w_y Current y coordinate of pointer in world.
71 void o_box_start(GschemToplevel
*w_current
, int w_x
, int w_y
)
73 i_action_start (w_current
);
75 /* init first_w[x|y], second_w[x|y] to describe box */
76 w_current
->first_wx
= w_current
->second_wx
= w_x
;
77 w_current
->first_wy
= w_current
->second_wy
= w_y
;
79 /* start to draw the box */
80 o_box_invalidate_rubber (w_current
);
83 /*! \brief End the input of a box.
84 * \par Function Description
85 * This function ends the input of the second corner of a box.
86 * The (<B>w_x</B>,<B>w_y</B>) point is set to be this second corner. The box is
87 * then defined by (<B>w_current->first_wx</B>,<B>w_current->first_wy</B> and
88 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>.
89 * <B>w_x</B> and <B>w_y</B> are in screen unit.
91 * The temporary box is erased ; a new box object is allocated, initialized
92 * and linked to the object list ; The object is finally drawn on the
95 * \param [in] w_current The GschemToplevel object.
96 * \param [in] w_x Current x coordinate of pointer in world units.
97 * \param [in] w_y Current y coordinate of pointer in world units.
99 void o_box_end(GschemToplevel
*w_current
, int w_x
, int w_y
)
103 GschemPageView
*page_view
= gschem_toplevel_get_current_page_view (w_current
);
104 g_return_if_fail (page_view
!= NULL
);
106 g_assert( w_current
->inside_action
!= 0 );
108 PAGE
*page
= gschem_page_view_get_page (page_view
);
109 g_return_if_fail (page
!= NULL
);
111 TOPLEVEL
*toplevel
= page
->toplevel
;
112 g_return_if_fail (toplevel
!= NULL
);
114 int box_width
, box_height
;
115 int box_left
, box_top
;
117 /* get the last coords of the pointer */
118 w_current
->second_wx
= w_x
;
119 w_current
->second_wy
= w_y
;
121 /* erase the temporary box */
122 /* o_box_invalidate_rubber (w_current); */
123 w_current
->rubber_visible
= 0;
125 box_width
= GET_BOX_WIDTH (w_current
);
126 box_height
= GET_BOX_HEIGHT(w_current
);
127 box_left
= GET_BOX_LEFT (w_current
);
128 box_top
= GET_BOX_TOP (w_current
);
130 /* boxes with null width or height are not allowed */
131 if ((box_width
== 0) || (box_height
== 0)) {
132 /* cancel the object creation */
133 w_current
->first_wx
= (-1);
134 w_current
->first_wy
= (-1);
135 w_current
->second_wx
= (-1);
136 w_current
->second_wy
= (-1);
140 /* create the object */
141 new_obj
= o_box_new (toplevel
, OBJ_BOX
, GRAPHIC_COLOR
,
143 box_left
+ box_width
, box_top
- box_height
);
144 s_page_append (toplevel
, page
, new_obj
);
147 printf("coords: %d %d %d %d\n", box_left
, box_top
, box_width
, box_height
);
150 w_current
->first_wx
= (-1);
151 w_current
->first_wy
= (-1);
152 w_current
->second_wx
= (-1);
153 w_current
->second_wy
= (-1);
155 /* Call add-objects-hook */
156 g_run_hook_object (w_current
, "%add-objects-hook", new_obj
);
158 gschem_toplevel_page_content_changed (w_current
, page
);
159 o_undo_savestate (w_current
, page
, UNDO_ALL
, _("Box"));
162 i_action_stop (w_current
);
165 /*! \brief Draw temporary box while dragging edge.
166 * \par Function Description
167 * This function is used to draw the box while dragging one of its edge or
168 * angle. It erases the previous temporary box drawn before, and draws a new
169 * updated one. <B>w_x</B> and <B>w_y</B> are the new position of the mobile point,
172 * The old values are inside the <B>w_current</B> pointed structure. Old width,
173 * height and left and top values are recomputed by the corresponding macros.
175 * \param [in] w_current The GschemToplevel object.
176 * \param [in] w_x Current x coordinate of pointer in world units.
177 * \param [in] w_y Current y coordinate of pointer in world units.
179 void o_box_motion (GschemToplevel
*w_current
, int w_x
, int w_y
)
182 g_assert( w_current
->inside_action
!= 0 );
184 /* erase the previous temporary box if it is visible */
185 if (w_current
->rubber_visible
)
186 o_box_invalidate_rubber (w_current
);
189 * New values are fixed according to the <B>w_x</B> and <B>w_y</B> parameters.
190 * These are saved in <B>w_current</B> pointed structure as new temporary
191 * values. The new box is then drawn.
194 /* update the coords of the corner */
195 w_current
->second_wx
= w_x
;
196 w_current
->second_wy
= w_y
;
198 /* draw the new temporary box */
199 o_box_invalidate_rubber (w_current
);
200 w_current
->rubber_visible
= 1;
203 /*! \brief Draw box from GschemToplevel object.
204 * \par Function Description
205 * This function draws the box from the variables in the GschemToplevel
206 * structure <B>*w_current</B>.
207 * One corner of the box is at (<B>w_current->first_wx</B>,
208 * <B>w_current->first_wy</B>) and the second corner is at
209 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>.
211 * \param [in] w_current The GschemToplevel object.
213 void o_box_draw_rubber (GschemToplevel
*w_current
, EdaRenderer
*renderer
)
216 cairo_t
*cr
= eda_renderer_get_cairo_context (renderer
);
217 GArray
*color_map
= eda_renderer_get_color_map (renderer
);
218 int flags
= eda_renderer_get_cairo_flags (renderer
);
220 eda_cairo_box (cr
, flags
, wwidth
, w_current
->first_wx
, w_current
->first_wy
,
221 w_current
->second_wx
, w_current
->second_wy
);
222 eda_cairo_set_source_color (cr
, SELECT_COLOR
, color_map
);
223 eda_cairo_stroke (cr
, flags
, TYPE_SOLID
, END_NONE
, wwidth
, -1, -1);