Coverage Summary for Class: IslandFieldPanel (it.polimi.ingsw.Client.GUI.Panels)
| Class | Method, % | Branch, % | Line, % |
|---|---|---|---|
| IslandFieldPanel | 0% (0/8) | 0% (0/45) | 0% (0/151) |
| IslandFieldPanel$1 | 0% (0/1) | 0% (0/1) | |
| Total | 0% (0/9) | 0% (0/45) | 0% (0/152) |
1 package it.polimi.ingsw.Client.GUI.Panels; 2 3 import it.polimi.ingsw.Client.GUI.ActionType; 4 import it.polimi.ingsw.Client.GUI.CircleLayout; 5 import it.polimi.ingsw.Client.GUI.Components.NoEntryTileComponent; 6 import it.polimi.ingsw.Client.GUI.Components.StudentButton; 7 import it.polimi.ingsw.Client.GUI.Components.TowerComponent; 8 import it.polimi.ingsw.Client.GUI.Listeners.GUISocketListener; 9 import it.polimi.ingsw.Controller.Actions.MoveMotherNature; 10 import it.polimi.ingsw.Controller.Actions.MoveStudent; 11 import it.polimi.ingsw.Controller.Actions.PlayCharacterCard; 12 import it.polimi.ingsw.Controller.MoveDestination; 13 import it.polimi.ingsw.Misc.OptionalValue; 14 import it.polimi.ingsw.Model.Enums.PawnColour; 15 import it.polimi.ingsw.Model.IslandGroup; 16 import it.polimi.ingsw.Model.Model; 17 import it.polimi.ingsw.Network.SocketWrapper; 18 import it.polimi.ingsw.Server.Messages.Events.Requests.PlayerActionRequest; 19 20 import javax.swing.*; 21 import java.awt.*; 22 import java.awt.image.BufferedImage; 23 import java.io.IOException; 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.Map; 27 28 import static it.polimi.ingsw.Client.GUI.IconLoader.*; 29 30 /** 31 * Class necessary to print all the islands on GUI and perform all player's action that involve an island or islandGroup 32 */ 33 public class IslandFieldPanel extends JPanel { 34 /** 35 * Contains game's information 36 */ 37 private final Model model; 38 /** 39 * Contains GuiReader's information necessary to record user's requests during his turn 40 */ 41 private final GUISocketListener guiSocketListener; 42 /** 43 * Optional Integer containing student's index inside player's PlayerBoard's entrance (necessary when sending MoveStudentAction to Server) 44 */ 45 private OptionalValue<Integer> entrancePositionToMove = OptionalValue.empty(); 46 /** 47 * Optional Integer containing card's index inside game (0 to 2), it can be empty if no characterCard has been played 48 */ 49 private OptionalValue<Integer> selectedCharacterCard = OptionalValue.empty(); 50 /** 51 * Pawn from character card that player wants to move inside an island 52 */ 53 private OptionalValue<PawnColour> pawnFromCharacterCard = OptionalValue.empty(); 54 /** 55 * Status of islandField 56 */ 57 private ActionType actionType; 58 59 public IslandFieldPanel(Model model, SocketWrapper sw, GUISocketListener guiSocketListener) { 60 //set IslandFieldPanel's actionType basing on previous actions performed by current Player 61 this.setActionType(ActionType.MOVEMOTHERNATURE, OptionalValue.empty()); 62 this.setOpaque(true); 63 this.setBackground(new Color(105, 186, 233)); 64 this.setLayout(new CircleLayout()); 65 this.model = model; 66 this.guiSocketListener = guiSocketListener; 67 ArrayList<IslandGroup> islandGroups = new ArrayList<>(this.model.getMutableIslandField().getMutableGroups()); 68 //list containing islands images 69 ArrayList<ImageIcon> islandIcons = new ArrayList<>(Arrays.asList(Island1, Island2, Island3)); 70 ArrayList<JButton> islandButtons = new ArrayList<>(this.model.getMutableIslandField().getMutableGroups().size()); 71 IslandGroup motherNaturePosition = this.model.getMutableIslandField().getMutableMotherNaturePosition(); 72 //---DYNAMIC SIZING ISLANDS' IMAGES---- 73 int widthIsland = 160 + getDimBoost(islandGroups.size()); 74 int heightIsland = 130 + getDimBoost(islandGroups.size()); 75 int widthStudent = 35 + (getDimBoost(islandGroups.size()) / 5); 76 int heightStudent = 30 + (getDimBoost(islandGroups.size()) / 5); 77 int widthMotherNature = 35 + (getDimBoost(islandGroups.size()) / 5); 78 int heightMotherNature = 45 + (getDimBoost(islandGroups.size()) / 5); 79 int widthTower = 17 + (getDimBoost(islandGroups.size()) / 5); 80 int heightTower = 35 + (getDimBoost(islandGroups.size()) / 5); 81 Map<PawnColour, Integer> pawnCountMap; 82 for (int i = 0; i < islandGroups.size(); i++) { 83 //Map containing students and their count on the islandGroup 84 pawnCountMap = islandGroups.get(i).getStudentCount(); 85 //get and scale an island's image 86 Image img = islandIcons.get(i % 3).getImage(); 87 Image newImg = img.getScaledInstance(widthIsland, heightIsland, java.awt.Image.SCALE_SMOOTH); 88 ImageIcon icon = new ImageIcon(newImg); 89 //create a new button with the scaled images 90 JButton islandButton = new JButton(icon); 91 islandButtons.add(islandButton); 92 int finalI = i; 93 //add on-click action listener to islandGroup 94 islandButton.addActionListener(e -> { 95 // skip execution of the action if a previous action still hasn't been processed by the server 96 if (guiSocketListener.awaitingPlayerActionFeedback()) { 97 JOptionPane.showMessageDialog(null, "Please wait for the server to process your previous" + 98 "request before making a new one"); 99 return; 100 } 101 switch (this.actionType) { 102 case CHARACTERCARD -> { 103 PlayCharacterCard playCharacterCard; 104 //create playCharacterCard action 105 if (pawnFromCharacterCard.isPresent()) { 106 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 107 selectedCharacterCard.get(), OptionalValue.of(islandGroups.get(finalI).getMutableIslands().get(0).getId()) 108 , pawnFromCharacterCard, OptionalValue.empty()); 109 } else { 110 playCharacterCard = new PlayCharacterCard(model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), 111 selectedCharacterCard.get(), OptionalValue.of(islandGroups.get(finalI).getMutableIslands().get(0).getId()) 112 , OptionalValue.empty(), OptionalValue.empty()); 113 } 114 PlayerActionRequest playerActionRequest = new PlayerActionRequest(playCharacterCard); 115 this.guiSocketListener.savePlayerActionRequest(playCharacterCard); 116 try { 117 //send playCharacterCard request to Server 118 sw.sendMessage(playerActionRequest); 119 } catch (IOException ex) { 120 throw new RuntimeException(ex); 121 } 122 } 123 case MOVESTUDENT -> { 124 //create moveStudent action and its playerActionRequest 125 MoveStudent moveStudent = new MoveStudent(this.model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), entrancePositionToMove.get(), MoveDestination.toIsland(islandGroups.get(finalI).getId())); 126 PlayerActionRequest playerAction = new PlayerActionRequest(moveStudent); 127 //save moveStudentAction request inside guiReader 128 this.guiSocketListener.savePlayerActionRequest(moveStudent); 129 try { 130 sw.sendMessage(playerAction); 131 } catch (IOException ex) { 132 throw new RuntimeException(ex); 133 } 134 } 135 case MOVEMOTHERNATURE -> { 136 //create moveMotherNature action and its playerActionRequest 137 MoveMotherNature moveMotherNature = new MoveMotherNature(this.model.getMutableTurnOrder().getMutableCurrentPlayer().getId(), getMotherNatureSteps(islandGroups, islandGroups.get(finalI))); 138 PlayerActionRequest playerAction = new PlayerActionRequest(moveMotherNature); 139 //save moveStudentAction request inside guiReader 140 this.guiSocketListener.savePlayerActionRequest(moveMotherNature); 141 try { 142 sw.sendMessage(playerAction); 143 } catch (IOException ex) { 144 throw new RuntimeException(ex); 145 } 146 } 147 } 148 // reset the action listener to the base action 149 this.setActionType(ActionType.MOVEMOTHERNATURE, OptionalValue.empty()); 150 }); 151 //remove border and filled background from islandGroups' button 152 islandButton.setPreferredSize(new Dimension(widthIsland, heightIsland)); 153 islandButton.setBorderPainted(false); 154 islandButton.setContentAreaFilled(false); 155 islandButton.setFocusPainted(false); 156 islandButton.setOpaque(false); 157 islandButton.setLayout(new GridLayout(3, 1, -45, 0)); 158 for (PawnColour p : pawnCountMap.keySet()) { 159 if (pawnCountMap.get(p) > 0) { 160 //create new StudentButton 161 StudentButton studentButton = new StudentButton(p, pawnCountMap.get(p), true); 162 //scale StudentButton's image 163 newImg = iconToImage(studentButton.getIcon()).getScaledInstance((int) (widthStudent / 1.5), (int) (heightStudent / 1.5), java.awt.Image.SCALE_SMOOTH); 164 icon = new ImageIcon(newImg); 165 studentButton.setIcon(icon); 166 studentButton.setPreferredSize(new Dimension(widthStudent, heightStudent)); 167 islandButton.add(studentButton); 168 //add same IslandGroups' actionListeners to studentButtons 169 studentButton.addActionListener(e -> islandButton.doClick()); 170 } 171 } 172 //Draw motherNature only if it's present in IslandGroup 173 if (islandGroups.get(i).getMutableIslands().stream().anyMatch(island -> island.getId() == motherNaturePosition.getId())) { 174 //load and scale MotherNature's image 175 img = motherNature != null ? motherNature.getImage() : null; 176 assert img != null; 177 newImg = img.getScaledInstance(widthMotherNature, heightMotherNature, java.awt.Image.SCALE_SMOOTH); 178 icon = new ImageIcon(newImg); 179 //create motherNature's label 180 JLabel motherNatureLabel = new JLabel(icon); 181 motherNatureLabel.setPreferredSize(new Dimension(widthMotherNature, heightMotherNature)); 182 //add motherNature to islandGroup's button 183 islandButton.add(motherNatureLabel); 184 } 185 //Drawing eventual tower 186 if (islandGroups.get(i).getTowerColour().isPresent()) { 187 //scale and set tower's image 188 TowerComponent tower = new TowerComponent(islandGroups.get(i).getTowerColour().get(), islandGroups.get(i).getTowerCount()); 189 newImg = iconToImage(tower.getIcon()).getScaledInstance(widthTower, heightTower, java.awt.Image.SCALE_SMOOTH); 190 icon = new ImageIcon(newImg); 191 tower.setIcon(icon); 192 //remove borders and filled background from tower's image 193 tower.setBorderPainted(false); 194 tower.setContentAreaFilled(false); 195 tower.setFocusPainted(false); 196 tower.setPreferredSize(new Dimension(widthTower, heightTower)); 197 tower.addActionListener(e -> islandButton.doClick()); 198 //add tower's image to IslandGroup's button 199 islandButton.add(tower); 200 } 201 //Drawing eventual NoEntryTile 202 if (islandGroups.get(i).getMutableNoEntryTiles().size() > 0) { 203 //scale and set NoEntryTile's image 204 NoEntryTileComponent noEntryTileComponent = new NoEntryTileComponent(islandGroups.get(i).getMutableNoEntryTiles().size()); 205 newImg = iconToImage(noEntryTileComponent.getIcon()).getScaledInstance(40, 35, java.awt.Image.SCALE_SMOOTH); 206 icon = new ImageIcon(newImg); 207 noEntryTileComponent.setIcon(icon); 208 noEntryTileComponent.setPreferredSize(new Dimension(40, 35)); 209 //add NoEntryTile component to island's button 210 islandButton.add(noEntryTileComponent); 211 //add same IslandGroups' actionListeners to noEntryTileComponent 212 noEntryTileComponent.addActionListener(e -> islandButton.doClick()); 213 214 } 215 islandButton.setToolTipText("<html><p width = 100px>ISLAND GROUP #" + islandGroups.get(i).getId() + "<br>" + 216 "STUDENTS:<br>" + 217 "RED:" + pawnCountMap.get(PawnColour.RED) + "<br>" + 218 "BLUE:" + pawnCountMap.get(PawnColour.BLUE) + "<br>" + 219 "YELLOW:" + pawnCountMap.get(PawnColour.YELLOW) + "<br>" + 220 "GREEN:" + pawnCountMap.get(PawnColour.GREEN) + "<br>" + 221 "PINK:" + pawnCountMap.get(PawnColour.PINK) + "</p></html>"); 222 ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE); 223 this.add(islandButton); 224 } 225 } 226 227 /** 228 * Method used for setting IslandFieldPanel's actionType from external panels 229 * 230 * @param actionType actionType that IslandFieldPanel will assume 231 * @param toRemove PlayerBoard's entrance's index containing the student to move (Optional.empty if action type is not MOVESTUDENT) 232 */ 233 public void setActionType(ActionType actionType, OptionalValue<Integer> toRemove) { 234 if (actionType == ActionType.MOVESTUDENT) { 235 this.actionType = actionType; 236 this.entrancePositionToMove = toRemove; 237 return; 238 } 239 this.actionType = actionType; 240 } 241 242 /** 243 * Support method used to increase islands' dimensions when the amount of IslandGroups decreases 244 * 245 * @param IslandsNumbers number of IslandGroups to show 246 * @return boost to add to original icons' dimensions 247 */ 248 private int getDimBoost(int IslandsNumbers) { 249 return switch (IslandsNumbers) { 250 case 12 -> 0; 251 case 11 -> 10; 252 case 10 -> 20; 253 case 9 -> 30; 254 case 8 -> 40; 255 case 7 -> 50; 256 case 6 -> 60; 257 case 5, default -> 70; 258 }; 259 } 260 261 /** 262 * Support method used to calculate difference between clicked islandGroup by user and actual motherNature's islandGroup 263 * 264 * @param islandGroups list of islandGroups present in game 265 * @param destinationIsland IslandGroup that has been clicked by player 266 * @return number of steps that motherNature should perform to reach wished IslandGroup 267 */ 268 private int getMotherNatureSteps(ArrayList<IslandGroup> islandGroups, IslandGroup destinationIsland) { 269 //get motherNature's islandGroup's index 270 int motherNatureIndex = islandGroups.indexOf(model.getMutableIslandField().getMutableMotherNaturePosition()); 271 int steps = 1; 272 //repeat until found islandGroup with same id as the one clicked by user 273 while (!islandGroups.get((motherNatureIndex + steps) % islandGroups.size()).equals(destinationIsland)) { 274 steps = steps + 1; 275 } 276 return steps; 277 } 278 279 /** 280 * Support method to extract Image from icon 281 * 282 * @param icon icon to convert 283 * @return image represented by icon 284 */ 285 private Image iconToImage(Icon icon) { 286 if (icon instanceof ImageIcon) { 287 return ((ImageIcon) icon).getImage(); 288 } else { 289 int w = icon.getIconWidth(); 290 int h = icon.getIconHeight(); 291 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 292 GraphicsDevice gd = ge.getDefaultScreenDevice(); 293 GraphicsConfiguration gc = gd.getDefaultConfiguration(); 294 BufferedImage image = gc.createCompatibleImage(w, h); 295 Graphics2D g = image.createGraphics(); 296 icon.paintIcon(null, g, 0, 0); 297 g.dispose(); 298 return image; 299 } 300 } 301 302 /** 303 * Basing on CharacterCard that has been activated, this method setup IslandFieldPanel for send the right PlayerActionRequest to Server 304 * 305 * @param actionType ActionType that IslandFieldPanel is going to switch to 306 * @param card card's index inside game 307 * @param toMove possible pawn to move 308 */ 309 public void setCharacterCardAction(ActionType actionType, OptionalValue<Integer> card, OptionalValue<PawnColour> toMove) { 310 this.actionType = actionType; 311 if (card.isEmpty()) return; 312 this.selectedCharacterCard = card; 313 if (toMove.isEmpty()) return; 314 this.pawnFromCharacterCard = toMove; 315 } 316 }