View Javadoc

1   /*
2    *   Firemox is a turn based strategy simulator
3    *   Copyright (C) 2003-2007 Fabrice Daugan
4    *
5    *   This program is free software; you can redistribute it and/or modify it 
6    * under the terms of the GNU General Public License as published by the Free 
7    * Software Foundation; either version 2 of the License, or (at your option) any
8    * later version.
9    *
10   *   This program is distributed in the hope that it will be useful, but WITHOUT 
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
13   * details.
14   *
15   *   You should have received a copy of the GNU General Public License along  
16   * with this program; if not, write to the Free Software Foundation, Inc., 
17   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  package net.sf.firemox.zone;
20  
21  import java.awt.Color;
22  import java.awt.Component;
23  import java.awt.Container;
24  import java.awt.FlowLayout;
25  import java.awt.Graphics;
26  import java.awt.Image;
27  import java.awt.LayoutManager;
28  import java.awt.Point;
29  import java.awt.event.MouseEvent;
30  import java.awt.event.MouseListener;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.OutputStream;
34  import java.net.MalformedURLException;
35  import java.util.Arrays;
36  import java.util.Collections;
37  import java.util.List;
38  
39  import javax.swing.JComponent;
40  import javax.swing.JPanel;
41  import javax.swing.JScrollPane;
42  
43  import net.sf.firemox.clickable.Clickable;
44  import net.sf.firemox.clickable.ability.Ability;
45  import net.sf.firemox.clickable.target.Target;
46  import net.sf.firemox.clickable.target.card.AbstractCard;
47  import net.sf.firemox.clickable.target.card.MCard;
48  import net.sf.firemox.clickable.target.player.Player;
49  import net.sf.firemox.stack.StackManager;
50  import net.sf.firemox.test.Test;
51  import net.sf.firemox.token.IdPositions;
52  import net.sf.firemox.token.Visibility;
53  import net.sf.firemox.token.VisibilityChange;
54  import net.sf.firemox.token.Visible;
55  import net.sf.firemox.tools.Configuration;
56  import net.sf.firemox.tools.Log;
57  import net.sf.firemox.tools.MToolKit;
58  import net.sf.firemox.tools.Pair;
59  import net.sf.firemox.tools.Picture;
60  import net.sf.firemox.ui.component.TableTop;
61  import net.sf.firemox.ui.i18n.LanguageManagerMDB;
62  import net.sf.firemox.ui.layout.FlowLayout2;
63  import net.sf.firemox.ui.layout.WallpaperTypes;
64  
65  /***
66   * A zone is a cards container.
67   * 
68   * @author Fabrice Daugan
69   * @since 0.2c
70   * @since 0.3 feature "reverseImage" implemented
71   * @since 0.4 you can now change wallpaper/color of this MZone and setting
72   * @since 0.52 "enableReverse" option are saved.
73   * @since 0.71 visibility of cards can be set. Cards come into this zone
74   *        returned or not immediately
75   */
76  public abstract class MZone extends JPanel implements MouseListener, Visible {
77  
78  	/***
79  	 * create an instance of MZone
80  	 * 
81  	 * @param idZone
82  	 *          id place of this panel
83  	 * @param layout
84  	 *          is it's layout
85  	 * @param superPanel
86  	 *          scroll panel containing this panel
87  	 * @param reverseImage
88  	 *          if true the back picture will be reversed
89  	 * @param name
90  	 *          the untranslated zone name
91  	 * @see net.sf.firemox.token.IdZones
92  	 */
93  	protected MZone(int idZone, LayoutManager layout, JScrollPane superPanel,
94  			boolean reverseImage, String name) {
95  		super(layout);
96  		setName(name);
97  
98  		this.superPanel = superPanel;
99  		this.reverseImage = reverseImage;
100 		this.idZone = idZone;
101 
102 		// A L&F bug requires this UI initialization to be done here
103 		if (superPanel != null) {
104 			superPanel.setBorder(null);
105 		}
106 	}
107 
108 	/***
109 	 * Initialize UI
110 	 */
111 	public void initUI() {
112 		final String getter = "zones." + getZoneName() + "."
113 				+ (reverseImage ? "up" : "down");
114 		this.doMosaic = Configuration.getBoolean(getter + ".mosaic", true);
115 
116 		if (superPanel != null) {
117 			superPanel.setViewportView(this);
118 			MToolKit.addOverlay(superPanel);
119 		}
120 
121 		setBorder(null);
122 		setAutoscrolls(true);
123 		setWallPaperFile(Configuration.getString(getter + ".wallpaper", ""));
124 		setBackground(new Color(Configuration.getInt(getter + ".background", 0)));
125 		addMouseListener(this);
126 	}
127 
128 	@Override
129 	public void paintComponent(Graphics g) {
130 		if (getImage() != null) {
131 			int width = getWidth();
132 			int height = getHeight();
133 			if (doMosaic && ZoneManager.bgDelegate != null) {
134 
135 				// Delegate the painting to the L&F painter ignoring the reverse options
136 				super.paintComponent(g);
137 			} else {
138 				if (reverseImage
139 						&& (Configuration.getBoolean("reverseSide", false) || Configuration
140 								.getBoolean("reverseArt", true))) {
141 					if (doMosaic) {
142 						for (int y = height / picHeight + 1; y-- > 0;) {
143 							for (int x = width / picWidth + 1; x-- > 0;) {
144 								g.drawImage(getImage(), x * picWidth + picWidth, y * picHeight
145 										+ picHeight, x * picWidth, y * picHeight, 0, 0,
146 										picWidth - 1, picHeight - 1, null);
147 							}
148 						}
149 					} else {
150 						g.drawImage(getImage(), width, height, 0, 0, 0, 0, picWidth,
151 								picHeight, null);
152 					}
153 				} else {
154 					if (doMosaic) {
155 						for (int y = height / picHeight + 1; y-- > 0;) {
156 							for (int x = width / picWidth + 1; x-- > 0;) {
157 								g.drawImage(getImage(), x * picWidth, y * picHeight, picWidth,
158 										picHeight, null);
159 							}
160 						}
161 					} else {
162 						g.drawImage(getImage(), 0, 0, width, height, null);
163 					}
164 				}
165 			}
166 		} else if (ZoneManager.bgDelegate != null) {
167 
168 			// Delegate the painting to the L&F painter ignoring the reverse options
169 			super.paintComponent(g);
170 		}
171 	}
172 
173 	/***
174 	 * return the card at index
175 	 * 
176 	 * @param index
177 	 *          is the index where is the element
178 	 * @return the card at the specified index
179 	 */
180 	public final MCard getCard(int index) {
181 		return (MCard) getComponent(index);
182 	}
183 
184 	/***
185 	 * return the last card (top)
186 	 * 
187 	 * @return the last card
188 	 */
189 	public MCard getTop() {
190 		return getCard(0);
191 	}
192 
193 	/***
194 	 * return the first card (bottom)
195 	 * 
196 	 * @return the first card
197 	 */
198 	public MCard getBottom() {
199 		return getCard(getComponentCount() - 1);
200 	}
201 
202 	/***
203 	 * Adds the specified card to this zone with the specified constraints at the
204 	 * specified index. Also notifies the layout manager to add the component to
205 	 * the this container's layout using the specified constraints object.
206 	 * 
207 	 * @param card
208 	 *          the card to be added
209 	 * @param constraints
210 	 *          an object expressing layout constraints for this
211 	 * @param position
212 	 *          the position in the container's list at which to insert the
213 	 *          component; <code>-1</code> means insert at the end card
214 	 * @see LayoutManager
215 	 */
216 	protected void add(MCard card, Object constraints, int position) {
217 		card.updateZoneVisibility(visibility);
218 		card.getMUI().isAutoAlign = true;
219 		if (position == -1) {
220 			super.add(card, constraints);
221 		} else {
222 			super.add(card, constraints, position);
223 		}
224 		updatePanel();
225 	}
226 
227 	/***
228 	 * Indicates whether this card suits to the specified position code.
229 	 * 
230 	 * @param card
231 	 *          is the card to locate.
232 	 * @param position
233 	 *          the matching position code
234 	 * @return true if this card suits to the specified position code.
235 	 * @see net.sf.firemox.token.IdPositions#ON_THE_BOTTOM
236 	 * @see net.sf.firemox.token.IdPositions#ON_THE_TOP
237 	 */
238 	public final boolean isSamePosition(MCard card, int position) {
239 		if (getCardCount() == 0) {
240 			return false;
241 		}
242 		if (position == IdPositions.ON_THE_BOTTOM) {
243 			return getBottom() == card;
244 		}
245 		return getCardCount() > position && getCard(position) == card;
246 	}
247 
248 	/***
249 	 * Return the index of the specified card within this zone
250 	 * 
251 	 * @param card
252 	 *          the card to search
253 	 * @return the found index
254 	 */
255 	public Pair<Integer, Integer> getRealIndexOf(MCard card) {
256 		int index = super.getComponentZOrder(card);
257 		if (index != -1) {
258 			return new Pair<Integer, Integer>(index, 0);
259 		}
260 		// the card is not directly in play but maybe attached
261 		final Component[] components = getComponents();
262 		for (index = components.length; index-- > 0;) {
263 			final Component component = components[index];
264 			if (component instanceof Container) {
265 				final int subIndex = ((Container) component).getComponentZOrder(card);
266 				if (subIndex != -1) {
267 					return new Pair<Integer, Integer>(index, subIndex);
268 				}
269 			}
270 		}
271 		throw new InternalError("" + card + " has not been found in " + this);
272 	}
273 
274 	/***
275 	 * return the backImage to display in this JPanel
276 	 * 
277 	 * @return the backImage to display in this JPanel
278 	 */
279 	private Image getImage() {
280 		return backImage;
281 	}
282 
283 	/***
284 	 * return the translated name of this zone
285 	 * 
286 	 * @return the name of this panel
287 	 */
288 	@Override
289 	public String toString() {
290 		return LanguageManagerMDB.getString("zone." + getZoneName());
291 	}
292 
293 	/***
294 	 * This function returns the result of Component#getName() This will return
295 	 * the untranslated name of this zone. The toString()method returns the
296 	 * translated name of this zone
297 	 * 
298 	 * @return the result of Component#getName()
299 	 * @see #toString()
300 	 */
301 	public String getZoneName() {
302 		return getName();
303 	}
304 
305 	/***
306 	 * return the wallpaper file, return null if current panel is not in wallpaper
307 	 * mode.
308 	 * 
309 	 * @return current wallpaper file
310 	 */
311 	String getWallPaperFile() {
312 		String getter = "zones." + getZoneName() + "."
313 				+ (reverseImage ? "up" : "down");
314 		return Configuration.getString(getter + ".wallpaper", "");
315 	}
316 
317 	/***
318 	 * set the new wallpaper to the picture from a specified file. The current
319 	 * display mode of this panel will be now as "wallpaper"
320 	 * 
321 	 * @param newFile
322 	 *          the new wallpaper. If null or null sized, wallpaper is disabled
323 	 */
324 	final void setWallPaperFile(String newFile) {
325 		String getter = "zones." + getZoneName() + "."
326 				+ (reverseImage ? "up" : "down");
327 		if (newFile != null && newFile.length() > 0) {
328 			try {
329 				final Image backImage = Picture.loadImage(newFile);
330 				picWidth = backImage.getWidth(this);
331 				picHeight = backImage.getHeight(this);
332 				this.backImage = backImage;
333 				Configuration.setProperty(getter + ".wallpaper", newFile);
334 			} catch (MalformedURLException e) {
335 				// IGNORING
336 			}
337 		} else {
338 			Configuration.setProperty(getter + ".wallpaper", "");
339 			backImage = null;
340 		}
341 	}
342 
343 	/***
344 	 * Set the new wallpaper for the current game.
345 	 * 
346 	 * @param inputStream
347 	 *          the input Stream containing the wallpaper configuration.
348 	 * @throws IOException
349 	 *           If some other I/O error occurs
350 	 */
351 	public void readWallPaperConfiguration(InputStream inputStream)
352 			throws IOException {
353 		WallpaperTypes type = WallpaperTypes.values()[inputStream.read()];
354 		switch (type) {
355 		case color:
356 			backImage = null;
357 			setBackground(new Color(MToolKit.readInt24(inputStream)));
358 			break;
359 		case watermark:
360 			// ignore water mark of opponent
361 			break;
362 		case picture:
363 			doMosaic = false;
364 			backImage = MToolKit.readImage(inputStream);
365 			picWidth = backImage.getWidth(this);
366 			picHeight = backImage.getHeight(this);
367 			break;
368 		case mosaicPicture:
369 		default:
370 			doMosaic = true;
371 			backImage = MToolKit.readImage(inputStream);
372 			picWidth = backImage.getWidth(this);
373 			picHeight = backImage.getHeight(this);
374 			break;
375 		}
376 	}
377 
378 	/***
379 	 * Send the wallpaper configuration over the given output stream.
380 	 * 
381 	 * @param out
382 	 *          the output Stream containing the wallpaper configuration.
383 	 * @throws IOException
384 	 *           If some other I/O error occurs
385 	 */
386 	public void writeWallPaperConfiguration(OutputStream out) throws IOException {
387 		if (ZoneManager.bgDelegate != null) {
388 			out.write(WallpaperTypes.watermark.ordinal());
389 		} else if (backImage != null) {
390 			if (doMosaic) {
391 				out.write(WallpaperTypes.mosaicPicture.ordinal());
392 			} else {
393 				out.write(WallpaperTypes.picture.ordinal());
394 			}
395 
396 			// Send the picture data
397 			MToolKit.writeFile(MToolKit.getFile(getWallPaperFile()), out);
398 		} else {
399 			out.write(WallpaperTypes.color.ordinal());
400 			MToolKit.writeInt24(out, getBackground().getRGB());
401 		}
402 	}
403 
404 	@Override
405 	public void removeAll() {
406 		super.removeAll();
407 		updatePanel();
408 	}
409 
410 	/***
411 	 * update this panel in function of it's components
412 	 */
413 	public void updatePanel() {
414 		// invalidate();
415 		doLayout();
416 		repaint();
417 	}
418 
419 	/***
420 	 * Shuffle the zone
421 	 */
422 	public void shuffle() {
423 		final List<Component> components = Arrays.asList(getComponents());
424 		Collections.shuffle(components, MToolKit.random);
425 		removeAll();
426 		for (Component component : components) {
427 			add(component);
428 		}
429 		updatePanel();
430 	}
431 
432 	public void mouseReleased(MouseEvent e) {
433 		mousePressed(e);
434 	}
435 
436 	public void mouseClicked(MouseEvent e) {
437 		if (e.getClickCount() > 1) {
438 			for (Component component : getComponents()) {
439 				((AbstractCard) component).getMUI().isAutoAlign = true;
440 			}
441 			doLayout();
442 		}
443 	}
444 
445 	public void mouseEntered(MouseEvent e) {
446 		// Ignore this event
447 	}
448 
449 	// Ignore this event
450 	public void mouseExited(MouseEvent e) {
451 		// Ignore this event
452 	}
453 
454 	/***
455 	 * Update the "reversed" state of this component.
456 	 */
457 	public void updateReversed() {
458 		// Ignore this event
459 	}
460 
461 	/***
462 	 * Update the layout of this panel depending on the owner.
463 	 * 
464 	 * @param panel
465 	 *          the panel to update
466 	 * @param reverse
467 	 *          is this zone is reversed.
468 	 */
469 	protected static void updateLayouts(JComponent panel, boolean reverse) {
470 		if (reverse) {
471 			panel.setLayout(new FlowLayout2());
472 		} else {
473 			panel.setLayout(new FlowLayout(FlowLayout.LEFT));
474 		}
475 	}
476 
477 	/***
478 	 * is called when you click on me
479 	 * 
480 	 * @param e
481 	 *          is the mouse event
482 	 */
483 	public void mousePressed(MouseEvent e) {
484 		PopupManager.instance.mousePressed(e, this);
485 	}
486 
487 	/***
488 	 * Save wallpaper name, display options and back colors of this panel to a
489 	 * specified output stream
490 	 */
491 	void saveSettings() {
492 		String setter = "zones." + getZoneName() + "."
493 				+ (reverseImage ? "up" : "down");
494 		Configuration.setProperty(setter + ".mosaic", doMosaic);
495 		Configuration.setProperty(setter + ".background", getBackground().getRGB());
496 	}
497 
498 	/***
499 	 * Add a card to this panel. If tag 'returnedCards' is true, this card comes
500 	 * returned into this zone.
501 	 * 
502 	 * @param card
503 	 *          the card to add to this zone.
504 	 */
505 	public void remove(AbstractCard card) {
506 		super.remove(card);
507 		updatePanel();
508 	}
509 
510 	/***
511 	 * return the number of cards in this panel
512 	 * 
513 	 * @return the number of cards in this panel
514 	 */
515 	public int getCardCount() {
516 		return getComponentCount();
517 	}
518 
519 	/***
520 	 * Checks all cards corresponding to the specified constraints including
521 	 * attached cards.
522 	 * 
523 	 * @param test
524 	 *          applied to count valid cards
525 	 * @param ability
526 	 *          is the ability owning this test. The card component of this
527 	 *          ability should correspond to the card owning this test too.
528 	 * @return amount of card matching with the specified test
529 	 */
530 	public int countAllCardsOf(Test test, Ability ability) {
531 		int result = 0;
532 		for (Component component : getComponents()) {
533 			result += ((AbstractCard) component).countAllCardsOf(test, ability, true);
534 		}
535 		return result;
536 	}
537 
538 	/***
539 	 * Checks all cards corresponding to the specified constraints including
540 	 * attached cards.
541 	 * 
542 	 * @param test
543 	 *          applied to count valid cards
544 	 * @param ability
545 	 *          is the ability owning this test. The card component of this
546 	 *          ability should correspond to the card owning this test too.
547 	 * @param limit
548 	 *          is the desired count.
549 	 * @param canBePreempted
550 	 *          <code>true</code> if the valid targets can be determined before
551 	 *          runtime.
552 	 * @return amount of cards matching with the specified test. Highest value is
553 	 *         <code>limit</code>.
554 	 */
555 	public int countAllCardsOf(Test test, Ability ability, int limit,
556 			boolean canBePreempted) {
557 		int result = 0;
558 		int index = getCardCount();
559 		while (index-- > 0 && result < limit) {
560 			result += ((AbstractCard) getComponent(index)).countAllCardsOf(test,
561 					ability, canBePreempted);
562 		}
563 		return result;
564 	}
565 
566 	/***
567 	 * Checks all cards corresponding to this constraints
568 	 * 
569 	 * @param test
570 	 *          applied to count valid cards
571 	 * @param list
572 	 *          the list containing the founded cards
573 	 * @param ability
574 	 *          is the ability owning this test. The card component of this
575 	 *          ability should correspond to the card owning this test too.
576 	 */
577 	public void checkAllCardsOf(Test test, List<Target> list, Ability ability) {
578 		for (Component component : getComponents()) {
579 			((AbstractCard) component).checkAllCardsOf(test, list, ability);
580 		}
581 	}
582 
583 	/***
584 	 * Disable all cards of this zone manager
585 	 */
586 	public void disHighLightAll() {
587 		for (Component component : getComponents()) {
588 			if (component instanceof Clickable) {
589 				((Clickable) component).disHighLight();
590 			}
591 		}
592 		disHighLight();
593 	}
594 
595 	/***
596 	 * Disable only this component, not the components of this zone.
597 	 */
598 	public void disHighLight() {
599 		// reset the tabbed panel background of this panel
600 		int id = TableTop.getInstance().tabbedPane.indexOfComponent(superPanel);
601 		if (id == -1) {
602 			Log.debug("error");
603 			throw new InternalError("index=-1; zone=" + this);
604 		} else if (TableTop.getInstance().tabbedPane.getBackgroundAt(id) != null) {
605 			TableTop.getInstance().tabbedPane.setBackgroundAt(id, null);
606 		}
607 	}
608 
609 	/***
610 	 * Highlight only this component, not the components of this zone. Use instead
611 	 * the specific highlight color of the desired zone.
612 	 * 
613 	 * @param color
614 	 *          the color of highlight.
615 	 */
616 	public void highLight(Color color) {
617 		TableTop.getInstance().tabbedPane.setSelectedComponent(superPanel);
618 		TableTop.getInstance().tabbedPane.setBackgroundAt(
619 				TableTop.getInstance().tabbedPane.indexOfComponent(superPanel), color);
620 	}
621 
622 	/***
623 	 * Remove all cards of this zone
624 	 */
625 	public void reset() {
626 		removeAll();
627 		visibility = Visibility.HIDDEN;
628 	}
629 
630 	public void setVisibility(Visibility visibility) {
631 		if (this.visibility != visibility) {
632 			this.visibility = visibility;
633 			// update the cards
634 			for (Component component : getComponents()) {
635 				if (component instanceof MCard) {
636 					((MCard) component).setVisibility(visibility);
637 				}
638 			}
639 			repaint();
640 		}
641 	}
642 
643 	/***
644 	 * Add a card at the bottom of this panel. If tag 'returnedCards' is true,
645 	 * this card comes returned into this zone.
646 	 * 
647 	 * @param card
648 	 *          the card to add to this zone.
649 	 */
650 	public void addBottom(MCard card) {
651 		add(card, -1);
652 	}
653 
654 	/***
655 	 * Add a card at the top of this panel. If tag 'returnedCards' is true, this
656 	 * card comes returned into this zone. Be careful, you can use this function
657 	 * only if the specified component is not yet in this container.
658 	 * 
659 	 * @param card
660 	 *          the card to add to this zone.
661 	 */
662 	public void addTop(MCard card) {
663 		add(card, 0);
664 	}
665 
666 	/***
667 	 * Add a card to this panel. If tag 'returnedCards' is true, this card comes
668 	 * returned into this zone.
669 	 * 
670 	 * @param card
671 	 *          the card to add to this zone.
672 	 * @param position
673 	 *          the position index of insertion.
674 	 */
675 	public void add(MCard card, int position) {
676 		add(card, null, position);
677 	}
678 
679 	/***
680 	 * Return player identifier of controller of this zone.
681 	 * 
682 	 * @return player identifier of controller of this zone.
683 	 */
684 	public int getControllerIdPlayer() {
685 		return reverseImage ? 1 : 0;
686 	}
687 
688 	/***
689 	 * Return controller of this zone.
690 	 * 
691 	 * @return controller of this zone.
692 	 */
693 	public Player getController() {
694 		return StackManager.PLAYERS[getControllerIdPlayer()];
695 	}
696 
697 	/***
698 	 * Return the zone identifier
699 	 * 
700 	 * @return the zone identifier
701 	 */
702 	public final int getZoneId() {
703 		return idZone;
704 	}
705 
706 	/***
707 	 * Start the drag and drop management for the given card.
708 	 * 
709 	 * @param card
710 	 *          The drag and drop component.
711 	 * @param mousePoint
712 	 *          The drag and drop starting point.
713 	 * @return <code>true</code> if the drag and drop is managed by this zone.
714 	 */
715 	public boolean startDragAndDrop(MCard card, Point mousePoint) {
716 		dragAndDropComponent = card;
717 		this.mousePoint = mousePoint;
718 		return true;
719 	}
720 
721 	/***
722 	 * Return <code>true</code> if the given card should be painted as reversed
723 	 * card.
724 	 * 
725 	 * @param card
726 	 *          the card to draw.
727 	 * @return <code>true</code> if the given card should be painted as reversed
728 	 *         card.
729 	 */
730 	public boolean isMustBePaintedReversed(MCard card) {
731 		return card.reversed && Configuration.getBoolean("reverseArt", true);
732 	}
733 
734 	/***
735 	 * Return <code>true</code> if the given card should be painted entirely.
736 	 * 
737 	 * @param card
738 	 *          the card to draw.
739 	 * @return <code>true</code> if the given card should be painted entirely.
740 	 */
741 	public boolean isMustBePainted(MCard card) {
742 		return true;
743 	}
744 
745 	/***
746 	 * Is this zone is shared with all players.
747 	 * 
748 	 * @return <code>true</code> if this zone is shared with all players.
749 	 */
750 	public boolean isShared() {
751 		return false;
752 	}
753 
754 	public boolean isVisibleForYou() {
755 		return visibility.isVisibleForYou(getController());
756 	}
757 
758 	public boolean isVisibleForOpponent() {
759 		return visibility.isVisibleForOpponent(getController());
760 	}
761 
762 	public void increaseFor(Player player, VisibilityChange visibilityChange) {
763 		setVisibility(visibility.increaseFor(player, visibilityChange));
764 	}
765 
766 	public void decreaseFor(Player player, VisibilityChange visibilityChange) {
767 		setVisibility(visibility.decreaseFor(player, visibilityChange));
768 	}
769 
770 	public Visibility getVisibility() {
771 		return visibility;
772 	}
773 
774 	public void restoreVisibility() {
775 		if (previousVisibility != null) {
776 			restoreVisibility(previousVisibility);
777 		}
778 	}
779 
780 	public void restoreVisibility(Visibility visibility) {
781 		this.previousVisibility = null;
782 		setVisibility(visibility);
783 	}
784 
785 	/***
786 	 * The previous visibility of this zone.
787 	 */
788 	protected Visibility previousVisibility;
789 
790 	/***
791 	 * picture displayed in the panel
792 	 */
793 	protected Image backImage = null;
794 
795 	/***
796 	 * The picture's height
797 	 */
798 	private int picHeight;
799 
800 	/***
801 	 * The picture's width
802 	 */
803 	private int picWidth;
804 
805 	/***
806 	 * Is the background picture is drawn as mosaic. Otherwise, is centered.
807 	 */
808 	boolean doMosaic;
809 
810 	/***
811 	 * Are the images are reversed in this zone.
812 	 */
813 	protected boolean reverseImage;
814 
815 	/***
816 	 * Indicates all cards of this zone are returned or not. All cards coming into
817 	 * this zone would be returned or not depending this flag.
818 	 * 
819 	 * @since 0.80 cards are hidden by default
820 	 * @since 0.90 use Visibility class instead of boolean
821 	 */
822 	private Visibility visibility = Visibility.PUBLIC;
823 
824 	/***
825 	 * the parent scroll pane
826 	 */
827 	public final JScrollPane superPanel;
828 
829 	/***
830 	 * The zone identifier.
831 	 */
832 	private final int idZone;
833 
834 	/***
835 	 * The drag and drop starting point
836 	 */
837 	public Point mousePoint;
838 
839 	/***
840 	 * The drag and drop component.
841 	 */
842 	public MCard dragAndDropComponent = null;
843 
844 }