@Override
  public void paintComponent(Graphics g) {
    if (world == null) {
      Color c = g.getColor();
      g.setColor(getParent().getBackground());
      g.fillRect(0, 0, getWidth(), getHeight());
      g.setColor(c);
      WorldHandler.getInstance().repainted();
      return;
    }

    // We need to sync, so that objects are not added and removed when we
    // traverse the list.
    // But, we only try to get the lock for a brief period to avoid
    // deadlocks. A deadlock could otherwise happen if a modal dialog is
    // created from the user code in one of the act() methods.
    // We could do the sync only on the paintObjects, but that would mean
    // that the background will be reset and no objects painted, resulting
    // in a slightly broken look, if the user code is sleeping (with
    // Thread.sleep).
    try {
      ReentrantReadWriteLock lock = WorldHandler.getInstance().getWorldLock();
      int timeout = WorldHandler.READ_LOCK_TIMEOUT;
      if (lock.readLock().tryLock(timeout, TimeUnit.MILLISECONDS)) {
        try {
          Insets insets = getInsets();
          Graphics2D g2 = (Graphics2D) g;
          g.translate(insets.left, insets.top);
          paintBackground(g2);
          paintObjects(g2);
          paintDraggedObject(g2);
          WorldVisitor.paintDebug(world, g2);
          g.translate(-insets.left, -insets.top);
        } finally {
          lock.readLock().unlock();
          WorldHandler.getInstance().repainted();
        }
      } else {
        WorldHandler.getInstance().repainted(); // we failed, but notify waiters anyway
        // (otherwise they keep waiting indefinitely...)
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
示例#2
0
  /**
   * Will save the currently selected image as the image of the class if OK is pressed.
   *
   * <p>If performed on the current world this will allow for previewing of the currently selected
   * image, but revert to the original background image of cancelled.
   *
   * @param e ignored
   */
  public void actionPerformed(ActionEvent e) {
    final World currentWorld = WorldHandler.getInstance().getWorld();
    // save the original background if possible
    final GreenfootImage originalBackground =
        ((currentWorld == null) ? null : WorldVisitor.getBackgroundImage(currentWorld));

    // allow the previewing if we are setting the image of the current world.
    ImageSelectionWatcher watcher = null;
    if (currentWorld != null
        && currentWorld.getClass().getName().equals(classView.getGClass().getQualifiedName())) {
      watcher =
          new ImageSelectionWatcher() {
            @Override
            public void imageSelected(final File imageFile) {
              if (imageFile != null) {
                Simulation.getInstance()
                    .runLater(
                        new Runnable() {
                          @Override
                          public void run() {
                            if (WorldHandler.getInstance().getWorld() == currentWorld) {
                              currentWorld.setBackground(imageFile.getAbsolutePath());
                            }
                          }
                        });
              }
            }
          };
    }

    // initialise our image library frame
    JFrame gfFrame = GreenfootMain.getInstance().getFrame();
    ImageLibFrame imageLibFrame = new ImageLibFrame(gfFrame, classView, watcher);
    DialogManager.centreDialog(imageLibFrame);
    imageLibFrame.setVisible(true);

    // set the image of the class to the selected file
    if (imageLibFrame.getResult() == ImageLibFrame.OK) {
      File currentImageFile = imageLibFrame.getSelectedImageFile();
      setClassImage(classView, gclassRole, currentImageFile);
      gfFrame.repaint();
    }
    // or if cancelled reset the world background to the original format
    // to avoid white screens or preview images being left there.
    else if (currentWorld != null && imageLibFrame.getResult() == ImageLibFrame.CANCEL) {
      Simulation.getInstance()
          .runLater(
              new Runnable() {
                @Override
                public void run() {
                  currentWorld.setBackground(originalBackground);
                }
              });
    }
  }
示例#3
0
  /**
   * Add an Actor to the world.
   *
   * @param object The new object to add.
   * @param x The x coordinate of the location where the object is added.
   * @param y The y coordinate of the location where the object is added.
   */
  public void addObject(Actor object, int x, int y) {
    if (object.world != null) {
      if (object.world == this) {
        return; // Actor is already in the world
      }
      object.world.removeObject(object);
    }

    objectsDisordered.add(object);
    addInPaintOrder(object);
    addInActOrder(object);

    // Note we must call this before adding the object to the collision checker,
    // so that the cached bounds are cleared:
    object.addToWorld(x, y, this);

    collisionChecker.addObject(object);
    object.addedToWorld(this);

    WorldHandler whInstance = WorldHandler.getInstance();
    if (whInstance != null) {
      WorldHandler.getInstance().objectAddedToWorld(object);
    }
  }
示例#4
0
  /**
   * Construct a new world. The size of the world (in number of cells) and the size of each cell (in
   * pixels) must be specified. This constructor allows the option of creating an unbounded world,
   * which actors can move outside the boundaries of.
   *
   * @param worldWidth The width of the world (in cells).
   * @param worldHeight The height of the world (in cells).
   * @param cellSize Size of a cell in pixels.
   * @param bounded Should actors be restricted to the world boundary?
   */
  public World(int worldWidth, int worldHeight, int cellSize, boolean bounded) {
    initialize(worldWidth, worldHeight, cellSize);
    this.isBounded = bounded;

    backgroundIsClassImage = true;
    setBackground(getClassImage());

    // Now, the WorldHandler must be informed of the new world, so it can be
    // used immediately. This is important for actors that are created by
    // the world constructor, if the actors are accessing the world in their
    // constructors (by using getWidth/Height for instance)
    final WorldHandler wHandler = WorldHandler.getInstance();
    if (wHandler != null) { // will be null when running unit tests.
      wHandler.setInitialisingWorld(this);
    }
  }
示例#5
0
  /** Needed for running in applets. */
  public static void initialize() {
    MouseMotionAdapter mma =
        new MouseMotionAdapter() {
          @Override
          public void mouseMoved(MouseEvent e) {
            LocationTracker.instance().move(e);
          }

          @Override
          public void mouseDragged(MouseEvent e) {}
        };
    MouseAdapter ma =
        new MouseAdapter() {
          @Override
          public void mouseClicked(MouseEvent e) {
            LocationTracker.instance().click(e);
          }
        };

    WorldCanvas canvas = WorldHandler.getInstance().getWorldCanvas();
    canvas.addMouseListener(ma);
    canvas.addMouseMotionListener(mma);
  }
 /** Repaints the world. */
 public void repaint() {
   WorldHandler.getInstance().repaint();
 }