1   package fi.jyu.mit.graphics;
2   
3   import java.awt.*;
4   import java.awt.event.ComponentAdapter;
5   import java.awt.event.ComponentEvent;
6   
7   
8   /**
9    * Ikkunoissa näytettävä paneeli johon kuviot piirretään
10   * @author Markus Kivioja
11   * @author Vesa Lappalainen
12   *
13   */
14  public class SpacePanel extends Component implements SpaceParent {
15  
16      private static final long serialVersionUID = 1L;
17      private Matrix sm;  // Perusskaalaus kuva ikkunaan
18      private Matrix a;   // Muunnokset taman paalle
19      private Matrix tm;  // Kokonaismuunnos  tm = sm * a; 
20      private Matrix rotator;
21      private boolean isotrophic;
22      private boolean allowRescale = true;
23      private Space space;
24      private RRect rRect = null;
25      private double left, right, top, bottom;
26      
27      /**
28       * Luo uuden paneelin jonka taustaväri on valkoinen
29       */
30      public SpacePanel() {
31          super();
32          initialize(); // NOPMD
33          setBackground(Color.WHITE);
34          // setOpaque(false);
35          setBackground(Color.WHITE);
36      }
37      
38      /**
39       * Alustaa paneelin asetuksen, kertoo näyttämälleen avaruudelle,
40       * että tämä paneeli näyttää sitä
41       */
42      private final void initialize() {
43          this.space = new Space();
44          this.space.registerWindow(this);
45          this.sm = new TMatrix();
46          this.a  = new TMatrix();
47          this.tm = new TMatrix();
48          this.rotator = new TMatrix();
49          // this.height = getHeight(); 
50          this.isotrophic = true;
51          addComponentListener(new ComponentAdapter() {
52              @SuppressWarnings("synthetic-access")
53              @Override
54              public void componentResized(ComponentEvent e) {
55                  if ( allowRescale ) reScale(); // NOPMD
56              }
57          });
58      }
59      
60      /**
61       * Skaalaa paneelin sisällän annettujen reuna-arvojen mukaisesti, 
62       * esimerkiksi:
63       * <pre>
64       *     panel.scale(-2.5, -2.2, 2.1, 2.7);
65       * </pre>
66       * @param left sisällän x-koordinaatin arvo paneelin vasemmassa reunassa
67       * @param bottom sisällän y-koordinaatin arvo paneelin alareunassa 
68       * @param right sisällän x-koordinaatin arvo paneelin oikeassa reunassa
69       * @param top sisällän y-koordinaatin arvo paneelin yläreunassa
70       */
71      public void scale(double left, double bottom, double right, double top) {
72          this.left = left;
73          this.bottom = bottom;
74          this.right = right;
75          this.top = top;
76          rRect = new RRect(left, top, right, bottom);
77          reScale();
78      }
79      
80      /**
81       * Skaalaa paneelin sisällän oikean kokoiseksi jos paneelin kokoa muutetaan
82       */
83      public final void reScale() {
84          if ( rRect == null ) return;
85          SRect sRect = new SRect(0, 0, getWidth(), getHeight());
86          this.sm = new TMatrix(rRect, sRect, isotrophic);
87          redraw();
88      }
89      
90      /**
91       * Pyrittää paneelin sisältää annetun akselin ympäri, esimerkiksi:
92       * <pre>
93       *     panel.rotate(Axis.X, 45.2);
94       * </pre>
95       * @param axis akseli jonka ympäri pyäritetään (Axis.X/Axis.Y/Axis.Z)
96       * @param deg pyäritettävän kulman suuruus asteina
97       */
98      public void rotate(int axis, double deg) {
99          transform(new RotMatrix(axis, deg));
100     }
101     
102     /**
103      * Liikuttaa paneelin sisältää, esimerkiksi:
104      * <pre>
105      *     panel.move(0, 1.5, -15);
106      * </pre>
107      * @param dx liikutettava matka x-akselin suunnassa
108      * @param dy liikutettava matka y-akselin suunnassa
109      * @param dz liikutettava matka z-akselin suunnassa
110      */
111     public void move(double dx, double dy, double dz) {
112         transform(new TranslateMatrix(dx,dy,dz));
113     }
114     
115     /**
116      * Skaalaa paneelin sisällän annettujen kertoimien mukaan
117      * <pre>
118      *      panel.scale(2, 1, 1); venyttää kuviot kaksinkertaiseksi x-suunnassa
119      * </pre>
120      * @param sx sisällän x-suuntainen kerroin
121      * @param sy sisällän y-suuntainen kerroin
122      * @param sz sisällän z-suuntainen kerroin
123      */
124     public void scale(double sx, double sy, double sz) {
125         this.left = this.left*sx;
126         this.right = this.right*sx;
127         this.bottom = this.bottom*sy;
128         this.top = this.top*sy;
129         transform(new ScaleMatrix(sx,sy,sz));
130     }
131     
132     /**
133      * @see fi.jyu.mit.graphics.Transformable#transform(fi.jyu.mit.graphics.Matrix)
134      */
135     @Override
136     public Transformable transform(Matrix m) {
137         if ( m == null ) return this;
138         this.a.multiplyThis(m);
139         redraw();
140         return this;
141     }
142     
143     /**
144      * Asetetaan kirtomatriisi
145      * @param m
146      */
147     public void setTransform(Matrix m) {
148         this.a = m;
149         redraw();
150     }
151     
152     /**
153      * @see fi.jyu.mit.graphics.Transformable#changeTransform(fi.jyu.mit.graphics.Matrix)
154      */
155     @Override
156     public void changeTransform(Matrix m) {
157         setTransform(m);
158     }
159     
160     /**
161      * @see fi.jyu.mit.graphics.Transformable#setRotator(fi.jyu.mit.graphics.Matrix)
162      */
163     @Override
164     public void setRotator(Matrix m) {
165         this.rotator = m;
166         redraw();
167     }
168     
169     /**
170      * @see fi.jyu.mit.graphics.Transformable#getRotator()
171      */
172     @Override
173     public Matrix getRotator() {
174         return this.rotator;
175     }
176     
177     /**
178      * Asettaa paneelin näyttämään annettua avaruutta
179      * @param space avaruus jota näytetään
180      */
181     public void setSpace(Space space) {
182         this.space = space;
183         this.space.registerWindow(this);
184     }
185     
186     /**
187      * Lisää paneeliin kuvion joka on Drawable-olio ja palauttaa sen,
188      * esimerkiksi:
189      * <pre>
190      *      panel.add(new Line(0, 0, 1, 1).setColor(255, 255, 0));
191      * </pre>
192      * @param shape lisättävä kuvio
193      * @return lisätty kuvio
194      */
195     public Drawable add(Drawable shape) {
196         return this.space.add(shape);
197     }
198     
199     /**
200      * Antaa Drawable-olion joka muodostuu kaikista 
201      * tämän paneelin näyttämistä kuvioista
202      * @return kokoelma tämän paneelin näyttämistä kuvioista
203      */
204     public Drawable getSavedPath() {
205         return this.space.getSavedPath();
206     }
207     
208     /**
209      * Poistaa paneelista kuvion joka on Drawable-olio
210      * @param shape poistettava kuvio
211      */
212     public void remove(Drawable shape) {
213         this.space.remove(shape);
214     }
215     
216     public void removeAll() {
217         this.space.removeAll();
218     }
219     
220     /**
221      * Piirtää paneelin sisällän uudelleen
222      */
223     @Override
224     public void redraw() {
225         repaint(1000L);
226     }
227     
228     /**
229      * Antaa paneelin kokonaismuunnosmatriisin
230      * @return paneelin kokonaismuunnosmatriisi
231      */
232     public Matrix getFullTransform() {
233         return tm;
234     }
235     
236     /**
237      * Piirtää paneelin sisällän omalla värillään ja muunnosmatriiseillaan
238      * @param g grafiikka johon piirretään
239      */
240     @Override
241     public void paint(Graphics g) {
242         g.setColor(getBackground());
243         g.fillRect(0,0,getWidth(),getHeight());
244         if ( space == null ) return;
245         sm.multiply(a,tm);
246         tm.multiplyThis(rotator);
247         this.space.draw(g, tm);
248     }
249     
250     /**
251      * Asettaa paneelin näkyväksi 
252      */
253     public void showWindow() {
254         this.setVisible(true);
255     }
256     
257     /**
258      * Asettaa isotrooppisuuden päälle/pois
259      * @param isotrophic isotrooppisuus tosi/epätosi
260      */
261     public void setIsotrophic(boolean isotrophic) {
262         this.isotrophic = isotrophic;
263     }
264     
265     /**
266      * Asettaa uudelleenskaalauksen kun paneelin kokoa muutetaan päälle/pois
267      * @param allowRescale uudelleenskaalaus tosi/epätosi
268      */
269     public void setAllowRescale(boolean allowRescale) {
270         this.allowRescale = allowRescale;
271         if ( allowRescale ) reScale();
272     }
273 
274     /**
275      * Antaa paneelin muunnosmatriisin
276      * @return paneelin muunnosmatriisi
277      */
278     @Override
279     public Matrix getTransform() {
280         return a;
281     }
282     
283     public double getLeft() {
284         return this.left;
285     }
286     
287     public double getRight() {
288         return this.right;
289     }
290     
291     public double getTop() {
292         return this.top;
293     }
294     
295     public double getBottom() {
296         return this.bottom;
297     }
298 }
299