package jadex.bdi.examples.marsworld_classic.environment; import jadex.bdi.examples.marsworld_classic.AgentInfo; import jadex.bdi.examples.marsworld_classic.Environment; import jadex.bdi.examples.marsworld_classic.Homebase; import jadex.bdi.examples.marsworld_classic.Location; import jadex.bdi.examples.marsworld_classic.Target; import jadex.bdi.runtime.IBDIExternalAccess; import jadex.bdi.runtime.IBDIInternalAccess; import jadex.bridge.IComponentListener; import jadex.bridge.IComponentStep; import jadex.bridge.IInternalAccess; import jadex.commons.ChangeEvent; import jadex.commons.SGUI; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextPane; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.UIDefaults; import javax.swing.border.BevelBorder; import javax.swing.border.TitledBorder; /** * This class displays the GUI of the sample application. * It shows the Environment and the positions of the single agents. * Red dots denote the targets that the Sentry Agent is going to check for ore, * to call other Agents to reduce the amount at the targets. * <p/> * The Environment is simulated with methods - when the agents would * interact with the environment, they will call methods. */ public class MarsworldGui extends JFrame { //-------- constants --------- /** The image icons. */ private static UIDefaults icons = new UIDefaults(new Object[] { "background", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/mars.png"), "homebase", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/homebase.png"), "target", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/target.png"), "sentry", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/sentryagent.png"), "production", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/productionagent.png"), "carry", SGUI.makeIcon(MarsworldGui.class, "/jadex/bdi/examples/marsworld_classic/images/carryagent.png") }); //-------- attributes -------- /** The timer for continuously repainting the gui. */ protected Timer timer; /** The marsworld panel. */ protected JPanel map; //-------- constructors -------- /** * Create a new gui. */ public MarsworldGui(final IBDIExternalAccess agent) { super("Mars Environment - Agents collecting ore from targets..."); // // Read the images. // this.images = new HashMap(); // images.put(Environment.SENTRY_AGENT+"_original", loadImage(SENTRY_AGENT_ICON_PATH)); // images.put(Environment.PRODUCTION_AGENT+"_original", loadImage(PRODUCTION_AGENT_ICON_PATH)); // images.put(Environment.CARRY_AGENT+"_original", loadImage(CARRY_AGENT_ICON_PATH)); // // images.put("homebase", loadImage(HOMEBASE_PATH)); // images.put("target", loadImage(TARGET_ICON_PATH)); // images.put("background", loadImage(BACKGROUND_ICON_PATH)); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { agent.killComponent(); } }); agent.scheduleStep(new IComponentStep() { public Object execute(IInternalAccess ia) { IBDIInternalAccess bia = (IBDIInternalAccess)ia; bia.addComponentListener(new IComponentListener() { public void componentTerminating(ChangeEvent ae) { SwingUtilities.invokeLater(new Runnable() { public void run() { MarsworldGui.this.timer.stop(); MarsworldGui.this.dispose(); } }); } public void componentTerminated(ChangeEvent ae) { } }); return null; } }); // agent.addAgentListener(new IAgentListener() // { // public void agentTerminating(AgentEvent ae) // { // SwingUtilities.invokeLater(new Runnable() // { // public void run() // { // MarsworldGui.this.timer.stop(); // MarsworldGui.this.dispose(); // } // }); // } // // public void agentTerminated(AgentEvent ae) // { // } // }); agent.scheduleStep(new IComponentStep() { public Object execute(IInternalAccess ia) { IBDIInternalAccess bia = (IBDIInternalAccess)ia; final Environment env = (Environment)bia.getBeliefbase().getBelief("environment").getFact(); // On what thread? map = createMarsworldPanel(env); SwingUtilities.invokeLater(new Runnable() { public void run() { JLabel sentrylabel = new JLabel(": Sentry Agent", icons.getIcon("sentry"), JLabel.LEADING); JLabel prodname = new JLabel(": Production Agent", icons.getIcon("production"), JLabel.LEADING); JLabel carryname = new JLabel(": Carry Agent", icons.getIcon("carry"), JLabel.LEADING); JLabel homename = new JLabel(": Homebase", icons.getIcon("homebase"), JLabel.LEADING); JLabel targetname = new JLabel(": Target", icons.getIcon("target"), JLabel.LEADING); JTextPane helptext = new JTextPane(); helptext.setText("A group of robots is searching for ore on Mars...\n\n" + "This example was inspired by the book " + "'Multiagentsystems' written by Jaques Ferber."); helptext.setEnabled(false); helptext.setEditable(false); JPanel p1 = new JPanel(); p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); p1.add(homename); p1.add(sentrylabel); p1.add(prodname); p1.add(carryname); p1.add(targetname); //p1.setBounds(513, 224, 148, 186); p1.setBorder(BorderFactory.createTitledBorder(null, "Description", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null,null)); JPanel p2 = new JPanel(); p2.setLayout(new GridBagLayout()); p2.add(helptext, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); //p2.setBounds(515, 10, 143, 177); p2.setBorder(BorderFactory.createTitledBorder(null, "Mars Robots", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); Insets insets = new Insets(2, 4, 2, 4); JPanel content = new JPanel(); content.setLayout(new GridBagLayout()); content.add(map, new GridBagConstraints(0, 0, 1, 3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0)); content.add(p1, new GridBagConstraints(1, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0)); content.add(p2, new GridBagConstraints(1, 1, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0)); content.add(new JPanel(), new GridBagConstraints(1, 2, 1, 1, 0, 1, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0, 0)); content.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); content.setEnabled(false); p2.setMinimumSize(new Dimension((int)p1.getMinimumSize().getWidth(), 160)); p2.setPreferredSize(new Dimension((int)p1.getPreferredSize().getWidth(), 160)); setContentPane(content); setSize(600, 450); setLocation(SGUI.calculateMiddlePosition(MarsworldGui.this)); setVisible(true); // Continuously repaint the gui. timer = new Timer(100, new ActionListener() { public void actionPerformed(ActionEvent e) { MarsworldGui.this.map.repaint(); } }); timer.start(); } }); return null; } }); // Create the gui. // agent.getBeliefbase().getBeliefFact("environment").addResultListener(new SwingDefaultResultListener(MarsworldGui.this) // { // public void customResultAvailable(Object source, Object result) // { // Environment env = (Environment)result; // // map = createMarsworldPanel(env); // // JLabel sentrylabel = new JLabel(": Sentry Agent", icons.getIcon("sentry"), JLabel.LEADING); // JLabel prodname = new JLabel(": Production Agent", icons.getIcon("production"), JLabel.LEADING); // JLabel carryname = new JLabel(": Carry Agent", icons.getIcon("carry"), JLabel.LEADING); // JLabel homename = new JLabel(": Homebase", icons.getIcon("homebase"), JLabel.LEADING); // JLabel targetname = new JLabel(": Target", icons.getIcon("target"), JLabel.LEADING); // // JTextPane helptext = new JTextPane(); // helptext.setText("A group of robots is searching for ore on Mars...\n\n" + // "This example was inspired by the book " + // "'Multiagentsystems' written by Jaques Ferber."); // helptext.setEnabled(false); // helptext.setEditable(false); // // JPanel p1 = new JPanel(); // p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); // p1.add(homename); // p1.add(sentrylabel); // p1.add(prodname); // p1.add(carryname); // p1.add(targetname); // //p1.setBounds(513, 224, 148, 186); // p1.setBorder(BorderFactory.createTitledBorder(null, "Description", // TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null,null)); // // JPanel p2 = new JPanel(); // p2.setLayout(new GridBagLayout()); // p2.add(helptext, new GridBagConstraints(0, 0, 1, 1, 1, 0, // GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); // //p2.setBounds(515, 10, 143, 177); // p2.setBorder(BorderFactory.createTitledBorder(null, "Mars Robots", // TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null)); // // // Insets insets = new Insets(2, 4, 2, 4); // JPanel content = new JPanel(); // content.setLayout(new GridBagLayout()); // content.add(map, new GridBagConstraints(0, 0, 1, 3, 1, 1, // GridBagConstraints.CENTER, GridBagConstraints.BOTH, insets, 0, 0)); // content.add(p1, new GridBagConstraints(1, 0, 1, 1, 0, 0, // GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0)); // content.add(p2, new GridBagConstraints(1, 1, 1, 1, 0, 0, // GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0)); // content.add(new JPanel(), new GridBagConstraints(1, 2, 1, 1, 0, 1, // GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0, 0)); // content.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); // content.setEnabled(false); // // p2.setMinimumSize(new Dimension((int)p1.getMinimumSize().getWidth(), 160)); // p2.setPreferredSize(new Dimension((int)p1.getPreferredSize().getWidth(), 160)); // // setContentPane(content); // setSize(600, 450); // setLocation(SGUI.calculateMiddlePosition(MarsworldGui.this)); // setVisible(true); // // // Continuously repaint the gui. // timer = new Timer(100, new ActionListener() // { // public void actionPerformed(ActionEvent e) // { // MarsworldGui.this.map.repaint(); // } // }); // timer.start(); // } // }); } //-------- methods -------- /** * Create the map panel. * @return The created panel. */ protected JPanel createMarsworldPanel(final Environment env) { JPanel ret = new JPanel(true) { /** Copies of icons scaled to fit current window size. */ Map images = new HashMap(); /** The current scale factor. */ double scale; /** * Overridden paint method, * actual display of the items is done here. */ protected void paintComponent(Graphics g) { super.paintComponent(g); Rectangle bounds = getBounds(); // Paint background. Image image = ((ImageIcon)icons.getIcon("background")).getImage(); int w = image.getWidth(this); int h = image.getHeight(this); if(w>0 && h>0) { for(int y=0; y<bounds.height; y+=h) { for(int x=0; x<bounds.width; x+=w) { g.drawImage(image, x, y, this); } } } // Do scaling of images. double newscale = bounds.getWidth()/600.0; if(newscale!=scale) { scale = newscale; Image img = ((ImageIcon)icons.getIcon("sentry")).getImage(); int wx = (int)(img.getWidth(this)*scale); int wy = (int)(img.getHeight(this)*scale); if(wx>0 && wy>0) images.put(Environment.SENTRY_AGENT, img.getScaledInstance(wx, wy, Image.SCALE_DEFAULT)); img = ((ImageIcon)icons.getIcon("production")).getImage(); wx = (int)(img.getWidth(this)*scale); wy = (int)(img.getHeight(this)*scale); if(wx>0 && wy>0) images.put(Environment.PRODUCTION_AGENT, img.getScaledInstance(wx, wy, Image.SCALE_DEFAULT)); img = ((ImageIcon)icons.getIcon("carry")).getImage(); wx = (int)(img.getWidth(this)*scale); wy = (int)(img.getHeight(this)*scale); if(wx>0 && wy>0) images.put(Environment.CARRY_AGENT, img.getScaledInstance(wx, wy, Image.SCALE_DEFAULT)); } // Display the agents. AgentInfo[] infos = env.getAgentInfos(); for(int i=0; i < infos.length; i++) { Image img = (Image)images.get(infos[i].getType()); if(img!=null) { Location loc = infos[i].getLocation(); int x = (int)(loc.getX()*bounds.getWidth()); int y = (int)(loc.getY()*bounds.getHeight()); int wx = img.getWidth(this); int wy = img.getHeight(this); int vw = (int)(infos[i].getVision()*bounds.getWidth()); g.drawImage(img, x-wx/2, y-wy/2, this); g.setColor(new Color(250, 250, 30, 50)); g.fillOval(x-vw, y-vw, vw*2, vw*2); String txt = infos[i].getName(); g.setColor(Color.black); g.drawString(txt, x-wx/2, y+wy/2+12); // todo: do not use not absolute coords } } // Paint homebase. Homebase home = env.getHomebase(); Location loc = home.getLocation(); int x = (int)(loc.getX()*bounds.getWidth()); int y = (int)(loc.getY()*bounds.getHeight()); int wx = (int)(0.14*bounds.getWidth()); int wy = (int)(0.12*bounds.getWidth()); g.setColor(new Color(30,30,30,70)); g.fillRect(x-wx/2, y-wy/2, wx, wy); g.setColor(Color.black); g.drawRect(x-wx/2, y-wy/2, wx, wy); g.drawString("Collected ore: "+home.getOre(), x-wx/2, y+wy/2+12); SimpleDateFormat sdf = new SimpleDateFormat("mm:ss"); g.drawString("Remaining time: "+sdf.format(new Date(env.getHomebase() .getRemainingMissionTime())), x-wx/2, y+wy/2+22); /*Image img = (Image)images.get("homebase"); if(img!=null) { int wx = img.getWidth(this); int wy = img.getHeight(this); //System.out.println("wx: "+wx+" "+wy); g.drawImage(img, x-wx/2, y-wy/2, this); g.setColor(Color.black); }*/ // Display the targets. Target[] targets = env.getTargets(); for(int i = 0; i<targets.length; i++) { loc = targets[i].getLocation(); x = (int)(loc.getX()*bounds.getWidth()); y = (int)(loc.getY()*bounds.getHeight()); int wxy = Math.min(12, Math.max(1, (int)(0.02*bounds.getWidth()))); if((targets[i]).isMarked()) { g.setColor(Color.black); g.drawString("ore: "+targets[i].getOre(), x+20, y); // todo: do not use not absolute coords g.drawString("capacity:"+targets[i].getOreCapacity(), x+10, y+10); g.setColor(new Color(50, 50, 50, 150)); } else g.setColor(new Color(200, 0, 0, 150)); g.fillOval(x-wxy/2, y-wxy/2, wxy, wxy); } } }; //ret.setBounds(10, 10, 500, 400); ret.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); return ret; } }