1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.devaki.nextobjects.workspace.models.graphics;
16 import java.io.Serializable;
17 import java.awt.BorderLayout;
18 import java.awt.Dimension;
19 import java.awt.Graphics;
20 import java.awt.Graphics2D;
21 import java.awt.Point;
22 import java.awt.Rectangle;
23 import java.awt.image.BufferedImage;
24 import javax.swing.event.ChangeListener;
25 import javax.swing.event.ChangeEvent;
26 import javax.swing.JPanel;
27 import javax.swing.JScrollPane;
28 import org.devaki.nextobjects.constants.CstGraphics;
29 import org.devaki.nextobjects.util.ModelMan;
30 import org.devaki.nextobjects.workspace.models.BaseModel;
31 import org.devaki.nextobjects.workspace.models.objects.BaseObject;
32 import org.devaki.nextobjects.workspace.models.objects.BaseClass;
33 import org.devaki.nextobjects.workspace.models.objects.ModelTitle;
34 import java.awt.Image;
35 /***
36 * The base for all models
37 *
38 * @author <a href="mailto:eflorent@devaki.org">Emmanuel Florent</a>
39 * @created December 22, 2003
40 */
41 public abstract class BaseModelView extends JPanel implements Serializable
42 {
43 /*** X coordinates used when mouse clicking */
44 protected int x1;
45 /*** Y coordinates used when mouse clicking */
46 protected int y1;
47 /*** X coordinates used when mouse draging */
48 protected int x2;
49 /*** Y coordinates used when mouse draging */
50 protected int y2;
51 /*** X difference between x1 and object location */
52 protected int dx;
53 /*** Y difference between x1 and object location */
54 protected int dy;
55 /*** the model bounds */
56 protected Rectangle rectangle;
57 /*** the context model */
58 protected BaseModel myModel;
59 /*** the drawing area */
60 public JPanel drawingArea;
61 /*** the scrollpane */
62 public JScrollPane jScrollPane;
63 /*** the "cartouche" */
64 private ModelTitle modelTitle;
65 /*** full drawing refresh */
66 protected boolean fullRefresh = true;
67 /*** The buffered image */
68 protected transient BufferedImage bi = null;
69
70
71 /***
72 * constructor
73 *
74 * @param pModel the model
75 */
76 public BaseModelView(BaseModel pModel)
77 {
78 /*** Initialization * */
79 super(false);
80
81 myModel = pModel;
82 modelTitle = new ModelTitle(pModel);
83 pModel.getLabels().addElement(modelTitle.getObjectView());
84 this.setVisible(true);
85 /*** Components * */
86
87 this.setLayout(new BorderLayout());
88 /***
89 * There is an inner class. This class is responsible for all the
90 * executive drawing. The main is paint method. At call the visible
91 * area is cleared and a prepared BufferedImage is pasted at the top
92 * left corner. Optionally the very BufferedImage can be rebuilt or
93 * not. This image is constitued by a set of smaller image generated by
94 * org.devaki.nextobjects.workspace.models.graphics.* Managing the
95 * offset can became a hard job.
96 */
97
98 drawingArea =
99 new JPanel()
100 {
101 /***
102 * Draw all components
103 *
104 * @param g the graphics
105 */
106 public void paint(Graphics g)
107 {
108 update(g);
109 }
110
111
112 public Image makeImage(Rectangle pRect)
113 {
114 Graphics2D big;
115 BufferedImage bi2;
116 Graphics2D bi2g;
117 ObjectView[] tmp = getVisibleObjectView();
118
119
120 bi =
121 (BufferedImage) drawingArea.createImage(
122 pRect.width,
123 pRect.height);
124 big = bi.createGraphics();
125 big.setColor(CstGraphics.MODEL_BACKGROUND_COLOR);
126 big.fillRect(0, 0, pRect.width, pRect.height);
127 for (int k = 0; k < tmp.length; k++)
128 {
129
130 Dimension d = tmp[k].getSize();
131 Point l = tmp[k].getLocation();
132
133 if (tmp[k] instanceof ClassView)
134 {
135
136 if (d.height > 0 && d.width > 0)
137 {
138 bi2 =
139 (BufferedImage) drawingArea.createImage(
140 d.width,
141 d.height);
142 bi2g = bi2.createGraphics();
143 tmp[k].paint(bi2g);
144 big.drawImage(
145 bi2,
146 l.x - pRect.x,
147 l.y - pRect.y,
148 this);
149 }
150 }
151 else
152 {
153
154 tmp[k].paint(big);
155 }
156 }
157 return bi;
158 }
159
160
161 public void update(Graphics g)
162 {
163 Graphics2D g2 = (Graphics2D) g;
164
165
166 super.paintComponent(g2);
167
168
169 Rectangle rect = calculateRectangle();
170
171 if (fullRefresh)
172 {
173 bi = (BufferedImage) makeImage(rect);
174 fullRefresh = false;
175 }
176 g2.drawImage(bi, rect.x, rect.y, this);
177
178 for (int j = 0;
179 j < ModelMan.getCurrentObjects().size(); j++)
180 {
181 ((BaseObject) ModelMan.getCurrentObjects().elementAt(j))
182 .getObjectView()
183 .renderSelected(g);
184 }
185 }
186 };
187
188
189 this.drawingArea.setBackground(CstGraphics.MODEL_BACKGROUND_COLOR);
190 this.drawingArea.setPreferredSize(CstGraphics.MODEL_DIMENSION);
191
192
193
194 this.jScrollPane = new JScrollPane(this.drawingArea);
195 jScrollPane.getViewport().setBackground(
196 CstGraphics.MODEL_BACKGROUND_COLOR);
197 this.add(jScrollPane, BorderLayout.CENTER);
198
199
200 this.jScrollPane.getViewport().addChangeListener(
201 new ChangeListener()
202 {
203 public void stateChanged(ChangeEvent e)
204 {
205 calculateRectangle();
206 }
207 });
208
209 jScrollPane.getViewport().setViewPosition(
210 CstGraphics.MODEL_INITIAL_POSITION);
211 }
212
213
214 /***
215 * get the visible objects
216 *
217 * @return the object views
218 */
219 public abstract ObjectView[] getVisibleObjectView();
220
221
222 /***
223 * Return a cached rectangle/bounds for the model
224 *
225 * @return the rectangle
226 */
227 public Rectangle getRectangle()
228 {
229 if (rectangle == null)
230 {
231 calculateRectangle();
232 }
233
234 return rectangle;
235 }
236
237
238 /***
239 * Compute a location point for this viewport to have a centered view of
240 * the model
241 *
242 * @param actIt optiopnaly center the model
243 * @return the center
244 */
245 public Point center(boolean actIt)
246 {
247 calculateRectangle();
248
249 Rectangle r1 = this.getRectangle();
250 Rectangle r2 = jScrollPane.getViewport().getViewRect();
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 Point p =
270 new Point(
271 (r1.x + r1.x + r1.width) / 2 - (r2.width / 2),
272 (r1.y + r1.y + r1.height) / 2 - (r2.height / 2));
273
274 if (actIt)
275 {
276 jScrollPane.getViewport().setViewPosition(p);
277 }
278 return p;
279 }
280
281
282 /***
283 * Calculate a cached model rectangle
284 *
285 * @return Description of the Return Value
286 */
287 public Rectangle calculateRectangle()
288 {
289 int xmin = 10000000;
290 int ymin = 10000000;
291 int xmax = 0;
292 int ymax = 0;
293 int xtmpmin = 10000000;
294 int ytmpmin = 10000000;
295 int xtmpmax = 0;
296 int ytmpmax = 0;
297 int delta = 30;
298
299 for (int i = 0; i < myModel.getClasses().size(); i++)
300 {
301 BaseClass baseObject =
302 (BaseClass) myModel.getClasses().elementAt(i);
303
304 xtmpmin = (int) baseObject.getObjectView().getLocation().getX()
305 - delta;
306 ytmpmin = (int) baseObject.getObjectView().getLocation().getY()
307 - delta;
308 xtmpmax =
309 baseObject.getObjectView().getLocation().x
310 + baseObject.getObjectView().getSize().width + delta;
311 ytmpmax =
312 baseObject.getObjectView().getLocation().y
313 + baseObject.getObjectView().getSize().height + delta;
314 if (xtmpmin < xmin)
315 {
316 xmin = xtmpmin;
317 }
318 if (ytmpmin < ymin)
319 {
320 ymin = ytmpmin;
321 }
322 if (xtmpmax > xmax)
323 {
324 xmax = xtmpmax;
325 }
326 if (ytmpmax > ymax)
327 {
328 ymax = ytmpmax;
329 }
330 }
331 for (int i = 0; i < myModel.getLabels().size(); i++)
332 {
333 ObjectView baseObject =
334 (ObjectView) myModel.getLabels().elementAt(i);
335
336 xtmpmin = (int) baseObject.getLocation().getX();
337 ytmpmin = (int) baseObject.getLocation().getY();
338 xtmpmax = baseObject.getLocation().x + baseObject.getSize().width;
339 ytmpmax = baseObject.getLocation().y + baseObject.getSize().height;
340 if (xtmpmin < xmin)
341 {
342 xmin = xtmpmin;
343 }
344 if (ytmpmin < ymin)
345 {
346 ymin = ytmpmin;
347 }
348 if (xtmpmax > xmax)
349 {
350 xmax = xtmpmax;
351 }
352 if (ytmpmax > ymax)
353 {
354 ymax = ytmpmax;
355 }
356 }
357 rectangle = new Rectangle(xmin, ymin, xmax - xmin, ymax - ymin);
358 return rectangle;
359 }
360
361
362 /***
363 * get the model
364 *
365 * @return the model
366 */
367 public BaseModel getMyModel()
368 {
369 return myModel;
370 }
371
372
373 /***
374 * set the model
375 *
376 * @param model the model
377 */
378 public void setMyModel(BaseModel model)
379 {
380 myModel = model;
381 }
382
383
384 /***
385 * set the dimension
386 *
387 * @param d the dimension
388 */
389 public void setViewSize(Dimension d)
390 {
391 jScrollPane.getViewport().setViewSize(d);
392 }
393
394
395 /***
396 * return the view size
397 *
398 * @return the location
399 */
400 public Dimension getViewSize()
401 {
402 return jScrollPane.getViewport().getViewSize();
403 }
404
405
406 /***
407 * Set if to refresh the drawing at next paint
408 *
409 * @param b full refresh
410 */
411 public void setFullRefresh(boolean b)
412 {
413 fullRefresh = b;
414 }
415
416
417 /***
418 * Location of the view position
419 *
420 * @return the point
421 */
422 public Point getViewPosition()
423 {
424 return jScrollPane.getViewport().getViewPosition();
425 }
426
427
428 /***
429 * Set the view position
430 *
431 * @param p the top left corner to clip the drawings.
432 */
433 public void setViewPosition(Point p)
434 {
435 jScrollPane.getViewport().setViewPosition(p);
436 }
437
438
439 /***
440 * get the model title view
441 *
442 * @return the model "cartouche"
443 */
444 public ModelTitleView getModelTitleView()
445 {
446 return (ModelTitleView) modelTitle.getObjectView();
447 }
448 }
449