Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: current
    • Fix Version/s: Release 1.0
    • Component/s: xjc wizard
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      6

      Description

      Currently, the wizard doesn't display any progress information at
      all while compiling the schema. It isn't unusual for a compilation
      to take several minutes, so it could be confusing for users if there
      isn't a progress meter or a frame showing the console output.

        Activity

        Hide
        kirillcool added a comment -

        The glass pane of the wizard has been majorly rewritten. It now uses
        double-buffering technique for efficient animation. The animation effect scrolls
        a patch of whitish lines down the screen in loop. When the glass pane is shown
        (setVisible(boolean) was overriden), a snapshot of the underlying window is
        taken and an animation thread is created and run:
        public void setVisible(boolean isVisible) {
        if (isVisible)

        { // reset owner snapshot this.ownerSnapshot = null; this.currHighLightRow = -HIGHLIGHT_ROW_SPAN; this.animator = new GlassPaneThread(this, 20); this.animator.start(); }

        else {
        if (this.animator != null)

        { this.animator.markStopped(); this.animator = null; }

        }
        super.setVisible(isVisible);
        }

        The animator thread calls back the iteration() function of the glass pane,
        prompting the refresh process:
        public void run() {
        this.toStop = false;
        while (!this.isMarkedStopped()) {
        this.glassPane.iteration();
        try

        { Thread.sleep(this.sleepTime); }

        catch (InterruptedException e) {
        }
        }
        }

        The isMarkedStopped() checks a boolean flag that is set in markStopped()
        function when glass pane is called on setVisible(false). Both these functions
        are synchronized.

        The iteration() function of the glass pane updates the highlight band position
        and then performs the actual drawing:
        // get the offscreen buffer
        Graphics2D graphics = (Graphics2D) this.offscreenImage.getGraphics();
        // draw the owner snapshot on it
        graphics.drawImage(this.ownerSnapshot, 0, 0, null);
        // paint the glass pane image on it
        if (this.isVisible())
        this.paintComponent(graphics);
        // draw back on the owner graphics
        this.owner.getGraphics().drawImage(this.offscreenImage, 0, 0, null);

        The ownerSnapshot contains the snapshot of the frozen window when it activated
        the glass pane. First it is drawn on offscreenImage, then we paint the glass
        pane itself and then we paint back the offscreenImage on the frozen window. This
        achieves much better performance than simply calling the owner to redraw itself.

        The snapshot is performed once after the setVisible(true) call:
        if (!this.owner.getTopLevelAncestor().isVisible())
        return;

        if (this.ownerSnapshot == null)

        { int width = this.owner.getWidth(); int height = this.owner.getHeight(); this.ownerSnapshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); this.offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); this.owner.paintAll(this.ownerSnapshot.getGraphics()); }

        In addition, the glass pane now allows showing a dynamic message (is updated at
        every iteration). To set the message, call setMessage(String), which is
        synchronized (as well as paintComponent). This message will be shown at the
        bottom of the screen on darkened background which is not affected by the
        highlight patch.

        Throughout the whole process of generation (generating classes, compiling,
        loading, processing), the glass pane is updated with the corresponding status.

        Show
        kirillcool added a comment - The glass pane of the wizard has been majorly rewritten. It now uses double-buffering technique for efficient animation. The animation effect scrolls a patch of whitish lines down the screen in loop. When the glass pane is shown (setVisible(boolean) was overriden), a snapshot of the underlying window is taken and an animation thread is created and run: public void setVisible(boolean isVisible) { if (isVisible) { // reset owner snapshot this.ownerSnapshot = null; this.currHighLightRow = -HIGHLIGHT_ROW_SPAN; this.animator = new GlassPaneThread(this, 20); this.animator.start(); } else { if (this.animator != null) { this.animator.markStopped(); this.animator = null; } } super.setVisible(isVisible); } The animator thread calls back the iteration() function of the glass pane, prompting the refresh process: public void run() { this.toStop = false; while (!this.isMarkedStopped()) { this.glassPane.iteration(); try { Thread.sleep(this.sleepTime); } catch (InterruptedException e) { } } } The isMarkedStopped() checks a boolean flag that is set in markStopped() function when glass pane is called on setVisible(false). Both these functions are synchronized. The iteration() function of the glass pane updates the highlight band position and then performs the actual drawing: // get the offscreen buffer Graphics2D graphics = (Graphics2D) this.offscreenImage.getGraphics(); // draw the owner snapshot on it graphics.drawImage(this.ownerSnapshot, 0, 0, null); // paint the glass pane image on it if (this.isVisible()) this.paintComponent(graphics); // draw back on the owner graphics this.owner.getGraphics().drawImage(this.offscreenImage, 0, 0, null); The ownerSnapshot contains the snapshot of the frozen window when it activated the glass pane. First it is drawn on offscreenImage, then we paint the glass pane itself and then we paint back the offscreenImage on the frozen window. This achieves much better performance than simply calling the owner to redraw itself. The snapshot is performed once after the setVisible(true) call: if (!this.owner.getTopLevelAncestor().isVisible()) return; if (this.ownerSnapshot == null) { int width = this.owner.getWidth(); int height = this.owner.getHeight(); this.ownerSnapshot = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); this.offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); this.owner.paintAll(this.ownerSnapshot.getGraphics()); } In addition, the glass pane now allows showing a dynamic message (is updated at every iteration). To set the message, call setMessage(String), which is synchronized (as well as paintComponent). This message will be shown at the bottom of the screen on darkened background which is not affected by the highlight patch. Throughout the whole process of generation (generating classes, compiling, loading, processing), the glass pane is updated with the corresponding status.

          People

          • Assignee:
            kirillcool
            Reporter:
            ryan_shoemaker
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: